果阿这个地方一直是冒险者的天堂, 就在前不久, 我们几个朋友计划去果阿旅行, 于是乎我们便在 Skyscanner 上搜索廉价机票, 然后找到了一个名为 "whereIDORsLive.com" 的网站. 这个网站的优惠幅度非常大, 它是一个大型旅游门户网站. 在这篇文章中, 我将跟大家分享几个我从中发现的 IDOR(不安全的直接对象引用) 漏洞.
第一个 IDOR: 下载任意用户的机票
当我在该网站的交易确认页面中继续完成机票订购时, 我发现了一个选项, 即将机票订单的 PDF 版通过短信, 右键和直接下载的方式提供给用户.
于是, 我直接下载了机票的 PDF 文件. PDF 文件名是一个加密字符串, 我一开始以为它使用的是 Base64 编码, 但解码之后却生成了一堆乱七八糟的东西. 这种情况很常见, 即字符串经过加密之后再次被编码为 Base64 格式, 这样它们就可以转换为可打印的字符, 以便在应用程序之间进行平滑传输和呈现.
每当我在网站中看到有数据被加密时, 我都忍不住想要去研究一下, 因为根据我的经验, 大多数网站在使用加密算法时都存在错误实现或者错误的 "自定义" 实现.
我之所以觉得这个网站有问题, 是因为他们没有为他们的 API 使用 SSL 证书, 并且对 PDF 文件名进行了加密操作, 这里一定有问题. 于是乎, 我右键点击了网页上的 "下载 PDF" 按钮, 然后审查元素.
我们发现, 代码使用我的 "订单 ID" 作为参数调用了 downloadPdf 函数. 那么我所做的第一件事, 就是将我的订单 ID+1, 比如说 "66786694", 然后再次调用该函数. 但此时打开的仍然是我这一份订单 PDF, 无论你提供给 downloadPdf 函数的订单 ID 值是多少, 它都只会返回当前机票订单的 PDF. 接下来, 我开始分析 downloadPdf 函数.
函数代码很简单, 它接收一个订单 ID 号作为参数 "tid"(这里就是 "66786693"), 但是却没有将其重新分配给加密字符串 "hdnBookingId". 因此, 当你单击它时, 将会在一个新的选项卡中打开你的 PDF:
http://api.whereIDORsLive.com/XYZService/EticketPdf/hdnBookingId.pdf
downloadPdf.JS[ 源代码 ]
- function downloadPdf(tid) {
- if (document.getElementById("hdnBookingId") != null && document.getElementById("hdnBookingId").value != "")
- tid = document.getElementById("hdnBookingId").value;
- if (tid != null && tid != "" && tid != undefined)
- Windows.open("http://api.whereIDORsLive.com/XYZService/EticketPdf/" + tid + ".pdf", '_blank');
- }
这就很奇怪了, 为什么会有人这么做? 为什么不直接调用 downloadPdf 函数? 为什么不用它来传递订单编号? 我的第一反应, 就是遗留代码, 此前可能是这个函数直接将 "订单 ID" 转换为 URL. 因此, 我猜测之前的链接形式可能为:
http://api.whereIDORsLive.com/XYZService/EticketPdf/bookingId.pdf
为了查看后端是否仍然有效, 我访问了下面这个链接:
http://api.whereIDORsLive.com/XYZService/EticketPdf/66786693.pdf
没错, 这条链接给我们返回了 PDF, 通过枚举订单 ID, 我还能够获取到其他人的机票订单.
漏洞成因
很可能是因为, 后端文件仍然是以 "bookingId.pdf" 的形式存储的, 并且有一个中间件来负责将 hdnBookingId 解密为 bookingId, 或者说同时存储了一个订单的两种文件名称 / 格式, 即同时存在 "hdnBookingId.pdf" 和 "bookingId.pdf".
第二个 IDOR: 同一家公司的另一个终端节点
接下来, 我对该公司旗下的 Android 应用程序进行了分析, 并且发现流量会被路由至一个终端节点处:
http://cloud.whereIDORsLive.in/XYZService/dboperation.svc
这对于黑客来说, 绝对是一个宝藏. 这是一个记录了所有节点的文档, 当点击相应节点的超链接时, 还会提供响应的 JSON 和 xml 样本 Payload, 以及节点返回的响应数据格式. 检查完这些节点之后, 我发现了一个可能会导致某些信息泄露的节点:
/GetETicket/{TransactionscreenID}/{UserName}/{Password}/{ProcessType}
这里要求提供 TransactionscreenID,UserName 和 Password 这三个参数, 但此时的我竟然有些束手无策测.
通过 Android 应用程序获取到订票信息后, 便会触发这个节点, 然后我们就可以查看到获取订票细节所需的参数值了:
节点会以 html Table 的格式返回乘客的信息, 而不是之前的 PDF 格式:
现在, 我们可以再看看之前的文档了. 还记得 ProcessType 参数吗? 我们可以直接将 URL 地址中的最后一个参数改成 1 或者其他值:
将 "3" 传递给 ProcessType 参数, 将会触发异常, 并允许我们查看到底层代码.
第三个 IDOR: 同一家公司的另一个终端节点
在查看文档时, 我还发现了另一个可能会泄露敏感信息的节点:
/GetPaxBookingDetails/{TransactionscreenID}/{UserName}/{Password}
向这个节点请求数据, 将会返回用户的个人身份识别信息 PII. 只要你在这家公司的网站上订过票, 那你的数据就可以通过这样的方式来获取到.
漏洞成因
该节点之所以会存在这个漏洞, 是因为它没有部署任何的访问控制策略或健壮的身份验证机制.
来源: http://www.tuicool.com/articles/7VJfayI