Course: WEB PROGRAMMING & APPLICATIONS — 503073
Topic: Topic 6 — Web Security & Vulnerability Mitigation
Semester: 2, Academic Year 2025–2026
Instructor: Dr. Van-Vang Le
Inkwell is a blogging platform built in two versions to demonstrate common web security vulnerabilities and their mitigations:
| File | Description |
|---|---|
vulnerable.html |
Intentionally insecure version — contains XSS, SQL Injection, CSRF, plaintext passwords, missing CSP |
inkwell-hardened.html |
Fully hardened version — all vulnerabilities mitigated |
The vulnerable version is for educational demonstration only. Never deploy it on a real server.
No installation required. Both versions run entirely in the browser as static HTML files.
- Download both HTML files from this repository
- Open either file directly in your browser:
- Windows: Double-click the file, or drag it into Chrome/Firefox/Edge
- Mac: Double-click the file, or right-click → Open With → Browser
- Linux:
xdg-open vulnerable.html
Or use the address bar:
file:///C:/Users/YourName/Downloads/vulnerable.html
file:///C:/Users/YourName/Downloads/inkwell-hardened.html
Chrome or Firefox (latest version). Both files are tested on Chrome 124+.
Use these accounts to log in to either version:
| Password | Role | |
|---|---|---|
eleanor@inkwell.io |
inkwell2024 |
Author (has existing posts) |
marcus@example.com |
writer123 |
Author (has existing posts) |
You can also register a new account on either version.
Where: Register page → Full name field
Payload:
<img src=x onerror=alert('XSS!')>
- Vulnerable: Alert dialog fires — script executed ❌
- Hardened: Name displayed as plain text — attack blocked ✅
Where: Sign in page → Email field
Payload:
' OR '1'='1' --
Password: (leave blank or type anything)
- Vulnerable: Logs in as Eleanor Voss with no valid credentials ❌
- Hardened: Returns "Incorrect email or password" ✅
Where: Open any post → Responses box
Payload:
<script>alert('Stored XSS!')</script>- Vulnerable: Alert fires every time the post is viewed ❌
- Hardened: Comment displays as literal text ✅
Where: Sign in page → Browser DevTools (F12) → Elements tab
Steps:
- Find the hidden input:
<input type="hidden" id="login-csrf" value="..."> - Change the value to anything:
faktoken123 - Click Sign in
- Vulnerable: No token exists — any request accepted ❌
- Hardened: Returns "Invalid CSRF token. Refresh and try again." ✅
Where: Sign in page
Steps: Enter the wrong password 5 times in a row
- Vulnerable: Unlimited attempts allowed ❌
- Hardened: Login locked for 15 seconds after 5 failed attempts ✅
Where: Open the HTML files in a text editor (VS Code, Notepad++)
- Vulnerable: Search for
password:— passwords stored as plaintext strings ❌ - Hardened: Search for
passwordHash:— stored assalt:hash(salt+password+pepper)✅
web-security-demo/
├── vulnerable.html # Vulnerable Inkwell app
├── inkwell-hardened.html # Hardened Inkwell app
├── README.md # This file
├── report.docx # Full academic report (Word)
└── presentation.pptx # Presentation slides (PowerPoint)
| Vulnerability | Vulnerable Approach | Hardened Fix |
|---|---|---|
| XSS | element.innerHTML = userInput |
element.textContent = userInput |
| SQL Injection | String concatenation into query | Parameterized query equivalent |
| CSRF | No token | Random 48-char session token validated on every form submit |
| Password Storage | Plaintext (password: 'abc123') |
Salt + djb2 hash (simulating bcrypt) |
| Content Security Policy | No CSP header | Content-Security-Policy meta tag |
| Brute Force | Unlimited login attempts | Rate limit: lock after 5 failures for 15 seconds |
| Information Leakage | Specific error messages | Generic "Incorrect email or password" for all auth failures |
- OWASP Top 10 (2021)
- OWASP XSS Prevention Cheat Sheet
- OWASP SQL Injection Prevention
- OWASP CSRF Prevention Cheat Sheet
- OWASP Password Storage Cheat Sheet
- MDN — Content Security Policy
| Name | Student ID |
|---|---|
| [Nguyen Le Quang Vinh] | [524H0205] |
| [Nguyen Van Minh Tri] | [523H0187] |
Submission Date: [15/05/2026]