396
submitted 1 year ago* (last edited 1 year ago) by AlmightySnoo@sh.itjust.works to c/lemmy@lemmy.ml

DO NOT OPEN THE "LEGAL" PAGE


lemmy.world is a victim of an XSS attack right now and the hacker simply injected a JavaScript redirection into the sidebar.

It appears the Lemmy backend does not escape HTML in the main sidebar. Not sure if this is also true for community sidebars.

EDIT:

the exploit is also in the tagline that appears on top of the main feed for status updates, like the following one for SDF Chatter:

EDIT 2:

The legal information field also has that exploit, so that when you go to the "Legal" page it shows the HTML unescaped, but fortunately (for now) he's using double-quotes.

"legal_information":" ![\" onload=\"if(localStorage.getItem(`h`) != `true`){document.body.innerHTML = `\u003Ch1\u003ESite has been seized by Reddit for copyright infringment\u003C\u002Fh1\u003E`; setTimeout(() =\u003E {window.location.href = `https:\u002F\u002Flemmy.world\u002Fpictrs\u002Fimage\u002F7aa772b7-9416-45d1-805b-36ec21be9f66.mp4`}, 10000)}\"](https:\u002F\u002Flemmy.world\u002Fpictrs\u002Fimage\u002F66ca36df-4ada-47b3-9169-01870d8fb0ac.png \"lw\")
you are viewing a single comment's thread
view the rest of the comments
[-] Max_P@lemmy.max-p.me 37 points 1 year ago* (last edited 1 year ago)

Something's weird about it because I tried copy pasting it into my instance's sidebar and nothing happened. It gets quoted properly, at least on the official 0.18.1 Docker.

The rendered HTML looks like this:

<img src="https://lemmy.max-p.me/pictrs/image/d3667ced-4ea5-4fbf-b229-461c68192570.jpeg" alt="&quot; onload=&quot;setTimeout(()=003E{alert('oh no')},3000)&quot;" title="lw"></p>

E: Found it! Requires emojis as per this PR

If your instance doesn't have any custom emojis, you're safe. If not, log out immediately and wait for the instance to be updated. Anyone can exploit this as long as long as there's any custom emojis defined.

[-] AlmightySnoo@sh.itjust.works 27 points 1 year ago* (last edited 1 year ago)

Have you tried sending the API request for the sidebar edit yourself? Maybe the escaping is only done at the UI level (which would be EXTREMELY bad).

EDIT: no, couldn't find anything via comments

[-] Max_P@lemmy.max-p.me 25 points 1 year ago* (last edited 1 year ago)

I've even checked in the database directly - the markdown exploit is pasted exactly as is from the JSON I shared here (passed through jq to strip the JSON-encoding), with the only difference being I replaced lemonparty with example.com.

It renders, I get the image, but it's escaped properly. Both the affected instances so far are running some RC / version number shows a git commit, so maybe there's something weird about the build config that results in slightly different parsing.

I've very puzzled about it. I tried it in sidebar, I tried it as taglines (where lemmy.world's exploit was), I tried it as a post, I tried it as a comment. All of them result in the same correct output. I've even added the trailing space at the end in case it matters.

I'm open if you have more ideas.

E: database:

[-] AlmightySnoo@sh.itjust.works 6 points 1 year ago

see my edit on the comment you just responded to, I just injected an "alert"

[-] Max_P@lemmy.max-p.me 7 points 1 year ago

On which instance? It renders fine on mine: https://lemmy.max-p.me/comment/101376

Seems to render fine there as well: https://sh.itjust.works/comment/862442

And there as well: https://lemmy.ml/comment/1406331

In all cases:

I've even tried Chromium just in case Firefox was auto-fixing it.

I'm confused now, does it really work on your end?

[-] AlmightySnoo@sh.itjust.works 3 points 1 year ago

See the edit on the original thread, it's apparently the tagline (where a message can be shown above the main feed).

[-] Max_P@lemmy.max-p.me 7 points 1 year ago

I tried taglines.

Looks like the key was custom emojis: https://github.com/LemmyNet/lemmy-ui/pull/1897/files

That probably explains the "lm" bit after, makes the parser do something which results in the code not being properly escaped and boom.

I'm guessing now that the exploit has to be tweaked for individual instances to trigger this, to target an emoji the instance has which makes the check go into that branch. I don't have any on mine so I couldn't possibly trigger the bug.

I'll try to play with that and see if I can trigger it with that extra knowledge.

[-] AlmightySnoo@sh.itjust.works 2 points 1 year ago

You're right but then that means only a compromised admin account can do that (and that is the case on lemmy.world with Michelle's account). The thing is it happened on other instances too, so I'm very inclined to think that there's also something going on with comments or community sidebars.

[-] Max_P@lemmy.max-p.me 6 points 1 year ago* (last edited 1 year ago)

Voilà!

It's a Markdown bug and it does work everywhere, but it's only exploitable when it matches a custom emoji defined by the instance. It only works on the instance where the emoji is defined for some reason, as it causes the check to fail. As soon as I deleted the emoji, it stopped working without changing the test post at all. I've left the emoji deleted because then I'm open to getting my account exploited.

So, it's exploitable by anyone on the instance as long as the instance has custom emojis. But then if you can trick an admin to visit a page with the exploit code, you can use that to extract the user's JWT and send it elsewhere, from which then you breach the admin account and can further put the exploit in taglines/sidebars and whatnot. And because of the JWT bugs, even disabling the account doesn't work because the JWT doesn't get invalidated.

[-] AlmightySnoo@lemmy.world 3 points 1 year ago

Don't you find it weird that the "fix" that is being proposed is only changing the UI? In a sense, we're still trusting the front-end while unescaped HTML is still being stored in the database.

[-] Max_P@lemmy.max-p.me 6 points 1 year ago

It's converted from Markdown to HTML in the frontend, it's not stored as HTML in the database.

Editing posts would be a trainwreck otherwise.

[-] AlmightySnoo@sh.itjust.works 3 points 1 year ago* (last edited 1 year ago)

I'm wrong sorry, Firefox's inspector deceived me but when you look at the HTML it's indeed escaped, I definitely need to go to sleep

[-] Oraksus@programming.dev 17 points 1 year ago* (last edited 1 year ago)

Just a guess I haven't looked at the code. There is probably front end validation, but not back end validation, so forming your own http call probably allows any input.

[-] fuser@quex.cc 2 points 1 year ago

Great work. Thanks for all the effort and info.

this post was submitted on 10 Jul 2023
396 points (99.7% liked)

Lemmy

11948 readers
46 users here now

Everything about Lemmy; bugs, gripes, praises, and advocacy.

For discussion about the lemmy.ml instance, go to !meta@lemmy.ml.

founded 4 years ago
MODERATORS