Tabnabbing and Window Opener Phishing: A Bug Bounty Deep Dive
The familiar reverse-tabnabbing demo opens an attacker page, calls window.opener.location = ..., and replaces the original tab with a login clone. Modern browsers often imply noopener for plain target="_blank", so that one-liner is no longer the whole hunt.
Opener phishing is broader. Named windows, JavaScript window.open, legacy webviews, cross-origin redirects, and same-origin link wrappers can preserve a handle even when the final destination looks external.
Map how the window is created
Inspect the actual click handler. These patterns deserve separate tests:
<a target="_blank">without explicitrel="noopener"window.open(userUrl, "_blank")window.open("", "preview")followed by assignments to the returned handle- Reused names such as
report,oauth, orhelp - An internal redirect endpoint that eventually lands on an external site
- Mobile in-app browsers and desktop Electron shells
Browser defaults differ by context. Record browser and platform. An HTML anchor may get implicit protection while a scripted window flow retains opener.
On the opened page, check window.opener !== null. Cross-origin policy blocks reading the original DOM, but navigation of opener.location may still be permitted. That write capability is enough for the phishing swap.
Build a believable, safe proof
Use accounts and domains you control. The attacker-controlled destination waits a few seconds, then navigates the opener to a harmless canary URL on your server or an allowed target logout page. The delay matters: users focus on the new tab and forget what the old one displayed.
A realistic video shows:
- Victim clicks a user-controlled link from a trusted target page.
- New tab opens and appears normal.
- Original tab silently changes.
- Victim returns to what they believe is the target tab.
Do not collect credentials. A mock page with “phishing destination reached” proves navigation. Explain that the unchanged tab history, favicon timing, and user expectation make credential capture plausible.
Named-window confusion
Named windows offer a different angle from reverse tabnabbing. If the app opens sensitive content into target="report", an attacker may pre-create or later reuse a window with that name. Flows can overwrite each other's content or hand a reference to a less trusted origin.
OAuth popups are worth care. The parent often polls or listens for postMessage; a popup that navigates through an attacker-controlled redirect may retain opener and send crafted messages back. That becomes an origin-validation finding, not merely tabnabbing, if the parent trusts the message.
Check mitigations rather than guessing
rel="noopener" severs the opener. rel="noreferrer" also suppresses the Referer and implies opener protection, but it changes analytics and is not always needed. Cross-Origin-Opener-Policy can isolate browsing context groups at the response layer.
If the opened destination is fully trusted and cannot redirect or host user content, the risk is weak. If users control the URL, an open redirect reaches arbitrary origins, or a partner domain has stored HTML, impact improves. Programs often rate generic tabnabbing Low or Informational. Show the exact attacker control and the product's trust cue instead of inflating it to automatic account takeover.
Report shape
List the source page, element or script that opens the window, final attacker-controlled origin, window.opener result, browser versions, and a no-credential PoC. Recommend explicit noopener on external windows, safe URL allowlists, no fixed window names for mixed-trust content, and strict postMessage origin checks.
MDN documents Window.opener and the conditions that suppress it. Test the product's full redirect chain; the first link is rarely where the interesting trust change happens.