Skip to content

Commit

Permalink
Merge pull request #528 from chinchila/lab-smuggling
Browse files Browse the repository at this point in the history
[OWASP 2021] - Add new A6 - Vulnerable and outdated components app
  • Loading branch information
gabriel-cantergiani committed Oct 29, 2021
2 parents 393ca08 + 8d17ee2 commit 7b00ccd
Show file tree
Hide file tree
Showing 12 changed files with 296 additions and 0 deletions.
47 changes: 47 additions & 0 deletions owasp-top10-2021-apps/a6/golden-hat/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# This is a Makefile template!

.SILENT:
.DEFAULT_GOAL := help

#If your app is written in golang, add the following lines to set GOPATH
GO ?= go
GOROOT ?= $(shell $(GO) env GOROOT)
GOPATH ?= $(shell $(GO) env GOPATH)
GOBIN ?= $(GOPATH)/bin

COLOR_RESET = \033[0m
COLOR_COMMAND = \033[36m
COLOR_YELLOW = \033[33m
COLOR_GREEN = \033[32m
COLOR_RED = \033[31m

PROJECT := Golden Hat Society
PORT := 10006
SLEEPUNTILAPPSTARTS := 45

## Installs a development environment using docker-compose
install: compose msg

## Run project using docker-compose
compose:
docker-compose -f deployments/docker-compose.yml down -v --remove-orphans
docker-compose -f deployments/docker-compose.yml up -d --build --force-recreate

## Prints initialization message after compose phase - You can find that the check-init.sh script is also in the docs folder.
msg:
chmod +x deployments/check-init.sh
./deployments/check-init.sh

## Prints help message
help:
printf "\n${COLOR_YELLOW}${PROJECT}\n------\n${COLOR_RESET}"
awk '/^[a-zA-Z\-\_0-9\.%]+:/ { \
helpMessage = match(lastLine, /^## (.*)/); \
if (helpMessage) { \
helpCommand = substr($$1, 0, index($$1, ":")); \
helpMessage = substr(lastLine, RSTART + 3, RLENGTH); \
printf "${COLOR_COMMAND}$$ make %s${COLOR_RESET} %s\n", helpCommand, helpMessage; \
} \
} \
{ lastLine = $$0 }' $(MAKEFILE_LIST) | sort
printf "\n"
118 changes: 118 additions & 0 deletions owasp-top10-2021-apps/a6/golden-hat/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
<!-- This is a README Template for secDevLabs apps -->
# Golden hat society

<p align="center">
<img src="images/img1.png"/>
</p>

Golden hat society is an application made with python that has a reverse proxy, mitmproxy, blocking the route `/golden.secret` that must be accessed only by whom is inside the docker VPN.

## Index

- [Definition](#definition)
- [Setup](#setup)
- [Attack narrative](#attack-narrative)
- [Objectives](#secure-this-app)
- [Solutions](#pr-solutions)
- [Contributing](#contributing)


## <a name="definition"></a> What does it mean to use vulnerable and outdated components?

This vulnerability was #9 on OWASP top ten 2017 and made all the way up to #6 in 2021. Normally, softwares that contains incoming connections, are executed by exclusive users with restricted permissions. The reason why is that if someone exploits the application, then this attacker can't do much because of these permissions.

As softwares get bigger and bigger, we must use some libraries at some point, this means that those libs must be secure too. The main point of this vulnerability is to use a lib, framework and other modules vulnerable to an already known vulnerability (known by advisories).

The main goal of this app is to discuss how using vulnerable and outdated components can be exploited and to encourage developers to send secDevLabs Pull Requests on how they would mitigate these flaws.

## Setup

To run the app:

```
cd secDevLabs/owasp-top10-2021-apps/a6/golden-hat
make install
```

## Get to know the app ⚜️

To properly understand how this application works, you can follow these simple steps:

* Visit the homepage.

## Attack narrative

Now that you know the purpose of this app, what could possibly go wrong? The following section describes how an attacker could identify and eventually find sensitive information about the app or it's users. We encourage you to follow these steps and try to reproduce them on your own to better understand the attack vector! 😜

### 👀

#### Use of vulnerable mitmproxy version allows HTTP desync attacks

First time acessing the app on port 10006:

<p align="center">
<img src="images/img1.png"/>
</p>

Once we try reaching the `/golden.secret` we can see interesting headers:

<p align="center">
<img src="images/attack1.png"/>
</p>

As we can see this `Via: mitmproxy/5.3.0` helps us with the recon. Now that we know what is running on the server we can search for CVEs on this version of mitmproxy. Once we found the CVE-2021-39214, we can make an exploit to this vulnerability.

Let's take a look on the mitmproxy source code, [TAG 5.3.0](https://github.com/mitmproxy/mitmproxy/tree/v5.3.0) at file [/mitmproxy/net/http/http1/read.py:L209](https://github.com/mitmproxy/mitmproxy/blob/a738b335a36b58f2b30741d76d9fe41866309299/mitmproxy/net/http/http1/read.py#L209):

```python
if "chunked" in headers.get("transfer-encoding", "").lower():
return None
```

As we can see this piece of code is responsible for the vulnerability. Now that we know that the proxy proccess any request as chunked that contains the chunked keyword, we can craft an request that the proxy will understand as `Transfer-Encoding` chunked and the gunicorn backend will understand as `Content-Length`. This request can be sent on burp repeater (you must disable the option `update content-length`), telnet, netcat or any type of connection that allow to send texts over sockets.

```
GET /w HTTP/1.1
Host: 127.0.0.1:10006
Transfer-Encoding: chunkedasd
Content-Length: 4
35
GET /golden.secret HTTP/1.1
Host: 127.0.0.1:8000
0
GET / HTTP/1.1
Host: 127.0.0.1:10006
```

The first request forces a 404 error. The frontend(proxy) will parse the request as a normal request with body until the 0. The backend will process the first request until 35 and then will parse the request to `/golden.secret` poisoning the next socket. Then we just put a new alignment request at the end to poison a socket that we control.

After running this payload as a request we can see the secret page:


<p align="center">
<img src="images/attack2.png"/>
</p>

This vulnerability is interesting because you can poison other clients requests and smug them to do what you want!

## Secure this app

How would you mitigate this vulnerability? After your changes, an attacker should not be able to:

- Bypass proxy rules.

## PR solutions

[Spoiler alert 🚨 ] To understand how this vulnerability can be mitigated, check out [these pull requests]!

## Contributing

We encourage you to contribute to SecDevLabs! Please check out the [Contributing to SecDevLabs](../../../docs/CONTRIBUTING.md) section for guidelines on how to proceed! 🎉

[secDevLabs]: https://github.com/globocom/secDevLabs
4 changes: 4 additions & 0 deletions owasp-top10-2021-apps/a6/golden-hat/app/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from server import app

if __name__ == "__main__":
app.run()
7 changes: 7 additions & 0 deletions owasp-top10-2021-apps/a6/golden-hat/app/block.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from mitmproxy import http
import re

def request(flow):
if 'golden.secret' in flow.request.url or re.match(r'^http://127.0.0.1:8000/[a-z._/]*$', flow.request.url) is None:
flow.response = http.HTTPResponse.make(401, b"Haha! Only allowed hats can see this page!")
flow.response.headers["Via"] = "mitmproxy/5.3.0"
3 changes: 3 additions & 0 deletions owasp-top10-2021-apps/a6/golden-hat/app/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/bash
mitmdump --mode reverse:http://127.0.0.1:8000 -p 10006 -s block.py --set block_global=false --no-http2 &
gunicorn --threads 8 --bind 127.0.0.1:8000 app:app
20 changes: 20 additions & 0 deletions owasp-top10-2021-apps/a6/golden-hat/app/server.py

Large diffs are not rendered by default.

12 changes: 12 additions & 0 deletions owasp-top10-2021-apps/a6/golden-hat/deployments/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
FROM ubuntu:18.04

RUN apt-get update \
&& apt-get install -y --no-install-recommends curl python3-pip python3-wheel python3-dev libffi-dev libssl-dev \
&& pip3 install -U pip setuptools \
&& pip install flask gunicorn[gevent] requests

RUN pip3 install --upgrade pip && \
pip3 --no-cache-dir install mitmproxy

WORKDIR /app
CMD /bin/bash run.sh
72 changes: 72 additions & 0 deletions owasp-top10-2021-apps/a6/golden-hat/deployments/check-init.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#!/bin/bash
#
# This script verifies if SecDevLabs app has properly start-up.
#

COLOR_RED='\033[31m'
COLOR_YELLOW='\033[33m'
COLOR_GREEN='\033[32m'
COLOR_BLUE='\033[1;34m'
COLOR_RESET='\033[0m'

PROJECT='A6 - Golden hat society'
PORT=10006
TRIES=480
LOADING=0

printf "${COLOR_YELLOW}SecDevLabs: 👀 Your app is starting!\n${COLOR_RESET}"

while : ; do
`curl -s -f http://localhost:$PORT > /dev/null`
if [ $? == 0 ] ; then
break
fi
if [ $TRIES == 0 ] ; then
break
fi
TRIES=$((TRIES-1))
sleep 0.25

# Loading animation
if [ $LOADING == 14 ]; then
LOADING=0
fi
if [ $LOADING == 0 ]; then
printf "\r${COLOR_YELLOW}SecDevLabs: 👀 Your app is still starting... (*-------) ${COLOR_RESET}"
elif [ $LOADING == 1 ]; then
printf "\r${COLOR_YELLOW}SecDevLabs: 👀 Your app is still starting... (-*------) ${COLOR_RESET}"
elif [ $LOADING == 2 ]; then
printf "\r${COLOR_YELLOW}SecDevLabs: 👀 Your app is still starting... (--*-----) ${COLOR_RESET}"
elif [ $LOADING == 3 ]; then
printf "\r${COLOR_YELLOW}SecDevLabs: 👀 Your app is still starting... (---*----) ${COLOR_RESET}"
elif [ $LOADING == 4 ]; then
printf "\r${COLOR_YELLOW}SecDevLabs: 👀 Your app is still starting... (----*---) ${COLOR_RESET}"
elif [ $LOADING == 5 ]; then
printf "\r${COLOR_YELLOW}SecDevLabs: 👀 Your app is still starting... (-----*--) ${COLOR_RESET}"
elif [ $LOADING == 6 ]; then
printf "\r${COLOR_YELLOW}SecDevLabs: 👀 Your app is still starting... (------*-) ${COLOR_RESET}"
elif [ $LOADING == 7 ]; then
printf "\r${COLOR_YELLOW}SecDevLabs: 👀 Your app is still starting... (-------*) ${COLOR_RESET}"
elif [ $LOADING == 8 ]; then
printf "\r${COLOR_YELLOW}SecDevLabs: 👀 Your app is still starting... (------*-) ${COLOR_RESET}"
elif [ $LOADING == 9 ]; then
printf "\r${COLOR_YELLOW}SecDevLabs: 👀 Your app is still starting... (-----*--) ${COLOR_RESET}"
elif [ $LOADING == 10 ]; then
printf "\r${COLOR_YELLOW}SecDevLabs: 👀 Your app is still starting... (----*---) ${COLOR_RESET}"
elif [ $LOADING == 11 ]; then
printf "\r${COLOR_YELLOW}SecDevLabs: 👀 Your app is still starting... (---*----) ${COLOR_RESET}"
elif [ $LOADING == 12 ]; then
printf "\r${COLOR_YELLOW}SecDevLabs: 👀 Your app is still starting... (--*-----) ${COLOR_RESET}"
elif [ $LOADING == 13 ]; then
printf "\r${COLOR_YELLOW}SecDevLabs: 👀 Your app is still starting... (-*------) ${COLOR_RESET}"
fi
LOADING=$((LOADING+1))
# End of loading animation

done

if [ $TRIES == 0 ]; then
printf "\n${COLOR_RED}SecDevLabs: Ooops! Something went wrong, please check api details for more information!\n${COLOR_RESET}"
else
printf "\n${COLOR_GREEN}SecDevLabs: 🔥 ${PROJECT} is now running at ${COLOR_RESET}${COLOR_BLUE}http://localhost:$PORT${COLOR_RESET}\n"
fi
13 changes: 13 additions & 0 deletions owasp-top10-2021-apps/a6/golden-hat/deployments/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
version: "3"
services:
app:
platform: linux/x86_64
container_name: app-a2
build:
context: ../
dockerfile: deployments/Dockerfile
ports:
- "10006:10006"
volumes:
- "../app/:/app"
restart: always
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 7b00ccd

Please sign in to comment.