Cross site scripting in HTTP-01 ACME challenge implementation
Description
This vulnerability occurs when an ACME HTTP-01 challenge implementation fails to properly sanitize or encode user-controlled input before rendering it in web pages. The HTTP-01 challenge is part of the ACME protocol used by certificate authorities like Let's Encrypt to verify domain ownership. When the challenge response endpoint reflects untrusted data without proper encoding, attackers can inject malicious JavaScript that executes in victims' browsers, leading to Cross-Site Scripting (XSS) attacks.
Remediation
Implement proper input validation and context-aware output encoding for all user-controlled data in ACME HTTP-01 challenge responses:
1. HTML Entity Encoding: Encode all special characters before rendering challenge tokens or related data in HTML contexts:
// Example in JavaScript/Node.js
function encodeHTML(str) {
return str.replace(/&/g, '&')
.replace(//g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
// Example in Python
import html
safe_output = html.escape(user_input)
// Example in PHP
$safe_output = htmlspecialchars($user_input, ENT_QUOTES, 'UTF-8');
2. Content Security Policy (CSP): Implement strict CSP headers to prevent inline script execution:
Content-Security-Policy: default-src 'self'; script-src 'self'; object-src 'none'
3. Input Validation: Validate that ACME challenge tokens match expected formats (alphanumeric characters) and reject unexpected input.
4. Use Security Libraries: Leverage established security libraries and frameworks that provide automatic output encoding rather than implementing custom solutions.
5. Security Testing: Regularly test ACME challenge endpoints with XSS payloads to verify proper encoding is applied.