厚脸皮找出题人要的零解题目0.o
题目描述
最近jack想学cc链,他请教了一位师傅,师傅为了考验他的能力,给了他一个网址和jar包,让他拿到地址中的flag,可是jack拿到网址后一脸懵逼,所以来找你求救,你能帮助他吗?
docker分析
通过nginx反向代理实现外部访问跳转到http://web:8080
这是他docker-compose.yml
1 | version: "3" |
可以看到他定义了两个网络:inner
和 outer
。
inner
网络是内部的,意味着连接到它的容器可以彼此通信,但不能与不在此网络中的容器通信。inner
网络使用桥接驱动程序,并配置了特定的子网(10.6.0.0/16)和网关(10.6.0.1)。outer
网络也使用桥接驱动程序。
subnet
:CIDR格式的子网,表示网段
CIDR
CIDR是“无类域间路由(Classless Inter-Domain Routing)”的缩写,它是一种IP地址分配和路由选择的方法,可以更有效地管理IP地址。CIDR采用更灵活的地址分配方法,通过在IP地址中使用可变长度的前缀,实现更细粒度的地址划分。它可以将一个IP地址块划分为多个子网,每个子网可以拥有不同数量的主机地址。CIDR还可以减少路由表的大小,提高路由选择的效率和速度。
如何将CIDR表示法转换为子网掩码?
- CIDR表示法是一个IP地址后面跟着一个斜杠和一个数字,例如192.168.1.0/24。
- 计算子网掩码的二进制数值。子网掩码是一个32位的二进制数,其中前面的n位为1,表示网络地址,后面的32-n位为0,表示主机地址。例如,CIDR表示法192.168.1.0/24中的数字24表示前面24位为1,后面8位为0,因此,对应的子网掩码为11111111.11111111.11111111.00000000,或者简写为255.255.255.0。
- 将子网掩码的二进制数值转换为十进制数值,即为对应的子网掩码。例如,11111111.11111111.11111111.00000000对应的十进制数值为255.255.255.0。
子网掩码
即用来判断两台计算机的IP地址是否属于同一个网络段的判断。如果两台计算机处于同一个网络字段上,则这两台计算机就可以直接进行通信交流。
屏蔽IP地址的一部分用来表示区别是网络标识和主机标识,以此来判断出IP地址是在局域网还是,Internet网上,将整个巨大的IP
网络划分成若干个小的子网,除此之外通过计算机的子网掩码,可以判断出两台计算机是否是处在同一个网络段的。
即将计算机的IP地址和子网掩码都转化为二进制,进行AND运算,得出结果相同的话,则说明两台计算机处在同一个网络段,可以直接通信。
gateway
:主子网的IPv4或IPv6网关
子网
为了确定网络区域,分开主机和路由器的每个接口,从而产生了若干个分离的网络岛,接口端连接了这些独立网络的端点。这些独立的网络岛叫做子网(subnet)。
网关
网关(Gateway)又称网间连接器、协议转换器。网关在传输层上以实现网络互连,是最复杂的网络互连设备,仅用于两个高层协议不同的网络互连。网关的结构也和路由器类似,不同的是互连层。网关既可以用于广域网互连,也可以用于局域网互连。 网关是一种充当转换重任的计算机系统或设备。在使用不同的通信协议、数据格式或语言,甚至体系结构完全不同的两种系统之间,网关是一个翻译器。与网桥只是简单地传达信息不同,网关对收到的信息要重新打包,以适应目的系统的需求。同时,网关也可以提供过滤和安全功能。大多数网关运行在OSI 7层协议的顶层–应用层。
网关实质上是一个网络通向其他网络的IP地址。
Bridge network
https://docs.docker.com/network/bridge/
Bridge network是一个链路层设备,在不用的网络单元之间转发消息。一个bridge可以是硬件设备也可以是运行在host OS内核的软件设备。
在Docker中,bridge network是一个软件bridge,能够允许连接到同一个bridge network的容器之间进行通信,同时能够隔离没有连接到此bridge network的容器。Docker的bridge驱动会自动在host machine安装路由规则,所以不同bridge network 上的容器之间不能直接相互通信。
Bridge network应用在同一个docker host上的容器。在不同docker host上的容器之间通信时,要么在操作系统层加路由,要么使用overlay network。
启动一个docker时,一个默认的bridge network会被自动创建,新启动的容器会连接到它,除非特别指定网络。也可以创建一个自定义的bridge network。
Docker network driver分类及介绍 Bridge、host、overlay、macvlan(1)-CSDN博客
所以定义自己的网络,并将需要隔离的容器连接到该网络。这样,这些容器之间可以相互通信,但是不能直接访问外部网络。实现了不出网。
Java二次反序列化之RMIConnector
在练一道题的时候碰到了,正好看到这篇文章,就学习一下。
一般在处理不出网题目或者绕过黑名单过滤
利用链
1 | invokerTransform#transform() -> RMIConnector#connect() ->> RMIConnector#findRMIServerJRMP() |
利用链分析
RMIConnector#findRMIServerJRMP()
在该方法中,将base64字符串解码后以序列化流的形式进行反序列化操作,如果能控制base64参数即可造成二次反序列化
可以看到该方法只有一个用法,在同一类的findRMIServer
方法中
判断path的开头必须为/stub/并截取的path后的值,所以path为我们base64序列化字符串的传入点。而path通过getURLPath()
获取,也就是下面urlPath属性的值,所以这里我们的思路就是通过反射修改urlPath属性的值,为/stub/base64_ser_str的形式
两个实现,但是doStart方法是protected,故只能使用public的connect方法。
RMIConnector#connect()
直接反射调用的demo来触发二次反序列化
完整POC
1 | import org.apache.commons.collections.Transformer; |
通过CC6来进行调用二次反序列化
1 | import org.apache.commons.collections.Transformer; |
调用栈
Javassist在反序列化中的应用
Javassist是一个可以动态生成Java字节码(.class)的库,它可以在运行的时候生成新的类。有时候,我们需要在所有class都被编译完后,运行时再修改或新建一个class文件,Javassist可以帮助我们达到这个目的。
本题在类的构造函数中定义了一个方法。该方法通过获取当前的 HTTP 请求,并利用反射获取请求中的参数,然后执行其中的命令,并将结果设置到 HTTP 响应的头部中。
org.apache.catalina.connector.Response
是接口ServletResponse
的实现。
ServletResponse
定义一个对象来帮助servlet向客户端发送响应。servlet容器创建一个 ServletResponse
对象,并将其作为参数传递给servlet 服务
方法
https://tomcat.apache.org/tomcat-8.5-doc/servletapi/javax/servlet/ServletResponse.html
通过 request.getParameter("cmd")
获取到名为 “cmd” 的请求参数,并将其作为命令执行。
题解
打开jar包看到
poc分析
这是出题人给的wp
1 | import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; |
main方法是rmiConnector结合CC1,rmiConnector是把CC3Exp这个函数返回的拼接进去,当作第二次反序列化的payload,而CC3Exp这个函数又是CC3加CC6,CC3是利用Javassist生成的字节码来执行任意命令。
动态调试
ctf-idea调试jar包_ctf java jar-CSDN博客
在环境目录执行:
1 | java -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005 -jar app.jar |
记得在打开题目jar包后引入common-collections3.2.1外部库
然后在IDEA中添加远程JVM调试
在org.apache.commons.collections.map.AbstractInputCheckedMapDecorator
的setValue方法打个断点
步入org.apache.commons.collections.map.TransformedMap
的checkSetValue方法
步入又回到了org.apache.commons.collections.map.AbstractInputCheckedMapDecorator
的setValue方法,可以看到这个时候返回值就不一样了。
接着步入到org.apache.commons.collections.map.TransformedMap
的checkSetValue方法
再步入就进入org.apache.commons.collections.functors.InvokerTransformer
的transform方法
链子就是
1 | AnnotationInvocationHandler.readObject-> |
知识星球 | 深度连接铁杆粉丝,运营高品质社群,知识变现的工具 (zsxq.com)
浅谈Java二次反序列化 - 先知社区 (aliyun.com)
二次反序列化 看我一命通关 - 知乎 (zhihu.com)
Java安全Commons Collections1初探过程的思考 - 先知社区 (aliyun.com)