[HackerNotes Ep. 158] Charity Hack-Along Technical Findings and Writeup analysis

We come back on the Hack-Along findings and some writeups analysis

Hacker TL;DR

  • Post-message race conditions can be won by using window.open with width/height parameters to prevent JS execution throttling in background tabs

  • When event.source in post-message handlers is compared against uninitialized variables using loose equality, sending from a sandboxed iframe yields null === undefined bypass

  • Browser permission delegation through iframe allow attributes lets attackers inherit camera/microphone access on sites where users have granted perpetual permissions

  • Youssef Sammouda's Meta chain demonstrates that analytics infrastructure treated as "low-risk code" becomes a critical attack surface when shared across domains

Join Justin at Zero Trust World in March!
Get $200 off registration with Code: ZTWCTBB26

Charity Hack-Along insights

Last week, there was a great Charity Hackalong for 10h on the CCTB Discord, and here are some insights into it:

Post-Message Race Conditions and JS Throttling

A post-message race condition emerged during testing where an iframe receives an initialization message from the top-level frame, and an attacker-controlled page needs to send a competing message first to hijack control. The constraint: window.open throttles JavaScript execution in background tabs, preventing the attacker page from sending messages fast enough or receiving responses reliably.

The bypass: open the target with window.open(url, '_blank', 'width=800,height=600') to create a popup window. Both the popup and the originating tab remain "visible" to Chrome, so both get full JS execution priority. The result is 10,000+ post-messages sent immediately, consistently winning the race.

This matters whenever you're exploiting post-message handlers that depend on initialization ordering. If your exploit works in dev but fails in production, check whether your attacking page is getting throttled.

Partial Auth State Exploitation

On SaaS platforms with SSO, attempting to log in with an email domain that triggers Okta redirect (e.g., [email protected]) can leave partial authentication cookies. Navigating back and logging in with a different email address puts the session in a hybrid state, authenticated with one identity but carrying signed tokens from the SSO flow for a different domain.

The attack surface:

  • Any endpoint that checks domain-based permissions may trust the signed token's domain claim

  • Recommendation engines showing "teammates" or "shared documents" may expose data from the SSO domain

  • Parent company integrations often inherit this partial auth across multiple acquired products

Methodology when you find partial auth:

  1. Enumerate all API endpoints and SPA routes

  2. Replay requests with the partial auth cookies/tokens

  3. Focus on endpoints that filter by organization or domain

  4. Check if the parent company's other products accept the same partial auth

The signed token carries a domain claim the user shouldn't have. If any backend trusts that claim without validating the full auth state, you get cross-tenant access.

Browser Permission Delegation via Iframe Allow Attributes

Sites that request perpetual camera/microphone access (video conferencing, recording tools) create a permission inheritance risk. If the site loads an attacker-controlled iframe with allow="camera; microphone", those permissions flow down to the iframe without additional prompts.

The attack chain:

  1. Find a site where users typically grant perpetual media permissions

  2. Identify any path that loads user-controlled iframe content

  3. Craft an iframe with allow="camera microphone" on the embedding page

  4. Redirect victim to your page → your iframe inherits the permissions → capture media silently

Chrome's current design doesn't re-prompt when permissions are delegated to child frames. This is "legacy behavior" that won't be changed due to backwards compatibility concerns. Any site with perpetual media permissions and user-embeddable iframes is vulnerable.

You can grep for <iframe.*allow= in page source and check if camera/microphone are in the allow list. Then find any path that loads third-party or user-controlled iframe content.

A lot of good writeups

Post-Message Source bypass

@SecurityMB discovered that event.source can be set to null in post-message events (Chrome-specific) in case of a check about null == undefined. The technique:

<iframe id="f"></iframe>
<script>
  frames[0].eval('parent.postMessage("payload", "*")');
  document.getElementById('f').innerHTML = '';
</script>

The eval queues the post-message, then immediately destroying the iframe via innerHTML removes the source frame context. When the message arrives, event.source === null.

This bypasses validation patterns that compare event.source against a frame reference:

if (e.source == window.frames[0]) {
  // process message
}

When the originating iframe is destroyed before the message is processed, window.frames[0] becomes undefined. Since JavaScript's loose equality treats null == undefined as true, the check passes. The attacker's message is accepted as if it came from the expected frame.

Note: This technique only works in Chrome. Firefox correctly preserves the event.source property even when the originating iframe has been destroyed.

CSPT and Authorization Header Behavior on Redirects

@InsertScript documented that authorization headers are dropped on redirects, but only under specific origin conditions:

Original Request

Redirect Target

Authorization Header

Same-origin

Different host

Dropped

Cross-origin

Different host

Included

If your CSPT targets api.example.com from www.example.com (cross-origin), and the API has an open redirect, the authorization header survives the redirect to your server.

If the original request is NOT targeting a same-origin endpoint, include the authorization header in case of redirect.

Custom headers like X-CSRF-Token are NOT dropped in either case. The protection only applies to the Authorization header specifically.

When hunting CSPT, check if the vulnerable endpoint is same-origin or cross-origin relative to the page making the request. Cross-origin CSPTs with redirects can leak auth headers directly.

CRLF to XSS on 302 Responses

@Def1ant demonstrated that CRLF injection in the Location header can achieve XSS even on 302 redirects, if you control the full header value and can start with a newline.

Location:
<script>alert(1)</script>

An empty Location header causes the browser to render the response body as HTML instead of following the redirect. Previously, CRLF in Location on 302 was considered low-impact due to limited exploitation primitives. This changes that assessment for scenarios where the attacker controls the full header value.

Meta XSS Chains - Youssef Sammouda's $300K+ Findings

Bug 1: Conversion API Gateway Post-Message XSS ($65K)

Meta's Conversion API Gateway (server-side tracking to replace client-side pixels) had a post-message handler without origin validation. The handler accepted data that was written to localStorage, which was later used to construct a script URL.

Constraints:

  • CSP blocked inline scripts and restricted script-src

  • COOP (Cross-Origin-Opener-Policy) prevented window.opener access

CSP bypass: find a route within the same origin that has a looser CSP (additional third-party domains in script-src). Load the exploit through that route.

COOP bypass (Facebook Android WebView only): window.name = 'test'; window.open(url, 'test') creates a self-referential opener. The WebView doesn't properly enforce COOP in this edge case.

A third-party iframe was hijacked server-side. This wasn't a client-side frame reference manipulation, the attacker compromised the third-party server to:

  1. Control the iframe content

  2. Host a malicious JS file

  3. Send the post-message from a "trusted" frame

The chain: exploit third-party → hijack iframe → bypass COOP via WebView quirk → send post-message → pollute localStorage → trigger script load → XSS on Meta origin.

Bug 2: Pixel ID Poisoning RCE-equivalent ($250K)

The same Conversion API Gateway had an IDOR allowing configuration of rules for any pixel ID. The rule engine used string concatenation to build JSON inside dynamically generated JavaScript:

var rule = '{"field": "' + userInput + '"}';

No sanitization on the input field. Injecting ", "injected": "payload breaks the JSON structure. But since this JSON is embedded in JS, proper payload crafting achieves arbitrary JS execution.

The impact: poison any customer's pixel → their JS file loads your payload → stored XSS across all sites using that pixel.

Meta open-sourced the gateway code on Amazon ECR. Decompiling the JAR revealed the string concatenation pattern. The IDOR was found by fuzzing pixel ID parameters with other customers' IDs.

Spring Boot Actuator Bypasses

@Zwink demonstrated a $55K actuator finding using /[path]/actuator/heapdump%23. The encoded # (%23) bypasses WAF rules or routing logic that block /actuator/heapdump directly.

Actuator fuzzing checklist:

  1. Don't just fuzz at root, prepend discovered API base paths

  2. Add path traversal sequences before actuator endpoints

  3. Apply 403 bypass techniques (;, %23, %2e%2e/, ..;/)

  4. Test authenticated and unauthenticated

  5. Combine multiple bypass techniques per endpoint

The full endpoint list is well-known (/actuator/env, /actuator/heapdump, /actuator/mappings, etc.), but the bypass variations multiply the search space significantly.

We do subs at $25, $10, and $5, premium subscribers get access to:

Hackalongs: live bug bounty hacking on real programs, VODs available
Live data streams, exploits, tools, scripts & un-redacted bug reports

Claude Code Command Injection Bypasses

@ryotkak from Flatt Security found 8 bypasses in Claude Code's command allowlist. The allowlist uses regex to permit "safe" commands like man, sort, sed, xargs. Each bypass exploits either:

1. Dangerous flags in "safe" commands:

  • man --html='touch /tmp/pwned' man , --html specifies the renderer, which executes arbitrary commands

  • sort --compress-program=/bin/sh , compression program flag accepts executables

  • echo test | sed 's/test/touch \/tmp\/pwned/e' , using the modifier e executes shell commands

2. Git argument abbreviation:

  • Git auto-completes abbreviated flags: --upload-pa becomes --upload-pack

  • Bypass regex filters matching exact flag names

  • git ls-remote --upload-pa='...' bypasses --upload-pack blocklist

3. Argument consumption assumptions:

  • xargs -t touch echo , regex assumes -t consumes the next argument, but -t is boolean

  • touch becomes the executed command, not an argument to -t

4. Bash prompt expansion:

echo ${one="$"}${two="$one(touch /tmp/pwned)"}${two@P}

The @P modifier interprets the variable as a prompt string, which supports command substitution. Combine with $ assignment to break out of restricted contexts like setting the variable one to $.

Any regex-based command validation against shell execution is fundamentally fragile. The attack surface includes every flag of every allowed command, plus shell parsing quirks, plus tool-specific behaviors like Git's abbreviation.

Smarter Mail Pre-Auth RCE

Watchtower Labs documented a path traversal in Smarter Mail's attachment upload. The vulnerability was identified by diffing a patch that added GUID validation.

The POST /api/upload endpoint allows unauthenticated uploads (AllowAnonymous = true). The multipart form data includes:

  • context , set to "attachment" to trigger the vulnerable code path

  • resumableFilename , attacker-controlled filename (e.g., shell.aspx)

  • contextData , JSON object containing the guid field

The server constructs the file path using format att_{0}_{1}.{2} where the GUID is embedded without sanitization. Path traversal in the guid field escapes the App_Data/Attachments directory:

{"guid":"../../../../../../../inetpub/wwwroot/shell"}

Combined with resumableFilename: shell.aspx and a webshell payload in the file upload, this writes directly to the web root for RCE.

ClamAV scanning was present but either couldn't detect the basic shell or the scan results weren't being processed.

Resources

That's it for the week, keep hacking!