zapread.com
zapread.com copied to clipboard
WebSocket XSS during LNURL-auth flow if k1 is known to attacker i.e., can see the screen
Describe the bug This is a minor XSS issue which is only exploitable if "k1" of the lnurl-auth flow is known, which can happen e.g. in cases where attackers can record the victims screen and quickly conduct an attack.
To Reproduce
- First, please go to https://zapread.com/Account/Login and click "Lnurl-auth"
- Right click & copy the
lightning:
URL from the QR - Paste and decode the LNURL here: https://lnurl.fiatjaf.com/codec/
- Copy k1 and paste it into "toUserId" in the HTTP request below
- Fire that request e.g., from the Burp Repeater to
https://realtime.zapread.com
POST /api/auth/lnauthcb HTTP/2
Host: realtime.zapread.com
Content-Type: application/json
Content-Length: 125
{"toUserId":"PASTE_k1_HERE","Callback":"javascript:alert(1)//","Token":""}
Expected behavior Why is this realtime API accessible by me? Can it be changed, so only the zapread backend can use it?
Further, I recommend to hardcode the "callback" URL, to prevent abuse.
Please observe the following code snippet from https://github.com/Horndev/zapread.com/blob/a1ba83e4e72e718483821c1de33ae5e13b60d3e8/zapread.com/Scripts/src/realtime/auth/onlnauthlogin.js.
export function onlnauthlogin(callback, token) {
// console.log("realtime callback: ", callback, token);
appInsights.trackEvent({
name: 'lnurl-auth login authenticated',
properties: {
pubkey: token
}
});
appInsights.flush(); // send now
// Go to callback with login
window.location.replace(callback + "?code=" + token + "&state=" + state);
}
Note that callback
which we can control in the call to realtime.zapread.com/api/auth/lnauthcb
flows into the window.location.replace
XSS sink.
If callback can not be hardcoded, I recommend to create a check that it matches ^/[a-zA-Z0-9].*
so no protocols like https:
or javascript:
can be used, while also preventing the use of //foo
.
Screenshots
Additional context I just want to be extra clear that this is a very low severity bug, as the QR code is usually not known, so this can not be mass exploited.
Ok, I see the real issue. Sending the callback url over ws could be a weak spot. Easy to fix.
I wrote a patch for this here: dbd7ca020eaa49cac8ec977c85ce1fa849cd6078
It will make it into the next release.
lgtm but I still don't get why this realtime API is publicly accessible. Am I missing something?
No you're not missing anything. I do need to implement cross-domain credential sharing to properly authenticate on the realtime API since it runs on a different service. Some things I do want to be public and others not. My vision was to have a public live activity stream at some point.