Cross-Site Scripting Prevention
Cross-Site Scripting (XSS) er en sårbarhed hvor angribere kan injicere ondsindet JavaScript i websider der vises til andre brugere.
Om Truslen
Cross-Site Scripting (XSS) er en af de mest udbredte sikkerhedssårbarheder på nettet og optræder konsekvent i OWASP Top 10. XSS opstår når en applikation inkluderer uvalideret eller uescaped brugerinput i output sendt til browseren. Dette giver angribere mulighed for at udføre JavaScript i offerets browser-kontekst, hvilket kan resultere i session hijacking, cookie theft, defacement, phishing-angreb og malware distribution. Statistikker viser at cirka 40% af alle cyberangreb involverer XSS i en eller anden form. XSS er særligt farligt fordi det kan bruges til at omgå Same-Origin Policy og få fuld adgang til alt indhold på siden, inklusive følsomme data. Der findes tre hovedtyper: Reflected XSS (ikke-persistent), Stored XSS (persistent) og DOM-based XSS, hver med deres egne karakteristika og udfordringer.
Key Points
- ✓Escape ALT output før det sendes til browseren - antag at alt input er ondsindet
- ✓Brug htmlspecialchars() eller htmlentities() med ENT_QUOTES flag for HTML-kontekst
- ✓Implementer Content Security Policy (CSP) headers for at begrænse script-eksekveringer
- ✓Brug HTTP-only og Secure flags på cookies for at forhindre JavaScript-adgang
- ✓Validér og sanitér input på server-side - client-side validering er ikke nok
- ✓Brug template engines med automatisk escaping (Twig, Blade)
- ✓Undgå at bruge eval(), innerHTML eller document.write() med brugerinput
- ✓Implementer X-XSS-Protection header (selvom moderne browsere har bedre beskyttelse)
- ✓Brug contextual output encoding baseret på hvor data vises (HTML, JavaScript, CSS, URL)
- ✓Implementér strict input validation med whitelists hvor muligt
- ✓Brug X-Content-Type-Options: nosniff header for at forhindre MIME-sniffing
- ✓Sanitér rich text editors med biblioteker som HTML Purifier
- ✓Implementér CSP nonce eller hash-baseret script whitelisting
- ✓Opdater regelmæssigt JavaScript libraries for at undgå kendte XSS-sårbarheder
Sårbar Kode (UNDGÅ)
Brug ALDRIG denne kode i produktion!
<?php
// SÅRBAR KODE - Brug ALDRIG dette i produktion!
// 1. Reflected XSS - Direkte echo af brugerinput
$name = $_GET['name'];
echo "<h1>Welcome, " . $name . "!</h1>";
// URL: page.php?name=<script>alert('XSS')</script>
// Dette vil eksekevere scriptet i brugerens browser
// 2. Stored XSS - Gemmer ondsindet input i database
$comment = $_POST['comment'];
$query = "INSERT INTO comments (text) VALUES ('$comment')";
mysqli_query($conn, $query);
// Senere når kommentarer vises:
$result = mysqli_query($conn, "SELECT text FROM comments");
while ($row = mysqli_fetch_assoc($result)) {
echo "<p>" . $row['text'] . "</p>";
// Hvis comment indeholder <script>steal_cookies()</script>
// vil det køre hver gang nogen ser kommentaren!
}
// 3. XSS i HTML-attributter
$search = $_GET['q'];
echo "<input type='text' value='" . $search . "'>";
// URL: page.php?q=' onload='alert(document.cookie)
// Resulterer i: <input type='text' value='' onload='alert(document.cookie)'>
// 4. XSS i JavaScript-kontekst
$user_data = $_GET['data'];
echo "<script>var userData = '" . $user_data . "';</script>";
// URL: page.php?data='; alert('XSS'); //
// Resulterer i: var userData = ''; alert('XSS'); //';
// 5. DOM-based XSS via PHP
$callback = $_GET['callback'];
echo "<script>" . $callback . "(data);</script>";
// URL: page.php?callback=maliciousFunction
// 6. XSS i href-attribut
$url = $_GET['url'];
echo "<a href='" . $url . "'>Click here</a>";
// URL: page.php?url=javascript:alert('XSS')
// eller: page.php?url=data:text/html,<script>alert('XSS')</script>
// 7. XSS gennem CSS
$color = $_GET['color'];
echo "<div style='color: " . $color . "'>Text</div>";
// URL: page.php?color=red; background: url(javascript:alert('XSS'))
// 8. Usikker JSON output
header('Content-Type: application/json');
echo json_encode(['message' => $_POST['message']]);
// Hvis Content-Type ikke sættes korrekt eller browseren gætter forkert
?>Sikker Kode (ANBEFALET)
Best practices for sikker implementation
<?php
// SIKKER KODE - Best practices for XSS prevention
// 1. Korrekt output escaping med htmlspecialchars()
$name = $_GET['name'] ?? 'Guest';
// ENT_QUOTES escaper både enkelt- og dobbelt-quotes
// ENT_HTML5 understøtter HTML5
echo "<h1>Welcome, " . htmlspecialchars($name, ENT_QUOTES | ENT_HTML5, 'UTF-8') . "!</h1>";
// 2. Stored XSS prevention med sanitering og escaping
$comment = $_POST['comment'] ?? '';
// Validér længde
if (strlen($comment) > 1000) {
die("Comment too long");
}
// Brug prepared statement til at gemme (forhindrer også SQL injection)
$stmt = $pdo->prepare("INSERT INTO comments (text, created_at) VALUES (?, NOW())");
$stmt->execute([$comment]);
// Når data vises: ALTID escape output
$stmt = $pdo->query("SELECT text, created_at FROM comments");
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
echo "<p>" . htmlspecialchars($row['text'], ENT_QUOTES, 'UTF-8') . "</p>";
echo "<small>" . htmlspecialchars($row['created_at'], ENT_QUOTES, 'UTF-8') . "</small>";
}
// 3. Sikker håndtering af HTML-attributter
$search = $_GET['q'] ?? '';
echo "<input type='text' value='" . htmlspecialchars($search, ENT_QUOTES, 'UTF-8') . "'>";
// 4. Sikker JavaScript-variabel
$user_data = $_GET['data'] ?? '';
// Brug json_encode() for at escape JavaScript-kontekst korrekt
echo "<script>var userData = " . json_encode($user_data, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT) . ";</script>";
// 5. URL validation og sanitering
$url = $_GET['url'] ?? '';
// Whitelist tilladte protocols
$allowed_protocols = ['http', 'https'];
$parsed_url = parse_url($url);
if (isset($parsed_url['scheme']) && in_array($parsed_url['scheme'], $allowed_protocols, true)) {
echo "<a href='" . htmlspecialchars($url, ENT_QUOTES, 'UTF-8') . "'>Click here</a>";
} else {
echo "<a href='#'>Invalid URL</a>";
}
// 6. Rich text med HTML Purifier
require_once 'HTMLPurifier.auto.php';
$config = HTMLPurifier_Config::createDefault();
$purifier = new HTMLPurifier($config);
$dirty_html = $_POST['content'] ?? '';
$clean_html = $purifier->purify($dirty_html);
echo $clean_html; // Sikkert at outputte
// 7. Content Security Policy header
header("Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-" . base64_encode(random_bytes(16)) . "'; object-src 'none'; base-uri 'self';");
// 8. Sikre cookie settings
ini_set('session.cookie_httponly', 1);
ini_set('session.cookie_secure', 1);
ini_set('session.cookie_samesite', 'Strict');
// 9. Security headers
header('X-Content-Type-Options: nosniff');
header('X-Frame-Options: DENY');
header('X-XSS-Protection: 1; mode=block');
?>Almindelige Fejl
- ⚠At glemme at escape output i templates og tro at input-validering er nok
- ⚠At bruge strip_tags() som primær beskyttelse - dette kan omgås og fjerner ikke alle XSS-vektorer
- ⚠At escape output kun i HTML-kontekst, men glemme JavaScript, CSS og URL-kontekster
- ⚠At stole på client-side validering eller filtering - alt skal valideres på server-side
- ⚠At tro at htmlentities() uden ENT_QUOTES flag beskytter mod XSS i attributter
- ⚠At implementere hjemmelavede sanitizing-funktioner i stedet for at bruge etablerede biblioteker som HTML Purifier
Forebyggelsesteknikker
- 🛡️Brug context-aware output encoding: htmlspecialchars() for HTML, json_encode() for JavaScript
- 🛡️Implementér Content Security Policy (CSP) headers med strict-dynamic og nonces
- 🛡️Brug template engines med auto-escaping som Twig eller Blade
- 🛡️Implementér HTTP-only, Secure og SameSite flags på alle cookies
- 🛡️Brug HTML Purifier eller lignende biblioteker for rich text content
- 🛡️Implementér input validation med whitelists på server-side
- 🛡️Brug Trusted Types API i moderne browsere for DOM-manipulation
- 🛡️Implementér security headers: X-Content-Type-Options, X-Frame-Options
Testing Metoder
- 🔍Manuel testing med XSS payloads i alle input-felter: <script>alert(1)</script>, \"'><script>alert(1)</script>
- 🔍Automated scanning med værktøjer som Burp Suite, OWASP ZAP eller XSSer
- 🔍DOM-based XSS testing med DOM Invader eller manual JavaScript analyse
- 🔍Code review med fokus på alle echo, print og template output statements
- 🔍Brug af browser extensions som XSS Hunter til at finde blind XSS
Quick Info
- ⚠Content Injection - Injection af ondsindet indhold uden script-eksekvetion
- ⚠HTML Injection - Manipulation af HTML-struktur
- ⚠CSRF - Cross-Site Request Forgery som ofte kombineres med XSS
⚠️Sikkerhedsadvarsel
Sikkerhedssårbarheder kan have alvorlige konsekvenser. Test altid grundigt i et sikkert miljø og implementer alle anbefalede forebyggelsesteknikker.