Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file.
37 changes: 37 additions & 0 deletions owasp-top10-2021-apps/a5/insecure-file-upload/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
.SILENT:
.DEFAULT_GOAL := help

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

PROJECT := INSECURE FILE UPLOAD
PORT := 8080

## Installs a development environment
install: compose

## Composes project using docker-compose
compose: compose-down
docker-compose -f deployments/docker-compose.yml up -d --build --force-recreate

## Down project using docker-compose
compose-down:
docker-compose -f deployments/docker-compose.yml down


## 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"
124 changes: 124 additions & 0 deletions owasp-top10-2021-apps/a5/insecure-file-upload/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
<!-- This is a README Template for secDevLabs apps -->

# INSECURE FILE UPLOAD

<p align="center">
<img src="https://github.com/Edmar-Sousa/secDevLabs/blob/feature/lab-upload-files/owasp-top10-2021-apps/a5/insecure-file-upload/images/img1.png"/>
</p>

Insecure File Upload is a web laboratory written in PHP, with weak file upload validations.
A simple app that uploads files to the server’s public folder and displays a list of saved
files that can be viewed.

This laboratory aims to demonstrate code execution on the server, a security flaw that
falls under A5 — Security Misconfiguration and A3 — Injection in the OWASP classification.

## Index

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

## <a name="definition"></a> What is Unrestricted File Upload?

Unrestricted File Upload is a class of vulnerability that occurs when a web application accepts
and stores files from users without performing adequate validation, sanitization, or safe handling.
When file uploads are not properly checked (for type, content, name, storage location, and execution
permissions), an attacker can upload a crafted file that the server later interprets or executes —
for example, a PHP file disguised as an image. This can lead to remote code execution (RCE), local
file inclusion, information disclosure, or other severe compromises.

## Setup

To start this intentionally **insecure application**, you will need [Docker][docker install] and [Docker Compose][docker compose install]. After forking [secDevLabs](https://github.com/globocom/secDevLabs), you must type the following commands to start:

```sh
cd secDevLabs/owasp-top10-2021-apps/a5/insecure-file-upload
```

```sh
make install
```

Then simply visit [http://localhost:8080][app]

## Get to know the app :camera_flash:

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

- Access the URL in your browser
- Click the Select Image button
- Choose a PNG image
- Click the Upload button
- Then the file list will update, and you can view the image by clicking the link icon

## 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! 😜

### 👀

Upon accessing the page the attacker will see the following interface. They will then try to find a way to break the application.
A common flaw in applications is the lack of proper validation of user-submitted data. This allows an attacker to take advantage of it.

<p align="center">
<img src="https://github.com/Edmar-Sousa/secDevLabs/blob/feature/lab-upload-files/owasp-top10-2021-apps/a5/insecure-file-upload/images/img1.png"/>
</p>

### 🔥

The attacker then decides to see how the application works and, meanwhile, will try to think of a security
vulnerability during the process. When they select an image and click **Upload**, the file list will refresh
with the new file, as shown in the image below.

<p align="center">
<img src="https://github.com/Edmar-Sousa/secDevLabs/blob/feature/lab-upload-files/owasp-top10-2021-apps/a5/insecure-file-upload/images/img2.png"/>
</p>

Ok! Everything went well. In the file listing, when inspecting the page source code, the attacker notices that the image keeps its original name and was saved in the `/uploads` folder on the server.

<p align="center">
<img src="https://github.com/Edmar-Sousa/secDevLabs/blob/feature/lab-upload-files/owasp-top10-2021-apps/a5/insecure-file-upload/images/img3.png"/>
</p>

Ok! At this point the attacker gets an idea: "what if I upload a file named `hello.png.php`?"

```sh
# hello.png.php
<?php
echo phpinfo();
```

Great! The file named `hello.png.php` passed the server's validation! When accessing the
link that was generated to view the image, the file's code was executed!

<p align="center">
<img src="https://github.com/Edmar-Sousa/secDevLabs/blob/feature/lab-upload-files/owasp-top10-2021-apps/a5/insecure-file-upload/images/img4.png"/>
</p>

## Secure this app

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

- Upload a file with an extension other than an image
- You will not be able to execute the code by accessing `/uploads/<filename>`

## PR solutions

- Issue still unresolved

<!-- [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
[ExploitDB]: https://www.exploit-db.com/
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<?php
echo phpinfo();
10 changes: 10 additions & 0 deletions owasp-top10-2021-apps/a5/insecure-file-upload/app/public/.htaccess
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
DirectoryIndex index.php index.html

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

</IfModule>
211 changes: 211 additions & 0 deletions owasp-top10-2021-apps/a5/insecure-file-upload/app/public/css/main.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
@import url('https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100..900;1,100..900&display=swap');

* {
margin: 0;
padding: 0;
box-sizing: border-box;
}


html, :root {

--background-color: #F3F4FF;
--white-color: #fff;

--purple-400: #4D44B5;

--red-400: #d82424;
--red-900: #830606;

--green-400: #57d824;
--green-900: #108306;

--gray-300: #dadada;
--gray-400: #313131;

--blue-900: #303972;

}


.app {
width: 100vw;
min-height: 100vh;

display: flex;
align-items: center;
justify-content: center;

padding: 30px;

background-color: var(--background-color);
}

.alert {
width: 100%;

display: flex;
align-items: center;
gap: 10px;

padding: 10px;
margin-bottom: 15px;

font-family: Roboto, Arial;
font-weight: 600;

border-radius: 10px;
border: 3px solid ;
}

.alert.error {
background-color: var(--red-400);
border-color: var(--red-900);
}

.alert.success {
background-color: var(--green-400);
border-color: var(--green-900);
}

.container-uploads {
width: 100%;
max-width: 600px;

padding: 20px;
border-radius: 20px;

box-shadow: 0 0 10px var(--gray-300);

background-color: var(--white-color);
}

.upload-section {
flex: 1;
}

.sections-container {
display: flex;
flex-direction: column;
gap: 50px;
}

@media screen and (min-width: 1024px) {
.sections-container {
flex-direction: row;
}
}

.hidden {
display: none;
}

.title-form {
margin-bottom: 50px;

color: var(--blue-900);
font-size: 18px;
font-family: Roboto, Arial;
}

.files-uploaded {
list-style-type: none;

display: flex;
flex-direction: column;
gap: 15px;
}

.file-item {
display: flex;
align-items: center;
gap: 20px;

font-family: Roboto, Arial;
}

.file-item svg {
width: 40px;
height: 40px;
}

.file-item div {
flex: 1;
}

.file-item .file-title {
font-weight: bold;
}

.file-item .file-size {
font-weight: normal;
font-size: 12px;

color: var(--gray-400);
}

.upload-area {
width: 100%;
min-height: 150px;

border-radius: 16px;
padding: 20px;
border: 2px dashed var(--purple-400);

display: flex;
flex-direction: column;
align-items: center;

gap: 20px;

font-family: Roboto, Arial;
text-align: center;
}

.upload-area svg {
width: 50px;
height: 50px;
}

.file-header {
width: 100%;

display: flex;
align-items: center;
justify-content: space-between;
}

.view-image svg {
width: 20px;
height: 20px;
}

.button-container {
margin-top: 20px;
}

.button-submit {
display: block;
margin: auto;

width: 150px;
height: 40px;

border: none;
border-radius: 10px;

font-family: Roboto, Arial;
font-weight: bold;

color: var(--white-color);
background-color: var(--purple-400);
}

.empty-uploads {
display: flex;
align-items: center;
gap: 10px;

font-family: Roboto, Arial;
color: var(--gray-400);
}
Loading