Why XSS Is Different
Priya opens the session with a question: "Who do you trust more β a stranger on the street, or your bank's website?" The developers all agree: the bank's website. "That's the problem," she says. "Your browser trusts websites too. And attackers know it."
She explains the fundamental concept: Cross-Site Scripting β abbreviated XSS, not CSS, because Cascading Style Sheets claimed that abbreviation first β is not an attack on the server. It's an attack on the user, delivered through the server. The attacker's goal is to get their script running in the victim's browser, and they achieve it by hiding that script inside a trusted website the victim already believes is safe. The browser sees script from the trusted site's domain β or what appears to be the trusted site's domain β and executes it without hesitation. "The attacker doesn't need to break into the server," Priya says. "They just need the server to pass their code to the victim's browser. And a lot of servers will do exactly that if the developer isn't careful."
JavaScript β The Weapon of Choice
Priya opens a browser and shows the team a simple demo. "What makes XSS practical is JavaScript. Every browser supports it. Nearly every user has it enabled. And JavaScript running in a browser can read session cookies, capture keystrokes, redirect the user, make requests on their behalf, and send data anywhere the attacker chooses β all silently, all without the victim seeing anything unusual."
She draws the basic attack chain on the whiteboard. The attacker crafts a malicious script. They find a way to get that script into a page the victim will view β either by embedding it in a link or storing it on the server. The victim visits the page or clicks the link. The browser loads the page, encounters the script, and executes it β because the script appears to come from the trusted site. The script runs silently, collecting cookies, session IDs, or credentials, and transmitting them to the attacker. "The victim has no idea," Priya says. "They visited their normal website. Nothing looked wrong. But their session is now in someone else's hands."
The Reflected Attack β One Link, One Victim
Priya explains the first type: non-persistent XSS, also called reflected XSS. "Imagine a site has a search box. You type 'laptops,' the page shows results, and in the header it says: You searched for: laptops. Where does that 'laptops' come from?" The team confirms: from the URL, passed back from the search input. "Right. Now what if instead of 'laptops,' the URL contained a JavaScript tag? If the site puts whatever's in the URL directly into the page without checking it, the browser sees a script and runs it."
The attack flow: the attacker finds a vulnerable search field or URL parameter on a legitimate site. They craft a malicious link β the legitimate site's URL with a script embedded in the query parameter. They email this link to a target. The target clicks the link (it looks like it's going to a real website they know). The legitimate site's server reflects the script back in the response. The victim's browser executes the script, which sends their session cookie to the attacker's server. "The key word is reflected," Priya says. "The attacker's code hits the server, the server bounces it back, and the victim's browser fires it. The server is innocent β it just passed along what it received without checking. The victim is the one who pays."
The Stored Attack β Everyone Gets It
The second type, Priya explains, is persistent XSS β also called stored XSS. "Same idea, but far more dangerous reach. Instead of sending a crafted link to one victim, the attacker posts their script directly onto a site that stores user content. A forum, a social media platform, a comment section. The script is now part of the site's own database. Every user who loads that page gets the script served to them automatically β no crafted link required."
She walks through the social media scenario. An attacker posts a comment on a public forum. The comment looks normal but contains embedded JavaScript. Every user who reads the comment has the script execute in their browser silently. On social networks, the script can go further β it can be written to automatically re-post the comment to the viewer's own profile. Now every person who follows the viewer sees it, and the script propagates to their browsers too. "In the right environment," Priya says, "a single stored XSS post can spread like a virus β self-replicating across the social graph. We've seen this in the real world. Thousands of accounts compromised in hours from one malicious post."
The Subaru Hack β One Token to Rule Them All
Priya pulls up a case study from June 2017. Security researcher Aaron Guzman was examining Subaru's online vehicle management portal. When a user logged in, they received an authentication token that allowed them to manage their vehicle remotely. The first problem: this token never expired. Unlike well-designed authentication tokens that expire after hours or days and require re-authentication, Subaru's token was permanent. Whoever had it, had access forever.
The second problem: the token was overpowered. It didn't just allow you to manage your own vehicle β it allowed any service request the portal supported, including adding an email address to someone else's account. Once your email was on another user's account, the token granted you full access to their vehicle management too. The third problem β where XSS connected everything β was that the web front-end had an XSS vulnerability. An attacker could send a malicious link to a Subaru owner. If the owner clicked it, the XSS exploit ran in their browser, captured the authentication token, and sent it to the attacker. With that one token β permanent, omnipotent β the attacker could access any vehicle whose owner they'd targeted, forever. "The XSS wasn't the whole attack," Priya tells the team. "But it was the delivery mechanism. The token was the prize. XSS was the hand that reached in and took it."
Stopping the Script
The team asks how to defend against XSS. Priya gives them two perspectives: developer and user. "From the developer side, the most important control is input validation and output encoding. You never let user-submitted content be rendered as HTML or executed as script. Every piece of user input is treated as data β plain text β and encoded before it's sent back to the browser. The browser then displays it as text, not executes it as code." She adds: same principle as SQL injection. The vulnerability is the same root cause β treating untrusted input as code.
"For users: don't click links you don't fully trust, especially in email. If you're going to a website, type the address yourself or use a bookmark. Consider a browser extension that controls which domains can run JavaScript. And keep your browser updated β vendors patch XSS-related vulnerabilities regularly." She closes with the developer emphasis: "The user mitigations reduce exposure but don't fix the vulnerability. The fix lives in the code. If the application properly encodes output and validates input, it doesn't matter what the user does β their browser will never execute an attacker's script through your site."