XSS (Cross-Site Scripting) detection has long been a challenge, balancing accuracy with avoiding excessive false positives. Traditionally, this meant creating specific reflection based string matchers for each target, leading to complex and hard-to-maintain configurations. But with headless modes, we can simplify and improve XSS detection in a more intuitive and efficient way.
In this post, we'll explore how to leverage nuclei headless mode to detect XSS payloads more easily and accurately, using the waitdialog
action. This approach significantly reduces the complexity of matching specific server responses, while maintaining high accuracy.
The Challenge of XSS Detection
For those who've worked with XSS detection templates, the complexity of configuring specific matchers
for every scenario is all too familiar. It becomes especially cumbersome when analyzing unique technologies or servers. Often, security engineers have to conduct additional research, using tools like Shodan or setting up vulnerable environments to fine-tune their matchers. While this approach improves accuracy and reduces false positives, it places a heavy burden on the user.
For example, look at the following template snippet:
yaml
1matchers-condition: and2matchers:3- type: word4part: body5words:6- 'topic_id: "</script><script>alert(document.domain)</script>'7- "window.erxesEnv"8condition: and
In this method, specific keywords in the response body are used to check if the injected script is reflected (although this doesn’t guarantee that the payload will actually be triggered). This approach requires detailed knowledge of the target's structure and can easily fail if the structure changes - even a little.
Enter Headless Mode
Nuclei's headless mode lets us mimic real user actions on a web page, including running JavaScript. This opens up a new way to detect XSS: instead of just looking for specific HTML output or script tags, we can check if an XSS payload actually triggers a JavaScript dialog (like alert
).
The waitdialog
action listens for these dialogs on a page, showing us clearly if an XSS payload has been executed. This method simplifies detection by focusing on the behavior of the payload rather than the page's source code.
Implementing Headless XSS Detection
Let's take a look at how we can implement this in practice.
The Old Way: Matcher-Based Detection
Before headless mode, detecting XSS relied heavily on matchers, as seen below:
yaml
1id: CVE-2021-3285323# ... SNIPPED ...45http:6- method: GET7path:8- "{{BaseURL}}/widgets/knowledgebase?topicId=%3C%2Fscript%3E%3Cscript%3Ealert%283%2B4%29%3C%2Fscript%3E"910matchers-condition: and11matchers:12- type: word13part: body14words:15- 'topic_id: "</script><script>alert(3+4)</script>'16- "window.erxesEnv"17condition: and1819- type: word20part: header21words:22- text/html2324- type: status25status:26- 200
In this older method, you had to define the HTTP headers and exact patterns to match the payload. While it works, the setup is more complicated because you need to create separate matchers
for each different environment.
The New Way: Headless Dialog Detection
With headless mode, we can simplify this process by detecting the JavaScript execution directly:
yaml
1id: CVE-2021-3285323# ... SNIPPED ...45headless:6- steps:7- args:8url: "{{BaseURL}}/widgets/knowledgebase?topicId=%3C%2Fscript%3E%3Cscript%3Ealert%283%2B4%29%3C%2Fscript%3E"9action: navigate1011- action: waitdialog12name: reflected_topicId_query1314matchers:15- type: dsl16dsl:17- reflected_topicId_query == true18- reflected_topicId_query_message == "7" # 3+419condition: and
Here, instead of searching for specific HTML content or headers, we use the waitdialog
action to wait for a JavaScript dialog to pop up. If the dialog gets triggered, the matcher checks if it matches the expected result (like alert(3+4)
).
waitdialog
action has been available since Nuclei v3.3.2 (bump now!), and you can refer to the documentation for more details on its usage.cli
1$ nuclei -t headless-xss.yaml -target https://erxes.xss -headless23__ _4____ __ _______/ /__ (_)5/ __ \/ / / / ___/ / _ \/ /6/ / / / /_/ / /__/ / __/ /7/_/ /_/\__,_/\___/_/\___/_/ v3.3.289projectdiscovery.io1011[INF] Current nuclei version: v3.3.2 (latest)12[INF] Current nuclei-templates version: v9.9.4 (latest)13[WRN] Scan results upload to cloud is disabled.14[INF] New templates added in latest release: 5915[INF] Templates loaded for current scan: 116[WRN] Loading 1 unsigned templates for scan. Use with caution.17[INF] Targets loaded for current scan: 118[CVE-2021-32853] [headless] [critical] https://erxes.xss/widgets/knowledgebase?topicId=%3C%2Fscript%3E%3Cscript%3Ealert%283%2B4%29%3C%2Fscript%3E
-headless
option (disabled by default).Benefits of Headless Detection
- Higher Accuracy: It listens for real script execution, so you get better results with fewer false positives.
- Reduced Complexity: No need to create detailed matchers for each server or target. Instead, it focuses on how the payload behaves, not just the response structure.
- Consistency: Whether you're dealing with a simple website or a complex application, headless mode provides consistent XSS detection every time.
Wrapping Up
Integrating headless mode into XSS detection is a game-changer, making things easier and more accurate. With the waitdialog
action, we can skip the headaches of traditional reflection based detection. No more tweaking detection for every server or technology—just straightforward, reliable XSS detection.
By combining headless mode with dialog handling, users can create simpler detection templates that focus on how XSS payloads behave. This approach cuts down the complexity and boosts reliability.
Headless mode is the future of XSS detection, and this approach brings us one step closer to making it easier for everyone.
References
You can also join our Discord server. It's a great place to connect with fellow contributors and stay updated with the latest developments. Thank you, once again!
By leveraging Nuclei and actively engaging with the open-source community, or by becoming a part of the ProjectDiscovery Cloud Platform, companies can enhance their security measures, proactively address emerging threats, and establish a more secure digital landscape. Security represents a shared endeavor, and by collaborating, we can consistently adapt and confront the ever-evolving challenges posed by cyber threats.