chat: mitigate unnecessarily risky code in third party oembed html #3115
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
When embedding content, there are two things I wanted to beef up:
This PR aims to address these two issues.
Perhaps there's still a workaround I've neglected, please do let me know. So easy to miss small details when making this kind of change.
Do embeds still work?
To check that Youtube, Twitter, and Spotify embeds still work, I simply ran Groups with these changes and tried embedding all three.
Appears to work!
Is this exploitable?
Actually, I think so! Specifically, for Twitter embeds. We can bypass the regex by using any domain that has the Twitter URL as a query parameter, ala
https://example.text/evil?ignoreMe=https://twitter.com/angelrightsnow/status/1557429719032905728
.This gets us past the regex but then we're hit with this roadblock:
https://github.com/tloncorp/landscape-apps/blob/e052bd0f39221652f39a0ea39f6be58804420e41/ui/src/state/embed.ts#L5
And then
https://github.com/tloncorp/landscape-apps/blob/e052bd0f39221652f39a0ea39f6be58804420e41/ui/src/state/embed.ts#L35
No way around it, we need to serve the malicious content from noembed. But noembed only serves oembed content from specific, supported providers. On the other hand, noembed is kind of old. Maybe some providers have actually died, and their domain is available for sale, all while noembed continues to support them!
We can search for noembed providers who's domains are for-sale by writing a simple Python script that uses noembed's and godaddy's APIs:
And running it...
Woo! So here's what an attacker does. First, you buy one of these domains.
Then you set the
"html"
property to contain a malicious link. TheTwitterEmbed
component looks for a link that looks like this:<a href=\"https://twitter.com/random_user/status/1733422327390490663?ref_src=twsrc%5Etfw\">
So we make nooledge.com/vid/9001 serve an oembed with a
javascript:
URL that passes these same checks. This will render as an error, including a link to the broken Tweet, which (when clicked) will launch the malicious JS code.In the end, we get a URL like nooledge.com/vid/9001?ignoreme=twitter.com/status/etcetc which Groups would misinterpret as a Twitter embed (due to the broken regex), which noembed would support, and which would snag HTML from a domain we can buy and control.
Very convoluted and unrealistic! Still, maybe there's something worse lurking beneath this silly thought exercise. In any case, maybe that justifies adding some additional mitigations.