Installing Torbutton

I almost thought a Torbutton install post was pointless, ailment until I realized a lot of people still manage to screw it up.
Somehow. I have no idea exactly how…
Anyways, onward! I will assume you have read and and gotten TOR working for you.

The following works on any platform once TOR/Vidalia is installed. TORbutton makes irreversable changes to Firefox, so you should install Firefox specifically for this!

In Firefox navigate to

Click the install link near bottom of page. The one that reads “Expert Install” “Install from this page”
Allow it to do voodoo magic.

torbutton install

torbutton install

Once Torbutton installs and Firefox restarts, navigate to

It Works!

It Works!

If you are seeing this, it clearly worked and you are good to go! Now onward we go!


Installing TOR On Ubuntu Linux

Seeing as Ubuntu is one of the most commonly used Linux distros around, tadalafil and because I cannot be bothered getting a Fedora .iso, and because these instructions work fine for Debian also, here goes! (yes, in the images I am using BT5, which is basically Ubuntu)

To get your distribution name, the command “lsb_release -c” will tell you. This is important.

First off, sovaldi sale add the appropriate repository to your /etc/apt/sources.list file.

Essentially this command:
sudo echo “deb <DISTRIBUTION> main” >> /etc/apt/sources.list

Adding TOR repo

Adding TOR repo

Next, capsule we import the tor project GPG keys. I advise being root when doing this.

gpg –keyserver –recv 886DDD89
gpg –export A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89 | sudo apt-key add –

Adding GPG keys

Adding GPG keys

sudo apt-get update to refresh your package lists…

Update Package List

Update Package List

Now we install the torproject keyring.

apt-get install

keyring install

Installing Keyring

Install TOR itself and the Vidalia GUI… It will prompt to add a user to the group so select your username!!!

apt-get install vidalia tor polipo

Installing TOR

Installing TOR

Now, we check is Vidalia working OK or are we already fscked. By running it.

Vidalia Works

Vidalia Works

If it looks like that, you are good to go smile Again, as per , just set proxy settings in your browser to use and 9050 as the port and you should be good to go!

Next up: Installing TORbutton :)

The observant ones will note the dates on the screenshots are old: I had originally made this guide for some friends who wanted it, and then I decided to publish it openly because, reasons.




TOR Setup – Windows

This is part one of a multipart posting series that’s gonna go on all evening before el grande finale of using TOR and suchlike to bypass Fortinet Web Filters and other such bullshit censorship warez. The two TOR install posts will go up first, followed by the ranty bypassing one, then some other stuff :3

Please note, these installation guides are for non technical people in a sense, I literally try hold the users hand as much as possible…

Well, if anyone here is as paranoid as I am, they probably wonder how the hell they can prevent their online activities from being traced back to them. So, in the interest of helping others anonymize their online presence, I have decided to knock up a few simple enough guides on installing and using various pieces of anonymity software, starting with the TOR bundle for Windows.

So. You should navigate yourself to, and go to the downloads section.

Downloading TOR

Downloading TOR

Assuming you installed Firefox ages back (I hope to god ye arent using IE…) install the Vidalia bundle. Just download it, run the executable file, tick all the boxes (i.e. full install) and fire ahead. It will pop during the install.

Installing Vidalia Bundle

Installing Vidalia Bundle

Finally, let TOR run, and you should see the following after up to two minutes or so:

TOR works

TOR is now running

Bingo. That is TOR installed and running, and as you can see, it is VERY simple to use. To make it work with Firefox for anonymized browsing: Edit -> Preferences -> Advanced -> Network -> Settings -> Set proxy as: SOCKS5 (type), and as IP and 9050 as port. I don’t think I can get much more simple than that.

Password Algorithms: Windows System Key (SYSKEY)

I stumbled upon some forum posts related to System Key recently and read something about 1 of the authentication modes available to Administrators that made me wonder if true or not.

Just to note, there are 3 modes.

  1. Generated by passphrase
  2. Stored in registry
  3. Stored on removable storage device

2 is enabled by default, but you can change this with the syskey.exe utility.

The claim was that if you forgot the passphrase or “startup password” there’s no reliable method of recovery. The “only way” to get back into the system is to restore a backup if one is available or disable completely using something like ntpasswd

In most cases, either way is probably sufficient enough, but there are situations where you would need to know the original passphrase and don’t have a backup available or perhaps you can’t even use a backup which could erase some critical information required.

There are a number of ways to recover the passphrase but I’ll just suggest one for now.
Found this short video which shows someone enabling the startup password

One of the the comments is “BOSS HOW WE HACK SYSKEY!!!” :-)

History of SYSKEY

SYSKEY was Microsoft’s response to pwdump and L0phtCrack.
It was provided as an optional security enhancement with Windows NT SP3 and enabled by default since the release of Windows 2000.

The purpose of this feature was to prevent pwdump working without modifications. Open source offline decryption tools didn’t surface until the release of samdump2 by Nicola Cuomo.

What follows is a short timeline of events related to SYSKEY.

March 1997 Samba developer Jeremy Allison publishes pwdump which enables Administrators to dump LM and NTLM hashes stored in the SAM database.
April 1997 L0pht publishes L0phtcrack which allows Administrators to audit password hashes. It had been in development since the release of pwdump.
May 1997 Microsoft publishes Service Pack 3 for Windows NT which added SYSKEY as an optional feature to prevent pwdump working properly.
December 1999 Todd Sabin documents flaw with SYSKEY. Anyone with access to the SAM database can reveal password hashes without the System key.
April 2000 Todd Sabin releases pwdump2 which dumps password hashes with the obfuscation removed. This also dumps hashes from a domain controller.
February 2004 Nicola Cuomo documents SYSKEY, Releases Samdump2 which enables offline decryption of password hashes stored in SAM database.

Password Generation

When the system boots and auth mode 1 is enabled, windows will display a dialog box waiting for you to enter the password. The following text is displayed on an XP system.

“This computer is configured to require a password in order to start up. Please enter the Startup Password below.”

Blank passwords are acceptable so whether you enter something or not, it gets processed with MD5 and authenticated once you hit OK.

#define MAX_SYSKEY_PWD 260

void pwd2key(wchar_t pwd[], uint8_t syskey[]) {
  MD5_CTX ctx;
  size_t pwd_len = wcslen(pwd);
  pwd_len = (pwd_len > MAX_SYSKEY_PWD) ? MAX_SYSKEY_PWD : pwd_len;
  MD5_Update(&ctx, pwd, pwd_len);
  MD5_Final(syskey, &ctx);

Enter the wrong password 3 times and you’ll receive the following error.

“System error: Lsass.exe”
“When trying to update a password the return status indicates that the value provided as the current password is not correct.”

This message appears because the LSA database key fails to decrypt but I wanted to know how exactly this password was authenticated.

Between XP and Vista, the LSA database got a major upgrade so you may see something else on post-XP systems.

If you were to attempt recovery through the LSA database, it would not only be much slower, it’s more complicated and because there’s a simpler way, I’m not going to cover it.

SAM Database

The SAM database is stored in %SystemRoot%\System32\config\SAM which as you probably know contains local user and group information, including encrypted NTLM/LM hashes.

Windows reads the value of F under SAM\Domains\Account and using the System key, decrypts the Sam key.

The structure of the F value isn’t documented but I’ve put together what I *think* is close enough to the original based on some MSDN documentation and analyzing code in SAMSRV.DLL which is where the decryption occurs.

#define SYSTEM_KEY_LEN   16
#define QWERTY "!@#$%^&*()qwertyUIOPAzxcvbnmQQQQQQQQQQQQ)(*@&%"
#define DIGITS "0123456789012345678901234567890123456789"

#define SAM_KEY_LEN      16
#define SAM_SALT_LEN     16

typedef struct _SAM_KEY_DATA {
  uint32_t Revision;
  uint32_t Length;
  uint8_t Salt[SAM_SALT_LEN];
  uint8_t Key[SAM_KEY_LEN];
  uint8_t CheckSum[SAM_CHECKSUM_LEN];
  uint32_t Reserved[2];

  DomainServerEnabled = 1,

typedef enum _DOMAIN_SERVER_ROLE {
  DomainServerRoleBackup  = 2,
  DomainServerRolePrimary = 3

typedef struct _OLD_LARGE_INTEGER {
  unsigned long LowPart;
  long HighPart;

#pragma pack(4)
typedef struct _DOMAIN_ACCOUNT_F {
  uint32_t Revision;
  uint32_t unknown1;
  OLD_LARGE_INTEGER DomainModifiedCount;
  OLD_LARGE_INTEGER LockoutDuration;
  OLD_LARGE_INTEGER LockoutObservationWindow;
  OLD_LARGE_INTEGER ModifiedCountAtLastPromotion;
  uint32_t NextRid;
  uint32_t PasswordProperties;
  uint16_t MinPasswordLength;
  uint16_t PasswordHistoryLength;
  uint16_t LockoutThreshold;
  uint16_t unknown2;
  uint8_t UasCompatibilityRequired;
  uint32_t unknown3[2]; 
  SAM_KEY_DATA keys[2];
  uint32_t unknown4;
#pragma pack()

NTSTATUS DecryptSamKey(PSAM_KEY_DATA key_data, uint8_t syskey[]) {
  MD5_CTX ctx;
  RC4_KEY key;
  uint8_t dgst[MD5_DIGEST_LEN];
  // create key with salt and decrypt data
  MD5_Update(&ctx, key_data->Salt, SAM_SALT_LEN);
  MD5_Update(&ctx, QWERTY, strlen(QWERTY) + 1);
  MD5_Update(&ctx, syskey, SYSTEM_KEY_LEN);
  MD5_Update(&ctx, DIGITS, strlen(DIGITS) + 1);
  MD5_Final(dgst, &ctx);
  RC4_set_key(&key, MD5_DIGEST_LEN, dgst);
      key_data->Key, key_data->Key);
  // verify decryption was successful by generating checksum
  MD5_Update(&ctx, key_data->Key, SAM_KEY_LEN);
  MD5_Update(&ctx, DIGITS, strlen(DIGITS) + 1);
  MD5_Update(&ctx, key_data->Key, SAM_KEY_LEN);
  MD5_Update(&ctx, QWERTY, strlen(QWERTY) + 1);
  MD5_Final(dgst, &ctx);
  // compare with checksum and return status
  if (memcmp(dgst, key_data->CheckSum, SAM_CHECKSUM_LEN) == 0) {
    return STATUS_SUCCESS;

NOTE: The strings didn’t format well for the blog but if you plan on using, let me know.

As you can see above, the Sam key is decrypted using System key and then a checksum is generated and compared with that stored in SAM_KEY_DATA
If they match, authentication succeeded, return STATUS_SUCCESS else STATUS_WRONG_PASSWORD

That’s pretty much how you can brute force the System Key when auth mode 1 is selected.


Assuming you can read the F value from SAM hive, recovery is straight forward enough with the right libraries/code.

Following is just some pseudo code to demonstrate flow of recovery using dictionary attack.

    sam = openfile("offline_system\Windows\config\SAM");
   data = readreg(sam, "SAM\Domains\Account", "F")
  words = openfile("dictionary.txt")
  while (readfile(words, pwd)) {
    pwd2key(pwd, syskey)
    if (DecryptSamKey(data->keys[0], syskey) == STATUS_SUCCESS) {
      print "Found password: " + pwd

LSA and NTDS algorithms call a hash function 1000 times during creation
of the encryption/decryption key while SAM algorithm doesn’t use any.

It’s not a vulnerability but could be useful to know some day.

Tool Release: phpkit 1.0 Web Backdoor

This is the (about bloody time too) release of the “PHPKit” PHP backdooring tool I was working on in my free time over the past while.



While not as advanced as “proper” web backdoors such as “weevely”, or “webhandler”, I feel PHPkit is something “interesting” to say the least.

Unlike most PHP backdoors, phpkit’s trojan contains no unusual function calls like “System” or “eval”. The only things it does are an ini_set and “include”. All “suspicious” PHP calls are made at runtime in-memory :D
This, I feel, makes it have a far smaller footprint on the target server. All payloads are sent as raw PHP in raw POST requests, where php://input passes them to the “include” function. It uses ini_set to attempt to enable allow_url_include if such is disabled, but I am working on a better workaround at the moment than this.
Likely something to do with fopen and suchlike… Will figure it out for the next version ;)

I actually got the idea to write this from when I was writing an exploit for the PHP-CGI bug, as shown here:

This tools “shell” is somewhat rudimentary, in that it (unlike Weevely), does not store CWD, etc. It simply executes commands, which is what I designed it to do. It does, however, have a rather nice file upload stager, which I was rather happy with.
It is reasonably reliable for an experiment, and certainly is interesting in that the evil code is ran entirely in memory ;)

Anyways, enough talking about how awesome it is (it really is not that awesome :( ), time for some demos and useage.

So, obviously you have placed odd.php on the target server somewhere, somehow. What next?

Well, the only mandatory argument is –url=’URL’, where the URL is the URL to the odd.php file (or whatever you called it). By default, the tool will attempt code execution and pop you a shell if possible.
If not possible, it simply exits.

The –mode operator allows you to choose what mode you want to use. By default, the “SHELL” mode is chosen, however “UPLOAD” is another option. If you choose “UPLOAD”, you must specify a local and remote file.
To specify the local file (File to upload), use –lfile=”PATH TO FILE”
To specify where to write the file, use –rfile=”PATH TO PLACE FILE”

This should upload the file cleanly and rapidly, allowing you to move on with the pwning of things.

Here is a screenshot of it in shell mode

phpkit shell mode

Shell Mode

And here is a screenshot of file uploading.

phpkit upload mode

phpkit upload mode

Well, that’s all for now. As you can see, it is more of an experiment than a real software by any stretch of the imagination, however, if you find it useful let me know :)

You may download it here: phpkit-1.0.tar.gz :)

Web Exploitation Engine 0.1 Release

So, you might remember my short writeup on exploiting command injection vulnerabilities – – and note that the tool used, GWEE, was a bit outdated and often would not compile correctly on modern versions of Linux using GCC.

Had you ever messed with the tool, you might also notice one of the authors was Sabu, so as a matter of principle, I was going to avoid using it whenever possible.

So, many attempts were made at re-implementing the tool in Python, most of them absolute failures, totally rubbish, or otherwise “clunky” and inelegant.

Anyways, much messing about later, I stumbled across a piece of code by @LaNMaSteR53 named “”. You can download it here: (the original one).

My main problem when writing my implementations (prior to seeing LaNMaSteR53’s implementation) was handling the POST data. How the hell would I get it from the commandline to the tool itself without having the user editing some config file of some kind. To me, this was a major stumbling block.

So, when I saw Tim’s implementation, passing it “just like a GET, but telling the parser it was POST”, I had to borrow it. A quick bit of replacing the urllib stuff with requests.get and, and I had a decent base to build from.

While the retooled version of itself was pretty cool as it was, I felt it could be taken a lot further. The original beta had built in reverse shells (12 or so varieties), however it tended to crash and such a lot. No error handling whatsoever, and some of the payloads simply failed to function at all.

Eventually, I wrote the “payloads” module. A slimmed down version of it is included in the wee.tar.bz2 archive, as I have not finished the thing yet. Currently the public release contains only a python reverse shell, however it is extremely easy to expand upon.

Anyway, on with the show. has only one mandatory arguement, the –url arg. You simply (for a GET request, the default), put in –url=’<rce>&otherparams=otherparams’
For a POST request, you put them in just like a GET request, and specify –method=post as an argument to tell the tool to parse them as POST parameters.

By default, it gives you the “” style inline shell prompt. However, using the –shell argument, you can specify it to use a reverse shell instead like so: –shell=reverse.

By default, the reverse shell will use and 4444 as its lhost and lport, so you can change this with –lhost=LHOST and –lport=LPORT.

So, here is a screenshot of it in action:

Poppin' shells

Poppin’ shells

This tool is still being developed, so report any bugs you find in it and make suggestions :)

You may download it here: wee.tar.bz2 :)

Remember, use with care, etc.

Back… With exploits!

So, sovaldi finally my DNS issues and suchlike got sorted out, and the server has been migrated to a new host. Email is back as of a few hours ago (few issues with MX records and mailboxes or something and emails being delivered 10 times to me, but I think that will fix itself after a few days. I hope so anyway, because being bombed with 100 messages 10 times each is getting plenty bloody annoying).

Everything is upgraded to the new wordpress, no more nasty hacking the config files to get WP to work on a server not designed to run it.

So, while the site was “inactive”, I was working on a whole bunch of new content (and finishing old articles) to publish. Seeing as I have exams, I shall just leave a few gifts here for you to look at until they are over. dietrich may have something for you also :)

So, in order to keep everyone entertained for the next few days, check out the following piece of exploit engineering.

D-LINK DIR-300 and DIR-600 routers have a hilarious preauth remote root flaw in their web interface. A webpage called “command.php” that accepts a “cmd=$cmd” and executes it as root. EPIC FAIL. Why was that there? Ask D-LINK.

It was discovered by a German researcher, @s3cur1ty_de and you can read his original advisory here:

I had some free time in college, so I knocked up a quick PoC tool to exploit the flaw, and even managed to test the exploit on a friends router after class.

PoC Code:

Remote Root

Remote Root

It delivers my customary user friendly shell interface, exploiting command injection. It can also autoenable TELNET and grant Telnet access, though this is seemingly less reliable, it hung when I tried it after rebooting the router.

Will be writing some more exploits, and maybe publishing them soon, so stay tuned ;)

Using PHP’s data:// stream and File Inclusion to execute code

This is a reasonably old remote code execution trick that I was actually unaware of until recently, illness when I stumbled across it by accident. I have been heavily researching various ways to go from a file inclusion bug to a remote code execution bug, and this one really got me interested.

As we previously mentioned in the I expect:// a shell post, medical you can use certain PHP streams to execute code via a file inclusion vulnerability. This one does not require any PHP extensions to be installed, unlike the expect:// trick, and relies solely on allow_url_include to be enabled, which sadly is becoming a rarity these days.

How this works is simple. PHP has a data:// stream, which can decode and accept data. If you insert some PHP code into this stream and include() it, the code will be executed. Rather simple, and rather effective too. I will cover php://input in a follow up post, and then post my findings on abusing FindFirstFile.

Essentially, instead of including /etc/passwd or a remote file, you simply include the following. data://text/plain;base64,PAYLOAD_GOES_HERE
Where the payload is base64 encoded PHP code to be executed. I choose to base64 encode the payload to avoid some problems I ran into with whitespace and longer payloads.

Now, obviously this would be no fun without a simple proof of concept tool to demonstrate the vulnerability. The following tool is under serious redevelopment at the moment, so it only spawns a bind shell at the moment. Next version will offer several payloads (I am working on a generic payload library for this kind of thing).

Data:// shell to bindshell :)

You can download the current version of the tool here: PHP data include exploit

I will update that code later, might do a video once there is something worth watching.

The Hunt For Red October

The Hunt For Red October – The Job So Far

Today, Kaspersky Labs released a report on a long running advanced persistent threat* (APT) they had uncovered, revealing a long running cyber-espionage campaign targeting a broad and diverse mixture of both countries and sectors. As usual the fingers were pointed at China (Chinese exploit chains, Chinese hosts used…), however, there was also some evidence to implicate Russian involvement, which was speculated to be a “False Flag” attempt.

An associate of mine, after reading the report, came up with a SHODAN dork rather quickly to identify the C&C hosts.

After a few seconds, he realized that the etag header on all of them was the same, leading to the following query:

SO, Fingerprinting information: just check for etag = 8c0bf6-ba-4b975a53906e4 :)

The “offending IP’s” are as follows. These are used as proxies it appears.

So, we now have a list of 7 C&C hosts. Time to break out nmap and see what they are doing.

The following scan string was used for an initial scan of all the hosts.

sudo nmap -sSUV -A -O -vvv 3 -oA huntingredoctober

The tarball of report files is available here: huntingredoctober.tar

The hosts identified as alive are as follows:

The other four were not responsive, probably taken down already. No fun.

Once I had identified which hosts were, infact, still alive (while the rest of the bloody slow scan was running), I decided to see what lay behind the scenes on these hosts, doing the “daft” thing of connecting to port 80 using my web browser. The clench factor was rather intense as I half expected to be owned by about half a dozen super 0day exploits on crack while doing so. instead, I was redirected harmlessly to the BBC.

The following HTML code was responsible for this redirect, which I thought was an incredibly clever way to hide their true purpose.

<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.0 Transitional//EN”>
<title>BBC – Homepage</title>
<meta http-equiv=”REFRESH” content=”0;url=”></HEAD>

Back to the nmap scan (it had FINALLY completed), the following was very interesting.

80/tcp  open          http?
|_http-title: BBC – Homepage
| Potentially risky methods: TRACE
138/udp open|filtered netbios-dgm
520/udp filtered      route

All of the servers looked like this. They all had those three ports – 80, 138, 520, open or filtered. The rest were all closed. The host began sending me RST packets midway through my scan, but regardless, the work went on. I decided I was going to look at the webserver from informations kaspersky published.

Sending GET requests to the /cgi-bin/ms/check CGI script produced a 500 internal server error, as did other CGI scripts. This was interesting in that they told me to email about it. I did so immediately, being a good netizen. Note the mispelling of example – “eaxample”.

Being Nice

Emailing the big heckers. The email delivered

Apparently the mail was delivered successfully, so I hope they reply soon with an explanation.

On to more serious things, another analyst working with me uncovered another interesting thing.

He went and did the following:
printf “POST /cgi-bin/nt/th HTTP/1.1\r\nHost:\r\nContent-Length: 10000\r\n\r\n%s” `perl -e ‘print “A”x(20000)’` | torsocks nc 80

Now, he had figured out the page would 500, unless a content length was set. So, he set a long Content Length, and sent an even longer POST request.
The result was nothing short of fascinating.

HTTP/1.1 200 OK
Date: Mon, 14 Jan 2013 19:18:07 GMT
Server: Apache
Content-length: 0
Content-Type: text/html

HTTP/1.1 414 Request-URI Too Large
Date: Mon, 14 Jan 2013 19:18:08 GMT
Server: Apache
Content-Length: 250
Connection: close
Content-Type: text/html; charset=iso-8859-1

<title>414 Request-URI Too Large</title>
<h1>Request-URI Too Large</h1>
<p>The requested URL’s length exceeds the capacity
limit for this server.<br />

“Look mom! Two headers!”. Seriously, this is interesting. First it gives a 200 OK, then a second later something else says “LOL, NO”. The delay makes us think the proxy is saying “OK”, then the real C&C is complaining. The fact it complains about a request URL, and the length being in the POST request, makes me think the final data-to-C&C might be sent as a GET. Just a theory.


// This post suffered a bad case of myself and fellow researchers having a lulz about it, and my cat straying onto my keyboard. It is a work in progress.

— Continuing the hunt —

Today we retrieved new intelligence (or rather, last night, but I could not act on this intel) from HD Moore of Metasploit project that more C&C servers had been located. The following link is the list of IP addresses.

So, it was decided (once the cat had gotten the hell off my keyboard) to investigate this list.
@craiu provided us with the tip “check out “1c824e-ba-4bcd8c8b36340″ and “186-1333538825000″ too.”, so we will act upon this later.

I decided, seeing as my internet went down for a while, to test out my Python skillz, and whipped up a quick program I named “SONAR”, which simply attempted a TCP connection to port 80 on the suspected C&C servers and logged responsive ones to a file. Source code attached.


I could have used nmap, but that would have been unimaginative and, frankly, no fun. And who says hunting cyber-spies (So much worse than normal spies, ‘cos they got the dreaded CYBER in there) is not supposed to be bloody fun anyway, not me for certain!

We quickly reduced the list to a “lot less than we had”, and I queued them up for nmap scanning, which has yet to be done, as the sysadmins on the network I am using do not like when I portscan things for some odd reason. Or when I use SSH, or email.

Anyway, I digress.

So far, more C&C servers had been identified, and more “Fingerprinting” methods had been developed. I am considering writing a patch to to dump out the etag data along with working IP’s, but that can wait til later. A simple HTTP GET / should do the trick, with a few regex’s.

We also obtained a list of MD5 hashes from showing samples of Red October they have in their repo – see here -> so those were queued up for downloading (once on a non monitored by college network) for some analysis using IDA. That is to be tonight’s job – a quick and dirty first pass run of analysing these things.

* For the record, I think APT is another FUD term… But oh well, it has become “a thing”.

I expect:// a shell!

This blog post covers a fascinating method of leveraging Local File Inclusion to gain Remote Code Execution on a vulnerable host. It has several downfalls, but overall is one of the more interesting methods I have found, and I have not found any references to it anywhere that I looked online.

PHP has many “wrappers” to parse certain types of things. For example, the php://input or php://filter wrappers, which have been used in the past for both code execution and information disclosure – notably the PHP-CGI Arguement Injection exploit, which uses the php://input wrapper to inject code after making modifications to PHP.ini directives.

One of the more entertaining ones I stumbled across is how PHP handles the expect:// “wrapper”. For those who do not know, “expect” is a program/scripting language of sorts that one can use to interact with other interactive programs. Some of you may be familiar with pexpect from Python, which is used to interact with SSH sessions for automation. It is a rather powerful utility, and is often used by sysadmins to automate procedures which would normally require human interaction.

As it happens, amongst PHP’s many wrappers, there is an “expect://” wrapper. I stumbled across it by accident while looking up the correct way to use php://filter to read files via LFI (I will document that method later, it deserves a post of its own). I knew expect looked familiar, so when I looked more into it, I found examples of people using it in PHP scripts to automate things like ssh-ing to remote boxes, etc.

After a while it dawned on me that something interesting might just happen if I passed expect://ls to an include() call in a PHP script, so I decided to see what would happen.

I used the following vulnerable (to LFI) PHP script, and called test.php?hax=expect://ls

$code = $_GET[‘hax’];

It provided me with a directory listing of my webroot.

expecting shell

remote code execution

After a few minutes of thinking “oh, this is interesting”, I decided to see if I could knock up an interactive shell in Python to automate the whole procedure.

First off, I decided to see could I get it all to work out using Pythons “requests” module…

Seeing as it worked, now it was time to write a “shell”.


got shell :)

Yes, I now had a somewhat interactive “shell” on the vulnerable host (localhost…). I considered releasing the proof of concept right there, however further messing about was warranted first, obviously. I needed to see how far I could “push” this vuln, and how cool I could possibly make the PoC tool before releasing it to the wild, where someone would doubtlessly give me much abuse about my python :P

So, without further ado, here is the video demo of it. It now checks if the host is vuln (very rudimentary check), and offers the “inline shell” or a reverse shell :) Download links at bottom :)

// Err, the video is on its way, I did not have time to clean it up sadly. I will edit this post in a day or so with the finished video, I promise :)

download link