Monthly Archives: June 2013


Getting Started

  1. Is Subterfuge free for download?
  2. What Operating Systems is Subterfuge built for?
  3. What dependencies does Subterfuge require?
  4. Help! I’m having browser issues
  5. How can I report a new bug?
  6. I see lots of errors in the terminal window what am I doing wrong?
  7. How do I run Subterfuge as an externally navigable server?
  8. How do I uninstall Subterfuge?
  9. What kind of support is there
  10. How can I contact you?

For issues not covered here see: Troubleshooting

1. Is Subterfuge free for download?

Screen Shot 2013-03-14 at 4.39.59 PM

2. What Operating Systems is Subterfuge built for?

Screen Shot 2013-03-14 at 4.40.13 PM

3. What dependencies does Subterfuge require?

Screen Shot 2013-03-14 at 4.40.23 PM

4. Help! I’m having browser issues 

Screen Shot 2013-03-14 at 4.40.34 PM

5. How can I report a new bug?

Screen Shot 2013-03-14 at 4.40.42 PM

6. I see lots of errors in the terminal window what am I doing wrong? 

Screen Shot 2013-03-14 at 4.40.54 PM

7. How do I run Subterfuge as an externally navigable server? 

Screen Shot 2013-03-14 at 4.41.05 PM

8. How do I uninstall Subterfuge?Screen Shot 2013-03-14 at 4.41.13 PM

9. What kind of support is there?

Screen Shot 2013-03-14 at 4.41.24 PM

10. How can I contact you?

Screen Shot 2013-03-14 at 4.41.37 PM

Subterfuge Documentation


Enter Subterfuge, a Framework to take the arcane art of Man-in-the-Middle Attacks and make it as simple as point and shoot. Subterfuge demonstrates vulnerabilities in the ARP Protocol by harvesting credentials that go across the network and even exploiting machines by injecting malicious code directly into their browsing sessions.

How to use this Document

Reading through this entire document may be tedious, and will certainly deluge you in information you may not have any desire in knowing. To aid in your perusal below is a short summary of each section, so that you know where to go in order to get the information that you came for:


This section is for those of you who are interested in where the Subterfuge Project came from, why it exists, and what we hope to accomplish. The introduction focuses on the risks of MITM attacks, the programmatic structure of Subterfuge, and the community buoying it up.

                     The Attack

                     The next portion of the documentation gets right into running Subterfuge.  It starts with the most basic usage, and moves on to basic module usage as well as settings and configuration options. 


                     Extending the attack through Plugins and Modules. This section takes an in depth look at how Subterfuge can really work for you. 


                     The most pervasive problem with hacking tools is that they never quite work right for everyone. Between the plethora of different builds we operate, and the differing conditions of each attack breaking things is almost inevitable. Here’s what to do to fix it.

                     Third-Party Tool Integration

                     Subterfuge doesn’t exist in a vacuum, and we didn’t design it that way. Here we discuss the external tools that the project leverages, and how they interact with the framework to make the penetration testing experience more fluid and dynamic.

                     Extending Subterfuge

                     Making Subterfuge work for you is easy. This portion of the documentation talks about just how to get deeper functionality out of the system. 

                     Contributing to the Project

                     Community Support for the project has been great so far. If you would like to contribute in some manner then this section might merit your perusal. 


                     Other stuff. See for yourself.

Installing Subterfuge on Kali Linux


This is an install of Subterfuge Version 1.0. It takes place on a Virtual Box VM running Kali Linux 1.0.2. Packages were updated by running:

apt-get update
apt-get dist-upgrade

Step 1: Download the Code


Step 2: Install Subterfuge

dpkg -i subterfuge_1.0-1_all.deb

Step 3: If the installer errors due to dependency issues install them along with Subterfuge

apt-get update && apt-get -f install

Because Subterfuge has deprecated its old installer and switched over to the Debian packaging system there should no longer be any chance that installing Subterfuge will break your existing packages!

Hopefully this install worked out for you all. Post in the comments if your issues still seem to persist, and we’ll try to help you work it out.

SANS Holiday Challenge 2012

The Year Without a Santa… Hack

Matthew Toussain (0sm0s1z)
Geoffrey Pamerleau (d0m3$t1c)
Christopher Shields (r00t0v3r1d3)

Thank you to Tim Medin, Ed Skoudis, and Tom Hessman for a fun Friday evening.

Guiding Questions

Where did you find the remainder of Snow Miser’s Zone 1 URL?

Snow Miser failed to utilize appropriate OPSEC measures. As such the remainder of his Zone 1 could be found in the reflection on his “Ice Cold Drink”.

What is the key you used with steghide to extract Snow Miser’s Zone 2 URL? Where did you find the key?

The key used was “IceIceBaby!”
I was located in the meta data of the off.jpg image

On Snow Miser’s Zone 3 page, why is using the same key multiple times a bad idea?

Using the same keys multiple times is a bad idea because if an attacker can deduce the key for one encryption they can use it to decrypt all messages, which were encrypted with the reused key. Since we had access to a combination of known plaintext and ciphertext we could determine the key used and then apply it to the encrypted Zone 4 URL.

What was the coding error in Zone 4 of Heat Miser’s site that allowed you to find the URL for Zone 5?

The PHP Header Redirect failed to specify exit() in order to force stop the execution of the remainder of the page.

How did you manipulate the cookie to get to Zone 5 of Heat Miser’s Control System?

Manipulating the UID cookie to the md5 of 1 allowed access to Heat Miser’s Zone 5 Control System.

Now for the real meat of the writeup:

Heat Miser – Write up:

Zone 0:

Viewing the source code gives us the KEY –> 1732bcff12e6550ff9ea44d594001418


Zone 1:

The solution to Zone 1 was simple once you read the HMISER Note on the Zone 0 page:

We had a security concern where the Zone 1 URL ended up in search engine results. We added a file to prevent the search engines from caching these pages. The system is now secure and no unauthorized users have access to the URL.

Search engines use the Robot Exclusion Standard to gain information on what pages on any given website are publically viewable. Participating Web Crawlers check for the existence of a robots.txt file to determine the pages on the web site to exclude.

For our purposes, browsing to this file yields the URL of Heat Miser’s Zone 1 Controller:

Viewing the source gives us the KEY –> d8c94233daef256c42bb95bd61382e02


Zone 2:

The HIMSER Note on the Zone 1 page indicates that a link to Zone 2 existed at one time. Viewing the page source reveals the following comment:

<!-- redacted, too many people clicked on the link and took it offline
<a href="/zone-2-761EBBCF-099F-4DB0-B63F-9ADC61825D49">Zone 2</a>

Copying the zone information to the URL bar grants us access to Zone 2. Viewing the source code gives us the KEY –> ef963731de7e886226fe4a6a6c2971f1


Zone 3:

Heat Miser gives us the first portion of the link to get to Zone 3:


But to get to Zone 3 we need a little bit more information. It helps to stalk our targets! @sn0w_m1s3r gives us our first clue:

“Another oops. Brilliant move @h34t_m1s3r. Your OS X term is semi-transparent, hot head! Oh, & u don’t need Metasploit for any of these zones”

Following the breadcrumbs brings us to a tweet by @h34t_m1s3r:

“Hot dog! We have some toolz ready in case we need them later

If we analyze the image we can see the URL bar of Heat Miser’s browser through his transparent terminal. Opening the image in Gimp and adjusting the brightness and levels makes the image easier to read. Putting the pieces together gives us the new link:


Viewing the source code gives us the KEY –> 0d524fb8d8f9f88eb9da5b286661a824


Zone 4:

Zone 3 gives us the link to Zone 4 right off the bat! Accessing the Control System on the other hand is not quite so straightforward. Browsing to the supplied link executes a PHP Header redirect sending the browser to noaccess.php. Snow Miser gives us a hint:


What he is referring to is an open redirect in Heat Miser’s code. The PHP code causing the redirect looks something like the following:


The problem results because Heat Miser failed to call exit() after the redirect. This means that the server continues to execute the rest of the code on the page. To access this code all that we need to do is navigate to the site with a browser that does not support PHP redirection. For our purposes we used Netcat:

nc 80

This pulls down the source and reveals the link to Zone 5 as well as the KEY –> e3ae414e6d428c3b0c7cff03783e305f


Zone 5:

Zone 5 is interesting… On first inspection it appears much the same as zone four, except for one major difference: cookies. Zone 5 uses cookies to authenticate a user before allowing access to the weather controller.  Inspecting the cookie by pasting javascript:alert(document.cookie) into the URL bar shows us what it is set to: UID=b8c37e33defde51cf91e1e03e51657da reversing the hash (we used reveals that the UID is set to the md5 of 1001. That is a standard user identification number under Linux systems. Using that schema the next step was to try changing the UID in order to privilege escalate. We originally tried 0 for root, but it was using a UID of 1 that gave us access:

javascript:void(document.cookie=”UID= c4ca4238a0b923820dcc509a6f75849b”)

We changed our cookie with the above URL injection, reloaded the page (Zone 5 not noaccess.php), and presto we’re in!

Viewing source gives us the KEY –> f478c549e37fa33467241d847f862e6f

Heat Miser Answers at a Glance:

Screen Shot 2013-06-24 at 6.38.19 PM


Snow Miser – Write up:

­­­­ Zone 0:

Viewing the source code gives us the KEY –> 1732bcff12e6550ff9ea44d594001418


Zone 1:

Snow Miser’s a bit too fond of his ice cold drinks! Someone should give tell him to use proper OPSEC because the link to his zone 1 URL is in the reflection on his glass. Flipping it horizontal and 180 degrees gives us the rest of the URL for Zone 1:


Viewing the source code gives us the KEY –> 38bef0b61ba8edda377b626fe6708bfa


­­­­Zone 2:

Snow Miser let’s us know that because of one of his snow-minions we have to do image analysis in order to get the URL for Zone 2. Step one is finding the image. The first trick is to get an image with a format that Steghide can use. Viewing the source to pull page resources shows us on.png, but if we click on the disable button. The resource changes to: off.jpg. Downloading the image and using exiftool on us gives us some notable metadata namely the passphrase:


The next step is to run steghide with the extract switch while specifying the above as the passphrase. Welcome to Zone 2!


Viewing the source code gives us the KEY –> b8231c2bac801b54f732cfbdcd7e47b7


Zone 3:

One of Snow Miser’s minions has been running rampant and messing up the Global Chiller Control System links! In order to facilitate access Snow Miser provides the first part of the Zone 3 URL for his authorized minions:


 Additionally, his fraternal nemesis has left us a whopper on Twitter:

“@h34t_m1s3r: Uh oh, @sn0w_m1s3r left his Ice Cream Sandwich Android phone at my volcano. Data extraction complete.”

From here we get the android file system of Snow Miser’s phone, jackpot! We check the browser cache with some Terminal Fu to see if he’s accessed the Chiller System from his phone:

“strings data/ | grep zone-3-EAB6B031”

Yay! Link:


Viewing the source gives us the KEY –> 08ba610172aade5d1c8ea738013a2e99


Zone 4:

Zone 3 Control System… almost there right? Look out, incoming crypto! Fortunately, Snow is kind enough to give us samples of his plaintext and ciphertext, “for verification purposes” of course:

Old Plaintext:


Old Ciphertext


New Ciphertext: 20d916c6c29ee54343e81ff1b14c1372650cbf19998f51b5c51bf66f49ec62184034a94fc9198fa9179849

Doing some careful eyeballing gives us some clues on how to start:

Old Plaintext:             z    o   n   e   –   4   –
Old Ciphertext:          20 d9 16 c6 c2 9e e5
New Ciphertext:        20 d9 16 c6 c2 9e e5

Let’s examine what we know. The ciphertext is exactly twice as long as the plaintext, and both sets of plaintext (the URLs) must start with zone-4-. The first 14 characters of both new and old ciphertexts were identical which aligns with the “zone-4-“. This gave us the hint that the same key was used to encrypt both the original and the old URL’s. On to the Python!

Our less then elegant solution……….

“knownpt = "zone-4-F7677DA8-3D77-11E2-BB65-E4BF6188709B"

knownct = "0x20 0xd9 0x16 0xc6 0xc2 0x9e 0xe5 0x3c 0x30 0xea 0x1e 0xff 0xc6 0x3b 0x1c 0x72 0x14 0x7e 0xb8 0x6b 0x99 0x8a 0x25 0xc0 0xcf 0x1b 0xf6 0x69 0x39 0xe8 0x62 0x1b 0x31 0x32 0xd8 0x3a 0xbb 0x16 0x83 0xdf 0x61 0x92 0x38"

knownctarray = knownct.split(" ")

unknownct = "0x20 0xd9 0x16 0xc6 0xc2 0x9e 0xe5 0x3c 0x30 0xea 0x1e 0xff 0xc6 0x3b 0x1c 0x72 0x14 0x7e 0xb8 0x6b 0x99 0x8a 0x25 0xc0 0xcf 0x1b 0xf6 0x69 0x39 0xe8 0x62 0x1b 0x31 0x32 0xd8 0x3a 0xbb 0x16 0x83 0xdf 0x61 0x92 0x38"

keyarray = unknownct.split(" ")

cttobreak = "0x20 0xd9 0x16 0xc6 0xc2 0x9e 0xe5 0x43 0x43 0xe8 0x1f 0xf1 0xb1 0x4c 0x13 0x72 0x65 0x0c 0xbf 0x19 0x99 0x8f 0x51 0xb5 0xc5 0x1b 0xf6 0x6f 0x49 0xec 0x62 0x18 0x40 0x34 0xa9 0x4f 0xc9 0x19 0x8f 0xa9 0x17 0x98 0x49"

cttobreakarray=cttobreak.split(" ")

count = 0
for c in knownpt:
   for i in range (256):
      result = hex(ord(c)^i)
      if result == knownctarray[count]:
         #print hex(i)
         #print result
   count = count + 1
answer = ""
for i in range(43):
print "The URL for Zone 4 is: " + answer

Since the length of the cipher text is exactly twice that of the plaintext we determined that Snow Miser took the ASCII of the URL and converted each character to hexadecimal. The plaintext was then encrypted using a byte-wise XOR with a one time pad (the key). XOR was assumed to be the operation performed on the two sets of bytes because an encryption algorithm is not a true encryption algorithm without XOR…right? Normally, this type of encryption would be impossible to reverse; luckily for us we were provided with a plaintext/ciphertext pairing. The python program allowed us to determine the key byte-by-byte. Once we had the key we could easily decrypt the posted ciphertext to obtain the Zone 4 URL we desired. The mess of Python above spits out the Zone 4 URL:


Viewing the source gives us the KEY –> de32b158f102a60aba7de3ee8d5d265a

Zone 5:

Zone 5 is top secret! Fortunately, the link to its URL can be found in the source code:


Additionally, Snow gives us the hint that the code is now part of an svn package management system (version 1.7). This means that we can pull down the Subversion Sqlite database by browsing to it:


Heat Miser gives us a clue on what to do from here by linking to a blog post by Tim Medin entitled: “All your svn are belong to us”


We open the database, check the table definitions (schema) to give ourselves a reference point, and grab the NODES:

sqlite3 wc.db
select local_relpath, ".svn/pristine/" || substr(checksum,7,2) || "/" || substr(checksum,7) || ".svn-base" as alpha from NODES;

This spits out the golden egg:


The next step is get to the Zone 5 Controller. Execute the following:

wget –O -

wget –O -

This returns the following output:

$accessallowed = FALSE;
$content = "<h1>Access Denied</h1>\n<!-- current server time is ".date('Y-m-d H:i').' -->';


function generate_otp($time) {
$pass = sha1("$time 7998f77a7dc74f182a76219d7ee58db38be3841c");

function verify_otp($inpass) {
    // passwords are valid for up to 3 minutes
    // don't forget to use the server time (see the noaccess.php page)

$validstamps = array(
    date('Y-m-d H:i', strtotime('+1 minute')), // added just in case the time sync is off
date('Y-m-d H:i'),
date('Y-m-d H:i', strtotime('-1 minute')),
date('Y-m-d H:i', strtotime('-2 minute')),

foreach ($validstamps as $stamp) {
   if (strtolower($inpass) == generate_otp($stamp))

        return TRUE;
return FALSE;

if ((array_key_exists('otp', $_POST) && verify_otp($_POST['otp'])) || (array_key_exists('otp', $_COOKIE) && verify_otp($_COOKIE['otp']))) {
    setcookie('otp', generate_otp(date('Y-m-d H:i')));
} else {
header( 'Location: noaccess.php' );

$accessallowed = TRUE;

Uh oh! Access Denied, but we did manage to get some of the server side code pertaining to the Controller’s Page. Examining it gives us insight. We need to hand the server a password in order to gain access to the Controller. Fortunately, noaccess.php tells us how to make a time based password, but to do that we need to get ahold of the server time. The server time can be found in the source of noaccess.php. Back to the Python!

import hashlib
salt = 7998f77a7dc74f182a76219d7ee58db38be3841c
hashlib.sha1(“2012-12-16 20:17 ” + seed).hexdigest() 

Output:           f614951b7f741dbbead5d47d285fcc47b1e63aec

We now have a three minute window to take the output and authenticate into the Zone 5 Controller from the Zone 4 page. That’s it!

Viewing the source gives us the KEY –> 3ab1c5fa327343721bc798f116be8dc6

Snow Miser Answers at a Glance:

Screen Shot 2013-06-24 at 7.03.55 PM


And that’s it! Hope you all enjoyed the writeup.

On Blogging

Thus far I’ve only ever blogged about Subterfuge extensively. While I have been focusing on Subterfuge development over the past year, it hasn’t been my only pursuit. I figured I’d open things up a bit and start adding additional content to the site. Things to expect to see here:

  • Subterfuge Stuff (of course)
  • General Security Topics
  • Red Team Tactics
  • Other Projects I’m Working On
  • Encounters of a Third Kind (interesting security related things I run into on the net)

To start things off I figured I’d post my writeup for the 2012 SANS Holiday Hack. The writeup is a bit belated, but it was a fun little competition. Link