Rating:

Disclaimer: I didn't solve this challenge and this is not a full writeup. I just want to put a few useful links here.

The challenge is about exploiting Chrome's Scroll To Text Fragment to leak data with lazy-loading images <img loading="lazy">. The uBlock Origin is intended to be used to duplicate the user activation to trigger multiple text fragment leakage. See @lbherrera''s partial solver for more details.

The author @thebluepichu (I think so?) said in the IRC channel:

Catalog has two injections: the image tag on the issue page and the username when you fail to login. Use the image tag one with a meta redirect to get offsite. Hint 1 + inclusion of uBlock: admin clicks on a link which gives a user activation to the active frame, uBlock sends a postMessage to its extension iframe, which duplicates the user activation. Whenever a page loads, the frontend gets a postMessage from the uBlock frame, and thus duplicates the activation back again. Now make a no-cors POST to use the failed login injection, then send them to issue.php?id=3. So now we have arbitrary content with a user activation on the correct page, but still no code exec.

Ok, but what can we do? A recent addition to Chromium was scroll-to-text-fragment, which lets you search the page for text (in entire words only) and scroll to it, though this consumes the user activation. If you could search for a letter at a time, then you could use your injection to add a bunch of whitespace and a lazy-loading image to detect the scroll. It turns out you can: the whole-word match counts tag boundaries as word boundaries, and the <em> tag gets split into a <span> for each individual letter on load! So you can do text searches of the form #:~:text=F-,{,-X for example to search for an X at the beginning of the flag. You can specify multiple text searches to do a binary search across the whole alphabet. Also include a meta refresh to send back offsite again after a short delay and you can leak ~5 characters per captcha. Repeat 5 or 6 times to get the whole flag.

Original writeup (https://balsn.tw/ctf_writeup/20200418-plaidctf2020/#catelog-(not-solved)).