Scan for Cross-Site Scripting vulnerabilities.
| 11 | |
| 12 | class XSSScanner(WebScannerModule): |
| 13 | """Scan for Cross-Site Scripting vulnerabilities.""" |
| 14 | |
| 15 | name = "xss" |
| 16 | description = "Test for reflected and DOM-based XSS vulnerabilities" |
| 17 | |
| 18 | SECLISTS_RELATIVE_PATHS = ( |
| 19 | "Fuzzing/XSS/robot-friendly/XSS-Jhaddix.txt", |
| 20 | "Fuzzing/XSS/robot-friendly/XSS-RSNAKE.txt", |
| 21 | "Fuzzing/XSS/robot-friendly/XSS-BruteLogic.txt", |
| 22 | ) |
| 23 | |
| 24 | # Built-in fallback payloads (benign probes that don't execute) |
| 25 | PAYLOADS = [ |
| 26 | '<script>alert(1)</script>', |
| 27 | '"><script>alert(1)</script>', |
| 28 | "'-alert(1)-'", |
| 29 | '<img src=x onerror=alert(1)>', |
| 30 | '"><img src=x onerror=alert(1)>', |
| 31 | '<svg onload=alert(1)>', |
| 32 | 'javascript:alert(1)', |
| 33 | '<body onload=alert(1)>', |
| 34 | '{{constructor.constructor("alert(1)")()}}', # Angular |
| 35 | '${alert(1)}', # Template injection |
| 36 | ] |
| 37 | |
| 38 | # Patterns to detect reflection |
| 39 | REFLECTION_PATTERNS = [ |
| 40 | r'<script>alert\(1\)</script>', |
| 41 | r'onerror\s*=\s*alert', |
| 42 | r'onload\s*=\s*alert', |
| 43 | r'javascript:alert', |
| 44 | ] |
| 45 | |
| 46 | def __init__( |
| 47 | self, |
| 48 | custom_payloads: list[str] | None = None, |
| 49 | seclists_path: str | None = None, |
| 50 | ): |
| 51 | super().__init__() |
| 52 | self.payloads = custom_payloads or load_wordlist( |
| 53 | self.SECLISTS_RELATIVE_PATHS, |
| 54 | fallback=self.PAYLOADS, |
| 55 | seclists_path=seclists_path, |
| 56 | ) |
| 57 | |
| 58 | async def run(self, target: Target) -> ScanResult: |
| 59 | """Scan target for XSS vulnerabilities.""" |
| 60 | result = self.create_result(target) |
| 61 | |
| 62 | url = self._build_url(target) |
| 63 | self.logger.info(f"Starting XSS scan on {url}") |
| 64 | |
| 65 | vulnerabilities = [] |
| 66 | |
| 67 | try: |
| 68 | async with HTTPClient() as client: |
| 69 | # Get the page first to find parameters |
| 70 | response = await client.get(url) |
no outgoing calls