Cross-Site Scripting

TL;DR: Dom, reflected, and stored cross-site scripting

When I was in college around ’08 – ’09, I stumbled my way into becoming a freelance web designer. Like most millennials, I learned the basics of coding largely through MySpace and AngelFire. Pages would play your favorite emo song when people visited with fireworks or pink sparkles falling down the screen like glitter. You could find templates around the web, but most sites were made with pretty basic HTML and CSS. I was working my receptionist job at Wolfram Research when my boss, Maggie, asked if I could run the website for her lesbian choir group. Being the outspoken young lesbian I was, I jumped at the opportunity. That was my first experience with content management systems, Drupal. It used to be that you’d upload your site files via FTP and designate a folder in Windows as a place to sync up with the web server. Needless to say, I had no idea what I was doing. I’m a pretty quick learner, so I managed to get something going for them, but I could only procrastinate so long before they decided to go with someone else.

I honestly can’t remember how, but I managed to meet up with a man whose name I have forgotten who owned a graphic design business called DreamScape Designs. He hired me to do a website for a local painting company at $10, and that’s how I accidentally stumbled my way into being a freelance web designer. At the time, most basic websites were written in a combination of HTML and CSS. Over the next couple of years, more and more websites started using Java and/or JavaScript, which I didn’t know how to do. That was the end of my web design career. It was a weird time in my life, so I never did end up learning JavaScript.

JavaScript is a client-side programming language used to add interactive elements like dynamically updated content, multimedia, animated images, button clicks, form validation, and any other animated or interactive elements you can think of. In 2025, JavaScript is a core technology on the web and is used by about 98.8% of all websites. As with any new technology, more advance tech means more advanced vulnerabilities. One such vulnerability is called Cross-Site Scripting (XSS). CROSS-SITE SCRIPTING (XSS)

A typical web application works by receiving HTML code from the back-end server and rendering it on the client side. If a site does not properly sanitize user input, say on a contact form, we can take advantage of that vulnerability by entering some code into the form. We can execute JavaScript code on the client-side to capture cookies or log in data, change the appearance of a web page, or even create fake login pages.

There are three different types of XSS vulnerabilities that we must understand before learning how to use and identify XSS vulnerabilities.

The first, and most critical, type is Stored XSS, sometimes called Persistent XSS. Stored XSS happens when the payload we inject gets stored on the back-end server or database, which means that the malicious script will be run when any user visits the site. This is the most critical type of XSS because it affects a wider audience and is often very difficult to get rid of.
Reflected XSS vulnerabilities occur when our input is processed on the back-end and returned to us without any sanitization. Reflected XSS vulnerabilities are non-persistent, meaning they will not carry over to other pages or users.
DOM-based XSS vulnerabilities are completely processed on the client-side via JavaScript. DOM XSS occurs when JavaScript is used to change the page source through the Document Object Model (DOM). This is also a non-persistent vulnerability.

XSS vulnerabilities are executed solely on the client-side and do not change the back-end server. STORED XSS

Lets look at the website above. It looks like we have a reddit type clone of the subreddit r/mightJustWork. We see the question at the top with some fun answers, then a text input at the bottom where we can submit our own crazy idea. To try to determine whether this site is vulnerable, lets try entering a basic HTML header script using the

tag. If we type

test

and submit, we see the text posted like before, but the size has grown to the size of a heading. If we open the page in two different containers, we can see that the heading script has persisted across multiple users.

Beautiful. So we know that we are able execute at least some code, which will be stored and executed for anyone who visits the website. This type of code injection is one thing hackers will use to deface a website by changing colors, backgrounds, text, and images. It may even be possible to inject code that will grab malicious code or malware from an external source and execute that code each time the page is visited.

We can also inject some JavaScript. Using the ‘prompt’ command, we can create a pop up prompt each time the page loads.

Since this is a stored XSS vulnerability, the prompt will appear for each user who visits the site. REFLECTED XSS

In this case we have a to-do list with a text input. If we submit a test input, we can see that our input is reflected back on the page in single quotes. It looks like our input is not being sanitized at all, just reflected. Lets try some JavaScript code to see if we can execute some scripts.

It looks like our script was executed successfully. If we look at the source code, we can see that it does contain our script. The text inside the