flawopen.com/Cross-Site Scripting/C/C++

Cross-Site Scripting in C/C++

High CWE-79 Draft — pending review
ELI5

Imagine a guestbook where visitors write a public note. Stored XSS is like someone writing a note that isn't just text — it's a hidden trick that makes the guestbook page itself start doing things, like stealing the next visitor's login session, the moment anyone opens the page to read it.

Key terms on this page
output encoding
Converting characters that have special meaning in HTML (like < and >) into harmless equivalents before inserting untrusted text into a page, so the browser displays it as text instead of running it as markup or script.
DOM
The in-memory tree structure a browser builds from a page's HTML — where an element's innerHTML is set determines whether inserted content is rendered as inert text or executable markup.

What's happening

Cross-site scripting happens when untrusted input reaches the rendered page without proper output encoding. C/C++ web contexts (CGI programs, embedded HTTP servers) build HTML responses manually — there's no template engine providing default escaping, so every output point needs its own explicit encoding.

Real-world impact

In 2005, an 19-year-old user exploited a stored XSS flaw on MySpace to create the "Samy" worm — a script that added itself to every profile that viewed it, infecting over a million profiles within about 20 hours and forcing MySpace offline to contain it. It remains one of the most-cited demonstrations of how quickly stored XSS can self-propagate.

Source: widely documented in security industry retrospectives — see References below.

Vulnerable vs. fixed

VULNERABLE
/* comment text written with no encoding */
fprintf(response,
  "<div>%s</div>", comment_text);
FIXED
/* encode before insertion */
char *encoded = html_encode(comment_text);
fprintf(response,
  "<div>%s</div>", encoded);
free(encoded);

Why the fix works

html_encode() (a custom function or a library like libxml2's escaping utilities) converts <, >, &, and quote characters into their entity equivalents before the string is written to the response — the browser displays them as text rather than parsing them as tags. fprintf performs no such transformation; it writes the format arguments exactly as given.

C/C++-specific gotchas

No standard library HTML-aware string handling exists at all

Unlike higher-level languages, C/C++ has nothing built in that understands HTML escaping — every project either writes its own encoding function or links a library for it, and it's easy for one output path to be missed.

Buffer safety and encoding are two separate concerns, again

Just as with SQL injection, building output with sprintf into a fixed buffer risks a buffer overflow independent of whether the content is HTML-encoded — fixing one doesn't fix the other, and both need addressing.

CGI environment variables are an easy-to-forget untrusted-input source

QUERY_STRING, HTTP_REFERER, and other CGI environment variables are attacker-controlled exactly like a parsed request parameter in a higher-level framework — code that reads them directly into output without encoding has the same exposure.

Common misconceptions

"This is a native binary, not a script — browser-side attacks don't apply"

The vulnerability lives in the HTML the program generates and sends to a browser, not in the program's own execution model — a C program that emits unencoded HTML is exactly as exploitable as a scripting-language equivalent.

"I bounds-checked the buffer, so the output is safe"

Buffer safety and HTML-encoding safety are independent — a perfectly bounds-checked snprintf call still produces exploitable output if the inserted content isn't encoded.

How to check if you're affected

grep -rn "fprintf(.*<\|sprintf(.*<" --include="*.c" --include="*.cpp" .
Treat every hit that writes HTML with an interpolated value as a candidate for review — confirm the value passes through an encoding function before this line.

Prevention checklist

FAQ

Is this the same bug as SQL injection?

Same underlying shape — untrusted data mixed into a command's structure without encoding — but the target and damage differ: SQL injection targets the database, XSS targets other users' browsers.

Does this apply to embedded HTTP servers used in IoT/device firmware?

Yes — a device's local admin web UI, often built the same way with hand-written HTML generation, carries the identical risk if it reflects any request-derived value unencoded.

References

View in: Python JavaScript Go Java PHP C# Ruby C/C++ Rust Kotlin Swift Solidity (N/A)
Also see: SQL Injection Command InjectionBuffer Overflow