DEV Community

Manuel Doncel Martos
Manuel Doncel Martos

Posted on

Practicing Basic Concepts On Web Security

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.

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 + "'"
Enter fullscreen mode Exit fullscreen mode

Exploitation

An attacker can bypass authentication by injecting SQL logic:

email: admin' --
password: anything
Enter fullscreen mode Exit fullscreen mode

This turns the query into:

SELECT * FROM users WHERE email = 'admin' --' AND password = 'anything'
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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
}
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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)