挖洞经验 | 打车软件Lyft费用报告导出功能的SSRF漏洞

在外出参与某个安全会议的旅程中,我发现打车拼车应用Lyft能以PDF或CSV方式生成用户的行程消费报告,作为一个Lyft的老用户,这种功能非常方便,可以简化我繁琐的工作费用整理流程。但便利的同时,我也在想一个问题:它会存在安全漏洞吗?最终经过我与Cody Brocious (@Daeken)的测试,发现Lyft在该功能上确实存在漏洞。该漏洞于2018年发现,直到最近才公开,我们一起来看看。

Lyft的消费报告导出功能

当完成了一次打车服务,缴费或给司机评分之后,在Lyft应用弹出的行程信息窗口中,用户可以在其中输入消费代码(expense code)或其它信息,来对行程进行标识记录。比如,出于测试目的,我打车到机场后,在Lyft应用中的“行程历史”(Ride History)下的行程信息窗口标识中,我输入了一个HTML标记(

test),之后,对应地它会提示我可以导出消费报告。点击导出之后,它会向我的邮箱发现两种报告模板:CSV和PDF,在我打开PDF版本的报告后,之前我输入的HTML标记(test)竟然成功在消费标识区域被加载了:

这个可利用点引起了我们的注意,我们想可以尝试用其中的PDF生成机制(PDF generator)来构造SSRF漏洞。

构造SSRF漏洞

从上可知,向PDF消费报告生成机制(PDF generator)中插入的HTML标记能有效加载,接下来可以考虑,利用该功能是否可让PDF generator调用一些外部资源实现敏感信息收集(如user-agent类的用户信息等)。由于行程消费标识操作每次都需要启动Lyft应用,为此,我们在其中设置了几个包含外部链接的行程历史记录,其中嵌入了如 和 <img>的外部资源标记,但是,经过测试发现,这种方式完全无效,没有任何反应。</p> <p>数周之后,HackerOne在纽约举办了一场线下实时比赛,其中就包含了 Lyft APP,而且这种类似内测的比赛可以在Lyft APP中添加大量行程历史记录,因此对我们来说,这算是一个非常好的漏洞测试机会。本次比赛,我们把关注点调整,首先需要了解为什么<h1> 和<u> 标记能正常加载,而<img> 和 <iframe>却不行。之前说过,在Lyft发来的消费报告中还存在一个CSV文件,经过对比其中的字符串集,我们发现其中包含的左右双引号是这样的<b>“</b>,而非正常的英打双引号<b>“</b>,之后,我们在PDF消费报告的Payload进行了校正,然后请求PDF报告,就能从Lyft应用中获取到报告生成服务端的User-Agent信息,其中包含了WeasyPrint服务,如下:</p> <p><img width="596" height="97" alt="lyft4.png" src="https://image.3001.net/images/20200604/1591262833_5ed8be7151596.png!small"></p> <h2>WeasyPrint </h2> <p>WeasyPrint 是一个开源的智能WEB报告生成服务,用它可以方便地在WEB应用中制作生成PDF报告,它能把简单的HTML标记转变成华丽的**、票据、统计报告等,用户在相应的HTML模板或URL链接中填写好要求的字段后就能自动生成PDF报告,如用以下命令就能把一个填写好的HTML模板生成PDF报告:</p> <blockquote><p>$> weasyprint input.html output.pdf</p> </blockquote> <p>所以,接下来我们就把研究点放到了WeasyPrint服务上,经过分析,我们发现WeasyPrint的具体工作机制如下:</p> <blockquote><p>允许嵌入短小数字作为HTML标记</p> <p>不允许执行Java脚本</p> <p>不允许执行iframe或类似标记</p> </blockquote> <p>通过对<a href="https://weasyprint.org/">WeasyPrint</a>开源代码的分析查看之后,我们在<a href="https://github.com/Kozea/WeasyPrint/blob/b7a9fe7dcc9d0755a3324b74d0965e806bb87378/weasyprint/html.py">html.py</a>中发现了一些有意思的地方,如WeasyPrint对img、embed和object等标签集都进行了重定义,由于其不支持Java脚本,所以当时我们对PDF生成机制的漏洞利用就没抱太大希望。但是,后来,我们在WeasyPrint开源代码的 <a href="https://github.com/Kozea/WeasyPrint/blob/b7a9fe7dcc9d0755a3324b74d0965e806bb87378/weasyprint/pdf.py">pdf.py</a>文件中发现了<link>属性,该属性允许向PDF报告插入任意的网页形式或本地文件内容,如:</p> <blockquote><p><link rel=attachment href=”file:///root/secret.txt”></p> </blockquote> <p>最终,利用数据压缩函数库zlib 以及 python, 我们写了一个从PDF文件中解包本地文件的脚本,如下:</p> <pre><code><p><code>import sys, zlib</code></p><p><code></code></p><p><code>def main(fn):</code></p><p><code></code></p><p><code> data = open(fn, 'rb').read</code></p><p><code></code></p><p><code> i = 0</code></p><p><code></code></p><p><code> first = True</code></p><p><code></code></p><p><code> last = None</code></p><p><code></code></p><p><code> while True:</code></p><p><code></code></p><p><code> i = data.find(b'>>\nstream\n', i)</code></p><p><code></code></p><p><code> if i == -1:</code></p><p><code></code></p><p><code> break</code></p><p><code></code></p><p><code> i += 10</code></p><p><code></code></p><p><code> try:</code></p><p><code></code></p><p><code> last = cdata = zlib.decompress(data[i:])</code></p><p><code></code></p><p><code> if first:</code></p><p><code></code></p><p><code> first = False</code></p><p><code></code></p><p><code> else:</code></p><p><code></code></p><p><code> pass#print cdata</code></p><p><code></code></p><p><code> except:</code></p><p><code></code></p><p><code> pass</code></p><p><code></code></p><p><code> print(last.decode('utf-8'))</code></p><p><code></code></p><p><code>if __name__=='__main__':</code></p><p><code></code></p><p><code> main(*sys.argv[1:])</code></p></code></pre> </p> <h2>最后一程</h2> <p>在本地环境测试中,我们把上述脚本结合Lyft的PDF生成机制设置了一个包含Payload的行程记录,在导出PDF报告的过程中,触发了其中的SSRF利用,获取到了相应的用户信息,确认了漏洞的存在,如下:</p> <p><img width="690" height="201" alt="lyft5.jpg" src="https://image.3001.net/images/20200604/1591262963_5ed8bef32751e.jpg!small"></p> <h2>致谢</h2> <p>感谢Lyft安全团队,Daeken的思路、@d0nutptr的漏洞验证,更多技术细节请查看HackerOne报告-<a href="https://hackerone.com/reports/885975">H-885975</a>,或观看NahamSec频道YouTube视频: <a href="https://www.*******.com/watch?v=t5fB6OZsR6c">Exploiting a Server Side Request Forgery (SSRF) in WeasyPrint for Bug Bounty & HackerOne’s $50M CTF </a></p> <h2>漏洞上报和处理过程<br /></h2> <blockquote><p>2018.11.10 – 我初次发现漏洞</p> <p>2018.11.29 – 在纽约比赛中与@Daeken合作完成POC</p> <p>2018.11.29 – 报送Lyft安全团队</p> <p>2018.11.29 – Lyft修复漏洞</p> <p>2018.11.30 – Lyft告知漏洞已修复</p> <p>2018.12.05 – Lyft按其最高众测标准给予漏洞赏金</p> <p>2020.5.20 – 漏洞公开</p> </blockquote> <p><b><span style="color: rgb(159, 163, 168);">*参考来源:<a href="https://www.nahamsec.com/posts/my-expense-report-resulted-in-a-server-side-request-forgery-ssrf-on-lyft">nahamsec</a></span><span style="color: rgb(159, 163, 168);">,clouds 编译整理,转载请注明来自 FreeBuf.COM</span></b></p>返回搜狐,查看更多

阅读 ()
平台声明
该文观点仅代表作者本人,搜狐号系信息发布平台,搜狐仅提供信息存储空间服务。