Building (and Breaking) a Vulnerable Web App in Go + Vue.js
As developers, we often learn best by doing, and in cybersecurity, that means not just building secure systems, but also understanding how they break.
During the last months, I was on charge of explaining some of the OWASP vulnerabilities to my team, and for that I created a vulnerable web application using Go (backend) and Vue.js (frontend), designed to demonstrate some of the most common and dangerous web vulnerabilities.
- The project is available here: https://github.com/manuelarte/gowasp
- The README includes a step-by-step hands-on exploitation guide.
In this post, I’ll walk through the key vulnerabilities implemented in the app and how an attacker can exploit them.
🧨 1. SQL Injection
The vulnerability
SQL Injection occurs when user input is directly concatenated into SQL queries without proper sanitization or parameterization.
A typical vulnerable pattern looks like:
query := "SELECT * FROM users WHERE email = '" + email + "' AND password = '" + password + "'"
Exploitation
An attacker can bypass authentication by injecting SQL logic:
email: admin' --
password: anything
This turns the query into:
SELECT * FROM users WHERE email = 'admin' --' AND password = 'anything'
The password check is commented out, granting access without valid credentials.
In the vulnerable application, you can practice this vulnerability and try to log in without knowing the password.
Takeaway
Always use prepared statements or ORM parameter binding. Never trust raw user input.
🧬 2. Mass Assignment
The vulnerability
Mass assignment happens when user-controlled input is directly bound to a struct or model without filtering allowed fields.
Example:
json.NewDecoder(r.Body).Decode(&user)
If the User struct includes sensitive fields like isAdmin, an attacker can modify them.
Exploitation
A malicious request:
{
"email": "attacker@example.com",
"password": "123456",
"isAdmin": true
}
If the backend doesn’t explicitly restrict fields, the attacker becomes an admin by assigning himself as admin.
Takeaway
Use DTOs (Data Transfer Objects) or explicit field mapping. Never bind request bodies directly to domain models.
🔁 3. CSRF (Cross-Site Request Forgery)
The vulnerability
CSRF occurs when authenticated users unknowingly perform actions triggered by malicious websites.
If your app relies only on cookies for authentication and lacks CSRF protection, it's vulnerable.
Exploitation
An attacker can craft a hidden form:
<form action="https://yourapp.com/api/delete-account" method="POST">
<input type="submit" />
</form>
<script>
document.forms[0].submit();
</script>
If the victim is logged in, their browser will send the request with session cookies—deleting their account without consent.
Takeaway
Use CSRF tokens and validate them server-side. SameSite cookies help, but are not enough alone.
🧩 4. HTML Template Injection
The vulnerability
When user input is rendered into templates without proper escaping, attackers can inject malicious expressions.
In Go templates, unsafe usage might look like:
tmpl.Execute(w, userInput)
And in VueJS it can be used with v-html.
Exploitation
An attacker injects template syntax in part that renders user input.
In some engines, this can lead to:
- Data leakage
- Server-side execution
- XSS (if rendered in browser)
Takeaway
Always treat user input as untrusted. Use proper escaping and avoid rendering raw input in templates.
Why This Project Matters
Modern frameworks make it easier to build applications—but they don’t make them automatically secure. These vulnerabilities are still incredibly common in real-world systems.
By intentionally building insecure features, this project helps you:
- Understand how attacks actually work
- Recognize insecure coding patterns
- Learn how to defend against them effectively
🛠️ Try It Yourself
The repository includes a full walkthrough so you can:
- Run the vulnerable app locally
- Exploit each vulnerability step by step
- Understand the impact in a safe environment
👉 https://github.com/manuelarte/gowasp
Final Comments
Security is not a feature you apply from the beginning.
If you can break your own system, you’re already one step closer to building something resilient.
And if you haven’t tried breaking it yet… someone else eventually will.
Top comments (0)