DEV Community

Alem Djokovic
Alem Djokovic

Posted on

Web Application Security & XSS Mitigation write up

  1. Objective

The objective of this project was to understand how Cross-Site Scripting (XSS) attacks operate in real web environments and to demonstrate the difference between secure and insecure input-handling practices. The goal was to build two versions of the same web application, one intentionally vulnerable and one protected, to see how an attacker’s input functions differently on each. We conducted a controlled experiment with both reflected and stored XSS attacks, analyzed how the browser executed or blocked injected scripts, and documented the effectiveness of detection and prevention mechanisms such as input sanitization, output encoding, and Content Security Policy (CSP). By the end of the experiment, the expected outcome was a clear comparison between the vulnerable and secure implementations, showing how specific coding decisions directly impact security. Overall, the project demonstrates that XSS vulnerabilities are created from small oversights in input handling and that layered defensive strategies significantly reduce the risk of exploitation.

  1. Introduction

2.1 Overview of the Experiment

This experiment focuses on Cross-Site Scripting (XSS), which is a common and serious web application vulnerability that occurs when user input is not handled or displayed correctly by a browser. XSS attacks let an attacker inject malicious client-side scripts, usually JavaScript, into a trusted website, where the code then runs in the browser of an unsuspecting user. Since modern web applications rely heavily on dynamic user input, XSS continues to be one of the most widespread security problems in real-world systems.

The motivation for this experiment was to understand how XSS vulnerabilities happen at a basic level and to see how malicious input behaves in both insecure and secure environments. Instead of depending only on automated tools, this project took a hands-on approach by manually building both a vulnerable version and a protected version of the same website. This made it easier to clearly compare how different ways of handling user input can directly impact application security.

The experiment focused on two main types of XSS attacks: reflected XSS and stored XSS. Reflected XSS happens when malicious input is immediately sent back in an HTTP response, while stored XSS occurs when harmful content is saved on the server and later delivered to other users. Both attack types were demonstrated using simple form-based interactions to reflect how real web applications typically handle user input.

Previous research and industry reports consistently point to XSS as a high-risk vulnerability because it can compromise user sessions, steal sensitive information, and manipulate website content. Many existing solutions stress the importance of secure coding practices like input validation, output encoding, and browser-based protections such as Content Security Policy. This experiment builds on those approaches by showing, in a controlled environment, how these defenses work in practice and how they successfully prevent scripts from executing when they are implemented correctly.

Overall, this experiment offers a practical look at XSS attacks and their defenses, reinforcing the importance of securely handling user input and using layered security controls in modern web application development.

2.2 Problem Identification (Nature of Attack)

The primary security issue examined in this project is the improper handling of user-provided input, which can lead to Cross-Site Scripting vulnerabilities. XSS attacks happen when a web application sends untrusted input back to the browser without proper validation or encoding, allowing malicious scripts to run. Since the browser treats this content as coming from a trusted website, the injected scripts are executed with the same privileges as legitimate site code.

In this experiment, the vulnerability occurs when user input is directly placed into HTML responses or saved on the server and later displayed without being sanitized. This allows attackers to inject JavaScript code that runs within the context of the website. Once the script executes, it can carry out a variety of malicious actions that put both user security and the overall integrity of the application at risk.

Once an XSS vulnerability is successfully exploited, attackers can:

Execute arbitrary JavaScript within the victim’s browser
Steal session cookies or authentication tokens
Manipulate or deface website content
Redirect users to malicious or phishing websites
Exploit trusted user sessions without direct user interaction
Two types of XSS were examined in this project: reflected XSS and stored XSS. Reflected XSS happens when malicious input is included in a request and immediately sent back in the server’s response, which commonly occurs through URL parameters or form submissions. Stored XSS is considered more dangerous because the injected code is saved on the server, such as in a comment or message field, and then delivered to other users when the content is viewed. Since the payload remains stored, these attacks can last over time and impact a much larger number of users.

Existing research and real-world examples show that XSS vulnerabilities continue to exist mainly because secure coding practices are not applied consistently. Many web applications depend only on client-side validation or neglect proper output encoding, both of which attackers can easily bypass. This project addresses these issues by showing how XSS attacks work in a realistic setting and by highlighting the importance of handling input on the server side and applying proper output encoding.

By building both a vulnerable and a secure version of the same website, this project highlights the root causes of XSS vulnerabilities and shows how small design choices, like directly displaying user input, can lead to serious security risks. This analysis sets the groundwork for evaluating the technical approach and defense mechanisms covered in the sections that follow.

2.3 Technical Approach

This project implemented a controlled local testing environment to demonstrate and analyze Cross-Site Scripting (XSS) vulnerabilities and their mitigation. The environment was developed using PHP and Visual Studio Code, with PHP’s built-in development server used to host two separate web applications. To ensure safety and ethical testing, the setup operated entirely on localhost with no external network access. Two web environments were deployed: a deliberately vulnerable website running on localhost:8001 and a secure, hardened version running on localhost:8002. The vulnerable site was intentionally designed to echo unsanitized GET parameters directly back to the page and to store raw user input in a guestbook feature. This configuration allowed both reflected and stored XSS attacks to be demonstrated, where injected JavaScript payloads executed within the browser, highlighting the real-world risks of failing to validate or encode user input.

In contrast, the secure website implemented multiple defensive mechanisms to prevent XSS exploitation. Pattern-based input inspection was used to detect suspicious payloads, and all potentially malicious activity was logged server-side for visibility and auditing. Most importantly, user-supplied data was safely handled using HTML output encoding through PHP’s htmlspecialchars() function, ensuring that injected scripts were rendered harmless as plain text rather than executed. Additional input sanitization further reduced the attack surface by filtering dangerous characters before processing. Together, these controls effectively blocked both reflected and stored XSS attempts, demonstrating how layered defenses significantly improve web application security. This side-by-side comparison clearly illustrates the impact of secure coding practices and reinforces the importance of proper input handling, encoding, and logging in defending against common web-based attacks.

3.1 Network Topology, Configuration, and System Setup

This experiment used a single-host, isolated test environment where all components ran locally on one machine (laptop/desktop). No external network access was required because both web applications were hosted on localhost and accessed through the local browser. The topology is intentionally simple: the client (Google Chrome) sends HTTP requests to a local PHP development server, which serves two separate web applications, one intentionally vulnerable and one hardened, running on different ports. This design keeps testing safe, repeatable, and contained on one system while still representing a realistic client/server web interaction model.

Hardware Components:
1x Laptop/Desktop (single host)
Acts as the web server host, development workstation, and client browser
Minimum recommended: 8GB RAM, modern CPU (any typical student laptop is fine)
Software Components:
Operating System: Any desktop OS (Windows/macOS/Linux)
PHP runtime + local web server: PHP built-in development server (via XAMPP PHP)
Editor / IDE: Visual Studio Code
Browser (client): Google Chrome
Project folders (two applications):
vulnerable_site.html/ (intentionally insecure)
secure_site.html/ (hardened version with detection + encoding)
Directory Structure and Application Roles:
1) Vulnerable Web Application (vulnerable_site.html/)
Purpose: demonstrate how XSS occurs when input is not validated/encoded.

index.php — Reflected XSS demo (unsanitized GET input is echoed to the page)
stored.php — Stored XSS guestbook (user input written and later rendered)
comments.txt — stores unsafe/raw comments (demonstrates persistence)
2) Secure Web Application (secure_site.html/)
Purpose: demonstrate detection + prevention controls working together.

index.php — secure reflected handling (detection + output encoding)
stored.php — secure stored handling (detection + output encoding)
detection.php — pattern-based input inspection + server-side logging
comments.txt — stores comments (safe handling occurs on output/sanitization logic)
xss_log.txt — persistent log of detected XSS attempts
Port and Server Configuration (Critical Settings)
Two separate PHP servers were run simultaneously to keep environments independent:

Vulnerable site server
Command: php -S localhost:8001
URL: http://localhost:8001
Secure site server
Command: php -S localhost:8002
URL: http://localhost:8002
Key configuration choices:

Localhost binding (localhost) ensures traffic never leaves the machine.
Separate ports (8001/8002) prevent file overlap and make comparisons clean.
No external network requirement keeps testing safe and avoids accidental exposure.
3.2 Experiment Steps

Prerequisites (Software + Folder Setup)
Software used:

PHP (local runtime) — via XAMPP PHP (or any PHP install that supports php -S)
Visual Studio Code — to edit files
Google Chrome — to test reflected/stored behavior in a real browser
Project folders (two separate apps)
Create two directories (or clone your project into this structure):

Become a member
The vulnerable site was coded to directly display user input without sanitization. The reflected XSS page echoed GET input back to the browser, and the guestbook page stored and displayed raw user comments, making both reflected and stored XSS possible.

The secure site was coded with detection and prevention controls. Input was inspected for XSS patterns, suspicious attempts were logged, output was encoded using htmlspecialchars(), and a Content Security Policy was enforced to block script execution.

The vulnerable site was started by running php -S localhost:8001, and the secure site was started using php -S localhost:8002. Both sites were accessed using Google Chrome.

Reflected XSS was demonstrated on the vulnerable site by submitting a script payload, which executed immediately and displayed an alert. Stored XSS was demonstrated by submitting a malicious guestbook comment that executed on submission and page reload.

The same attacks were tested on the secure site. The payloads did not execute, warning messages were shown, and all attempts were logged, confirming that XSS attacks were successfully detected and blocked.

3.3 Results and Analysis

Testing against the vulnerable website confirmed that both reflected and stored XSS payloads managed to execute without any hindrance. Submitting alert(), JavaScript executed inline in the browser right away, causing the message to pop up, confirming that user input was being echoed back into what was probably a vulnerable website without any validation or encoding. In the stored XSS guestbook page, comments that had been written maliciously in raw form got saved and executed each time the page was refreshed, demonstrating how persistent XSS can repeatedly affect users who view the compromised page. These results reinforce how dangerous unsanitized user input becomes when it is embedded directly into HTML output.

In contrast, the secure version of the application blocked all tested payloads. Instead of executing, malicious input was encoded and displayed as plain text, and the system displayed warning messages when suspicious patterns were detected. Server-side logs consistently captured details about each attempted attack, providing insight into when and how XSS attempts were made. This demonstrated that both the detection algorithm and output encoding mechanisms were functioning properly. The CSP added a layer of defense by preventing inline scripts from running, even if an attacker attempted to bypass encoding protections.

Overall, the results showed a clear difference in the behaviors between the insecure version and the secure one. The vulnerable site allowed full script execution with minimal effort, while the secure site stopped every payload and maintained normal functionality. These findings highlight a strong correlation between proper input handling and system resilience, demonstrating that output encoding and CSP are particularly effective at reducing the risk of reflected and stored XSS attacks. The experiment also showed that using both prevention and detection made the system much stronger rather than depending on just one layer of defense.

  1. Protocols and Algorithms for Prevention, Detection, and Countermeasures

4.1 Prevention Mechanisms

The prevention mechanisms implemented in this project were designed to stop malicious scripts from executing in the user’s browser, even when an attacker attempts to inject harmful input. Rather than relying on a single security control, the secure implementation applied multiple preventative techniques to demonstrate a defense-in-depth approach against XSS attacks.

Protocols

The primary protocol implemented to prevent XSS attacks in this project was a Content Security Policy. The CSP restricts the sources from which scripts can be executed within the browser, allowing only trusted content originating from the application itself. By enforcing these restrictions at the browser level, the CSP prevents unauthorized or inline scripts from executing, even if malicious input is successfully injected into the page. This protocol strengthens the system’s defenses by adding a browser-enforced security layer that operates independently of server-side input handling. As a result, the CSP reduces the likelihood that injected scripts can execute and mitigates the impact of potential bypasses in application-level defenses.

Algorithms

To prevent XSS vulnerabilities at the application level, this project used a server-side output encoding approach based on HTML entity encoding. This method converts potentially dangerous characters, such as <, >, “, and ‘, into safe encoded versions before user input is displayed in the browser. Output encoding was chosen as the main prevention technique because it effectively stops malicious scripts without changing or removing the user’s input. By encoding the data immediately before it is sent to the browser, the application ensures that any injected payload is treated as plain text rather than executable code. This method helps protect against both reflected and stored XSS attacks and is widely considered a best practice in secure web development.

Implementation Details

The prevention techniques and algorithms were built directly into the server-side logic of the secure version of the website. Any user input that was going to be displayed was first passed through a sanitization function before being rendered. This ensured that both new input and previously stored data could not execute scripts when shown on the page, providing consistent protection across all secure pages.

In addition, a Content Security Policy was applied at the page level using browser-supported enforcement to add another layer of defense against script execution. One challenge during implementation was keeping the website’s normal functionality while still applying strict security measures. This was handled by allowing user input to be stored and displayed as expected, but only after it had been properly encoded. By combining output encoding with browser-level protections, the application remained usable while greatly reducing the risk of XSS attacks.

4.2 Detection Mechanisms

Monitoring Tools:

To monitor potential XSS attacks, the project relied mainly on server-side logging and browser developer tools. The secure site used a logging file (xss_log.txt) to record every suspicious input submitted by the user. This log helped track repeated attempts, identify payload patterns, and confirm if an attack was successfully blocked. In addition, Chrome Developer Tools were used during testing to inspect the page’s behavior, check for blocked scripts, and verify that encoded output was displayed correctly. Overall, these tools provided visibility into how the system responded to malicious input and made it easier to confirm whether the detection logic was working properly.

Detection Algorithms:

The detection algorithm used in the secure version of the website followed a pattern-matching approach. The program checked user input for common XSS indicators such as , event handlers like onload or onclick, and other high-risk characters or sequences seen in malicious payloads. When a match was found, the system flagged the input, displayed a warning message to the user, and wrote the attempt to the server log. Although this algorithm is not as advanced as machine-learning-based detection, it was effective for this experiment because it reliably caught typical XSS payloads and prevented them from executing. It also showed how even basic pattern detection can reduce risk when combined with other security measures.</p> <p>Implementation Process:</p> <p>The detection mechanisms were built into the secure site’s PHP files and ran automatically whenever input was submitted. Incoming data was passed through the detection function before being displayed on the page. If the input was flagged as suspicious, the system encoded the output, logged the event, and displayed a warning. During testing, small adjustments were made to reduce false positives, usually by narrowing which patterns trigger alerts and ensuring normal text input was not blocked. This process helped balance security and resulted in a detection system that was both effective and practical for this project.</p> <p>4.3 Countermeasures</p> <p>Immediate Actions:</p> <p>Once Cross-Site Scripting (XSS) vulnerabilities were detected, immediate response measures were implemented to limit system exposure and prevent further exploitation. All user inputs were validated and sanitized on both the client and server sides to block malicious payloads before processing. Suspicious inputs were rejected or cleaned to remove executable scripts. Output encoding was applied to ensure that user-generated content was rendered safely within the browser. By encoding dynamic data based on its context, the application prevented injected scripts from executing. Vulnerable code sections responsible for unsafe rendering were promptly patched to remove injection points. Additionally, temporary mitigation measures such as Web Application Firewall (WAF) rules were deployed to block known XSS payload patterns. These controls provided short-term protection while permanent fixes were implemented.</p> <p>Long-term Solutions:</p> <p>To provide sustained protection against XSS attacks, long-term security strategies were incorporated into the application design. Secure coding practices were enforced using modern frameworks that automatically escape dynamic content, reducing the risk of developer error.A strong Content Security Policy (CSP) was implemented to restrict script execution and limit trusted sources. By blocking inline scripts and enforcing source whitelisting, CSP significantly reduced the impact of potential XSS attacks. Regular security testing using Static and Dynamic Application Security Testing (SAST/DAST) tools was integrated into the development process. Secure input-handling libraries, safe template engines, and browser-level protections such as HttpOnly and SameSite cookies, along with HTTPS enforcement, further strengthened the application’s security posture.</p> <p>Implementation Strategy:</p> <p>The countermeasures were implemented using a layered security approach to provide defense in depth. Security controls were applied across multiple layers, including input handling, application logic, browser rendering, and network protection. Automated security testing tools were integrated into the CI/CD pipeline to enable continuous vulnerability detection. Logging and monitoring mechanisms were also implemented to detect abnormal script behavior and injection attempts in real time. Ongoing maintenance includes regular updates, code reviews, and security policy refinements, supported by continuous developer training.</p> <ol> <li>Conclusion</li> </ol> <p>This project demonstrated how Cross-Site Scripting attacks can compromise web applications when proper security controls are absent. By comparing a vulnerable application with a secured version, the experiment showed how reflected and stored XSS payloads can be used to inject scripts, manipulate user interactions, and expose sensitive data. The implementation of layered defenses, including input validation, output encoding, CSP enforcement, browser security settings, and continuous testing, resulted in a significant reduction in exploitable behavior. These results reinforce that XSS prevention requires multiple coordinated defenses rather than a single solution. Overall, the project highlights the importance of secure coding, proactive testing, and developer awareness in building resilient web applications. The findings contribute practical insights into effective XSS mitigation strategies.</p> <ol> <li>Future Recommendations</li> </ol> <p>To further enhance protection against Cross-Site Scripting (XSS) attacks, future work should focus on strengthening security throughout the development lifecycle. Adopting a Security-by-Design approach ensures that XSS prevention techniques are integrated during the earliest stages of application development rather than being addressed reactively. Automating security testing by incorporating Static and Dynamic Application Security Testing (SAST/DAST) tools into CI/CD pipelines would allow vulnerabilities to be detected before deployment. Additionally, continuously refining Content Security Policies can further restrict script execution and limit the impact of injection attempts. Regular code audits and penetration testing should be conducted to identify new or overlooked vulnerabilities as the system evolves. Ongoing developer training is also essential to keep teams informed about emerging XSS techniques and modern defensive practices. Strengthening user input controls through advanced sanitization libraries, secure template engines, and server-side validation frameworks can further reduce attack surfaces. Finally, implementing real-time monitoring and logging mechanisms would enable faster detection and response to suspicious script behavior, improving overall system resilience.</p> <p>References</p> <p>OWASP. (n.d.). Cross Site Scripting Prevention. OWASP Cheat Sheet. <a href="https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html">https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html</a></p> <p>OWASP. (2017). A7:2017 — Cross-Site Scripting (XSS). OWASP Top Ten 2017. A7:2017 — Cross-Site Scripting (XSS)</p> <p>OWASP. (2023). Testing for Reflected Cross Site Scripting. OWASP Web Security Testing Guide (WSTG). <a href="https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/07-Input_Validation_Testing/01-Testing_for_Reflected_Cross_Site_Scripting">https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/07-Input_Validation_Testing/01-Testing_for_Reflected_Cross_Site_Scripting</a></p> <p>OWASP. (2023). Testing for Stored Cross Site Scripting. OWASP Web Security Testing Guide (WSTG). <a href="https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/07-Input_Validation_Testing/02-Testing_for_Stored_Cross_Site_Scripting">https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/07-Input_Validation_Testing/02-Testing_for_Stored_Cross_Site_Scripting</a></p>

Top comments (0)