TL;DR
Reflected Cross-Site Scripting (XSS) happens when malicious scripts are injected into a website through user input and immediately reflected back to the user. This guide shows how to block it on common web servers using input validation, output encoding, and HTTP security headers.
1. Understand Reflected XSS
Reflected XSS is often triggered by search boxes or URL parameters. The server takes your input, includes it in the HTML response without proper sanitisation, and sends it back to your browser. Your browser then executes the malicious script.
2. Input Validation
- Whitelist Approach: Define what characters are allowed. Reject anything else. This is the most secure method if you know exactly what input is expected.
if (preg_match('/^[a-zA-Z0-9 ]+$/', $_GET['search'])) { $safeSearch = $_GET['search']; } else { $safeSearch = ''; // Or handle the invalid input appropriately } - Blacklist Approach (Less Secure): Identify and remove dangerous characters or patterns. This is harder to get right as attackers can bypass filters.
Avoid relying solely on blacklists.
- Length Restrictions: Limit the length of input fields to prevent excessively long scripts from being injected.
3. Output Encoding
Encoding converts potentially dangerous characters into a safe format that browsers will display as text, not execute as code.
- HTML Entity Encoding: Encode characters like
<,>,", and&.$safeOutput = htmlspecialchars($userInput, ENT_QUOTES, 'UTF-8'); - JavaScript Encoding: Encode characters for safe use within JavaScript code. Use this when outputting data inside
<script>tags.$safeOutput = json_encode($userInput); - URL Encoding: Encode characters for safe inclusion in URLs.
$safeOutput = urlencode($userInput);
4. HTTP Security Headers
These headers tell the browser how to handle content and can significantly reduce XSS risks.
- Content-Security-Policy (CSP): Defines which sources of content are allowed.
Header set Content-Security-Policy "default-src 'self'"This example only allows resources from the same domain. Configure CSP carefully to avoid breaking legitimate functionality.
- X-XSS-Protection: Enables the browser’s built-in XSS filter (though its effectiveness varies).
Header set X-XSS-Protection "1; mode=block"While useful, don’t rely on this alone.
- X-Content-Type-Options: Prevents MIME sniffing.
Header set X-Content-Type-Options "nosniff"
5. Server Specific Configuration
- Apache (.htaccess or httpd.conf): Use
mod_securityfor advanced protection. - Nginx (nginx.conf): Configure CSP and other headers within the server block.
server { ... add_header Content-Security-Policy "default-src 'self'"; } - PHP: Use
htmlspecialchars()consistently, as shown in step 3.
6. Testing
Regularly test your application for XSS vulnerabilities using automated scanners and manual penetration testing.
- Try injecting simple scripts like
<script>alert('XSS')</script>into various input fields. - Test different encoding scenarios.