Burp Suite can’t directly "test" for clickjacking vulnerabilities in the way it scans for XSS or SQL injection; instead, it’s a crucial tool for manually probing and confirming them.
Let’s see how Burp’s Proxy and Repeater can be used to discover if a web application is susceptible to clickjacking.
Imagine you’re on a banking site, logged in, and you visit a seemingly innocuous third-party site. If that third-party site, using a hidden iframe, can trick you into clicking a button on your banking site (like "Transfer Funds"), you’ve got a clickjacking problem. Burp helps us find those hidden iframes and the vulnerable targets.
Here’s a typical scenario:
-
Intercepting a Request: You’re browsing the target application, performing actions. You’ve got Burp Suite’s proxy set up. You navigate to a page that might be a target for clickjacking – perhaps a page with a sensitive action like "Delete Account" or "Approve Transaction." You send this request to Burp Repeater.
-
Crafting a Malicious Page (in Repeater): In Repeater, you’ll see the original HTTP request. The goal now is to see if this page can be framed by another site. You’ll modify the response from the server to include a
Content-Security-Policyheader that allows framing, or more commonly, you’ll construct a separate HTML page that tries to frame the vulnerable page.Let’s say the vulnerable page is
https://vulnerable-bank.com/transfer. In Burp Repeater, you’ll take the response forGET /transfer HTTP/1.1and then craft a new request, usually a GET request, to a completely different origin (or even just a local file on your machine for testing) that looks like this:<!DOCTYPE html> <html> <head> <title>Click Me!</title> </head> <body> <h1>Click the button below to win a prize!</h1> <iframe src="https://vulnerable-bank.com/transfer" width="500" height="300" style="position:absolute; top:0px; left:0px; z-index:100;"></iframe> <a href="#" style="position:absolute; top:50px; left:100px; z-index:200;">Click Here</a> </body> </html>The key here is the
iframepointing to the sensitive URL. We position it absolutely, and then overlay a visible element (like an<a>tag) on top of it, at a different z-index. The user thinks they’re clicking the visible element, but they’re actually clicking the framed element. -
Testing the Frameability: You’d then use Burp to send this crafted HTML to a browser. The easiest way is to save this HTML as a file (e.g.,
clickjacking_test.html) and open it in your browser with Burp as the proxy. You then navigate tohttps://vulnerable-bank.com/transferin the same browser session (ensuring you are logged in).Alternatively, you can use Burp Repeater to modify the server’s response to include a
Content-Security-Policyheader. If the application doesn’t have a restrictiveX-Frame-OptionsorContent-Security-Policy: frame-ancestorsheader, it might be vulnerable. You’d look for responses that lack these headers or have permissive values.A common technique in Burp Repeater is to take a legitimate request for a sensitive page, then modify the request to add a header like
Referer: https://evil.comto see if the server reacts differently, or to remove any existingX-Frame-OptionsorCSP: frame-ancestorsheaders that might be present.If you can load
https://vulnerable-bank.com/transferwithin an<iframe>on any other origin, and the content is displayed and interactive, you’ve found a clickjacking vulnerability.
The core problem is the lack of proper frame-breaking directives. Web applications should explicitly tell browsers whether they can be embedded in iframes, and by whom.
Here’s how you’d fix it:
-
X-Frame-OptionsHeader: The simplest and most widely supported defense.- Diagnosis: In Burp, check the HTTP response headers for
X-Frame-Options. If it’s missing, or set toALLOW-FROM(which is deprecated and has poor browser support), orSAMEORIGIN(which might be too restrictive if parts of your site need to be framed by others), it’s a potential issue. - Fix: Ensure the server always sends
X-Frame-Options: DENYorX-Frame-Options: SAMEORIGIN.DENY: Prevents any site from framing the page.SAMEORIGIN: Allows framing only by pages from the same origin.
- Why it works: The browser enforces this header, preventing the page from rendering within an
<iframe>from a different origin.
- Diagnosis: In Burp, check the HTTP response headers for
-
Content-Security-Policy(CSP)frame-ancestorsDirective: A more modern and flexible approach.- Diagnosis: Check for the
Content-Security-Policyheader in the response. Look specifically for theframe-ancestorsdirective. If it’s missing, or if it allows framing from*(all origins), it’s vulnerable. - Fix: Add or modify the
Content-Security-Policyheader to includeframe-ancestors.Content-Security-Policy: frame-ancestors 'none';(Equivalent toX-Frame-Options: DENY)Content-Security-Policy: frame-ancestors 'self';(Equivalent toX-Frame-Options: SAMEORIGIN)Content-Security-Policy: frame-ancestors https://trusted-partner.com;(Allows framing only bytrusted-partner.com)
- Why it works: The browser interprets the
frame-ancestorsdirective to control which origins are permitted to embed the resource.
- Diagnosis: Check for the
-
Server-Side Validation of Referer/Origin (Less Reliable): Some applications might check the
RefererorOriginheaders to prevent framing.- Diagnosis: In Burp Repeater, modify the request to send a crafted
RefererorOriginheader (e.g.,Referer: https://evil.com) and see if the application still renders the sensitive content correctly or blocks the request. - Fix: Implement robust server-side checks on the
RefererandOriginheaders, ensuring they match the expected origins. - Why it works: This acts as a secondary defense, but it’s less reliable because
Referercan be absent or spoofed by some browsers/proxies, andOriginmight not be present for all frameable requests. It should never be the sole defense.
- Diagnosis: In Burp Repeater, modify the request to send a crafted
-
Frame Busting JavaScript (Legacy/Less Reliable): Older applications might use JavaScript to detect if they are in a frame and break out.
- Diagnosis: Examine the page’s JavaScript for patterns like
if (top.location != self.location) { top.location = self.location; }. Then, try to disable JavaScript in your browser or use Burp to strip script tags from the response before rendering it to see if the frame-busting fails. - Fix: Ensure any existing frame-busting JavaScript is functional and that the
X-Frame-Optionsor CSP headers are also implemented, as JavaScript can be bypassed. - Why it works: The JavaScript code attempts to redirect the top-level window to the current page’s URL if it detects itself being framed, effectively breaking the frame.
- Diagnosis: Examine the page’s JavaScript for patterns like
-
Browser-Specific Vulnerabilities: Some older browsers might have had specific bypasses.
- Diagnosis: Test the vulnerability across different browser versions and types.
- Fix: Keep browser versions updated and rely on standardized headers (
X-Frame-Options, CSP) rather than browser-specific quirks. - Why it works: Browser vendors patch these vulnerabilities, and modern browsers consistently implement the framing directives.
The next vulnerability you’ll likely encounter after fixing clickjacking is related to insecure direct object references, where an attacker can manipulate parameters to access unauthorized data.