https://github.com/manuelarte/gowasp
Go application to explain some of the main 🌐 OWASP vulnerabilities ☣️
https://github.com/manuelarte/gowasp
golang owasp-top-10 training vulnerabilities
Last synced: 6 months ago
JSON representation
Go application to explain some of the main 🌐 OWASP vulnerabilities ☣️
- Host: GitHub
- URL: https://github.com/manuelarte/gowasp
- Owner: manuelarte
- Created: 2025-02-05T14:36:37.000Z (8 months ago)
- Default Branch: main
- Last Pushed: 2025-04-12T18:30:57.000Z (6 months ago)
- Last Synced: 2025-04-12T19:25:49.366Z (6 months ago)
- Topics: golang, owasp-top-10, training, vulnerabilities
- Language: Go
- Homepage:
- Size: 116 KB
- Stars: 5
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
Awesome Lists containing this project
README

# GOwasp
GOwasp is a deliberately vulnerable web application written in [Go](https://go.dev/). This project demonstrates some of the most common security vulnerabilities affecting web applications today, based on the [OWASP](https://owasp.org/) top 10. The goal is to learn security concepts by exploiting and then fixing these vulnerabilities.
🚀 Getting Started
To run the app, in the root directory type:
> make r
If you want to run it with Docker 🐳 use:
> make dr
## 🛠️ Application Overview
Once you have the application running, let's start first exploring the functionality provided by it.
### 🔑 Login/Signup Page
Navigate to to access the signup form [/users/signup][1]. Let's try to create a user, for example, with:
```
username: test
password: test
```### 🏠 Welcome Page
After you login or create an account, you are redirected to the [welcome][3] page. In this page you can see an intro blog, and also links to the latest posts. Let's click in one of the latest posts.
### 📝 Post Page
Clicking on a post takes you to its details page, where you can read the post, view comments, and submit your own comment. Try to submit a comment like:
```
very nice post!
```---
After this small guide, let's now try to hack this application.
## ☣️ Vulnerabilities
Let's explore different vulnerabilities by exploiting some of the functionalities that this app provides:
### 1. Create User - POST /users/signup
We are going to explote the vulnerabilities related to the endpoint to create a user in [/users/signup][1].
The vulnerabilities that we are going to check are:
+ [Weak Password Requirements](https://cwe.mitre.org/data/definitions/521.html)
+ [Weak Hash Algorithm](https://cwe.mitre.org/data/definitions/328.html)An HTTP client is provided in [users-signup.http](./tools/users-signup.http) to follow along.
#### 🔐 Weak Password Requirements
As you can see in [users_service.go](./internal/services/user_service.go), the only requirement for a password is to have *more than 4 characters* (`#1. Scenario`).
Let's try to improve that by adding **stronger requirements**:
+ minimum 8 characters, (let's set also a maximum password length of 256)
+ include non-alphanumerical charactersOnce you have implemented these restrictions, test them using the http client.
#### 🤖 Weak Hash Algorithm
A detailed explanation of this vulnerability can be found [here](https://knowledge-base.secureflag.com/vulnerabilities/broken_cryptography/weak_hashing_algorithm_vulnerability.html)
Run the http requests described in [#2. Scenario](./tools/users-signup.http) and:
+ Get the generated MD5 hashed password, and check how long does it take for a computer to decrypt it (e.g. https://10015.io/tools/md5-encrypt-decrypt#google_vignette)
+ Check that same passwords generate the same hash.> [!IMPORTANT]
> Never use outdated hashing algorithms like MD5.To solve it, the best solution is to use up-to date hashing algorithms, like `bcrypt`, `scrypt` or `PBKDF2`.
+ Change the MD5 hashing algorithm for [bcrypt](https://pkg.go.dev/golang.org/x/crypto/bcrypt).
+ Use a different salt for every user.
+ Repeat `#2 Scenario` and check that the same password generates different hashes.### 2. Login User - POST /users/login
We are going to explote the vulnerabilities related to the endpoint to log in a user in [/users/login][2].
The vulnerability that we are going to check is:+ [SQL injection](https://owasp.org/www-community/attacks/SQL_Injection)
An HTTP client is provided in [users-login.http](./tools/users-login.http) to follow along.
As you can see in [user_repository.go](./internal/repositories/user_repository.go), in the `Login` method, the query is created by string concatenation.#### 💉🛢 SQL Injection
Try to explote this query concatenation by concatenating an `always true` sql statement (something like `-OR '1'='1'-`).
The goal is to avoid the execution of the password clause (maybe by injecting a comment (`--`) to comment out the rest of the query)> [!IMPORTANT]
> Never concatenate strings in a query.### 3. View Posts
Once you're logged in, you are redirected to the [Welcome][3] page. There you can see an **Intro Post**.
The vulnerabilities that we are going to check in this scenario:
+ [SSRF](https://owasp.org/Top10/A10_2021-Server-Side_Request_Forgery_%28SSRF%29/)
To follow along, check [posts.http](./tools/posts.http)
#### 📥 SSRF - Server Side Request Forgery
If you open the network tab of the developer console of your web browser (normally F12), and **refresh the welcome page**, the program makes a call to http://localhost:8080/posts?name=intro.txt.
Let's check how the `GetStaticPostFileByName` method is implemented in [posts_handler](./internal/handlers/posts_handlers.go).
We can see that we are using [`os.Open`](https://pkg.go.dev/os#Open):
> file, err := os.Open(fmt.Sprintf("./resources/posts/%s", name))+ What would happen in we change the name query parameter to point to a different file in a different location?, maybe we could try with `../internal/private.txt`
+ Try to also display `/etc/passwd` file content.To solve this issue for this scenario we could validate the user input, and avoid path traversal with functions like [`os.Root`](https://pkg.go.dev/os#Root)
> [!IMPORTANT]
> Always validate user input.### 4. Add Comments
The vulnerabilities we are going to check here:
- Broken Access Control
- [CSRF](https://owasp.org/www-community/attacks/csrf)
- HTML Template injection#### 🩹 Broken Access Control
If we look at the Scenario 1 in the http tool [post_comments.http](/tools/post_comments.http), we can see that we can create a comment for a post.
But if we take a look at the payload, we can see that the `postID` and the `userID` are sent as part of the payload.
We can manipulate these values and check that we can create comments for any user to any post.There are several ways to implement a solution for this vulnerability in this case:
+ Override the values given in `userID` and/or `postID` by the proper values (the user id coming from the session cookie and the postID coming from the url)
+ (**Preferred**) Implement a new struct that contains only the valid fields as we have in `UserSignup` struct.#### 🔄 CSRF - Cross Site Request Forgery
The add comments endpoint is not protected against CSRF attacks. And we can check it by following this steps:
+ login in the application with your browser.
+ open [price-win.html](/tools/price-win.html) with that same browser.
+ Click on the rewards button.
+ Go to `http://localhost:8080/posts/2/comments` and check what happened.The app has been exploit by two vulnerabilities, CSRF and HTML Template injection.
To avoid CSRF attacks we can validate add a CSRF cookie in our requests, and validate in the payload that the cookie and the json field match.
In the template [add_edit_comment.tpl](/web/templates/posts/add_edit_comment.tpl) you can check that we are sending a csrf value in:``````
Validate that the value that we receive from that json field matches the value that we have in the `csrf` cookie in the Request.
Restart the application and check that you can't create comments anymore using the `win price` button.#### 💉🌐 HTML Template Injection
Before we could see that we also suffered from template injection.
Run the `#Scenario 2` http requests that tries to inject a `` content in your comment.
To solve this remember to always escape/validate user input.
In this case, [Gin](https://gin-gonic.com/) provides already a mechanism against this attack, and we needed to avoid it by creating a custom function to avoid escaping the html characters.
You can check [`gowasp.main`](cmd/gowasp/gowasp.go) how I created an `unsafe` function to render html content.## 📝 TODO
- Improve the css.
- Avoiding brute force attacks.
- Insufficient logging when adding the comment.[1]: http://localhost:8080/users/signup
[2]: http://localhost:8080/users/login
[3]: http://localhost:8080/users/welcome