Test case 26 / 26PASS

Path Traversal - Profile Picture - Upload Filename

Lab environment — not a production system

Screenshots and raw traffic are not translated; text within them may be in another language.

vuln-bank/Evidence/[PASS] Path Traversal - Profile Picture - Upload Filename

01 — Notes

Test notes

Vulnerability

[PASS] Path Traversal - Profile Picture - Upload Filename

Description

The test attempted to write a file outside the upload directory by inserting ../ sequences into the client-supplied filename. A comment in the source code states that path traversal is possible, so this endpoint was tested specifically.

Impact

No impact. Control holds: Werkzeug's secure_filename function flattens the filename so ../ sequences are removed and the file remains inside the static/uploads directory. Writing a file to an arbitrary location was not achieved. Note: the same endpoint is still flawed because it does not validate file type; this is reported separately in the Unrestricted File Upload finding.

CWE

CWE-22: Improper Limitation of a Pathname to a Restricted Directory (Path Traversal)

OWASP

A01:2021 - Broken Access Control

Scenario

A file is uploaded with the name ../../../../tmp/pwned.txt intended to escape the upload directory. Result: the filename is flattened by secure_filename and the file is stored inside static/uploads, not in /tmp. Verification was done by retrieving the file at its actual storage location.

Endpoint

POST http://127.0.0.1:5001/upload_profile_picture

Affected feature

Profile picture upload (filename handling)

Remediation

- Keep using secure_filename. - Ignore the client-supplied filename entirely and generate a random name server-side. - Verify that the final path is inside the upload directory before writing the file.

Proof of concept

1) (Screenshot 1) ATTEMPT: a file is uploaded with the name ../../../../tmp/pwned.txt -> the name is flattened, the file is stored inside static/uploads. 2) (Screenshot 2) RESULT: the file is retrieved at its actual storage location inside static/uploads, proving traversal did not occur and the control holds.
View source note (English)
Vulnerability:
[PASS] Path Traversal - Profile Picture - Upload Filename

Description:
The test attempted to write a file outside the upload directory by inserting ../ sequences into the client-supplied filename. A comment in the source code states that path traversal is possible, so this endpoint was tested specifically.

Impact:
No impact. Control holds: Werkzeug's secure_filename function flattens the filename so ../ sequences are removed and the file remains inside the static/uploads directory. Writing a file to an arbitrary location was not achieved.

Note: the same endpoint is still flawed because it does not validate file type; this is reported separately in the Unrestricted File Upload finding.

CWE:
CWE-22: Improper Limitation of a Pathname to a Restricted Directory (Path Traversal)

OWASP:
A01:2021 - Broken Access Control

Scenario:
A file is uploaded with the name ../../../../tmp/pwned.txt intended to escape the upload directory. Result: the filename is flattened by secure_filename and the file is stored inside static/uploads, not in /tmp. Verification was done by retrieving the file at its actual storage location.

Endpoint:
POST http://127.0.0.1:5001/upload_profile_picture

Affected Feature:
Profile picture upload (filename handling)

Remediation:
- Keep using secure_filename.
- Ignore the client-supplied filename entirely and generate a random name server-side.
- Verify that the final path is inside the upload directory before writing the file.

POC:
1) (Screenshot 1) ATTEMPT: a file is uploaded with the name ../../../../tmp/pwned.txt -> the name is flattened, the file is stored inside static/uploads.
2) (Screenshot 2) RESULT: the file is retrieved at its actual storage location inside static/uploads, proving traversal did not occur and the control holds.

02 — Screenshots

Screenshots (2)

01 / 1
02 / 2

03 — Requests and responses

HTTP captures

Some credential values are masked in this public HTML view. This does not mean every sensitive value or linked file has been redacted.

CAPTURE 01 / 1
HTTP request
POST /upload_profile_picture HTTP/1.1
User-Agent: python-requests/2.33.1
Accept-Encoding: gzip, deflate, br, zstd
Accept: */*
Connection: keep-alive
Authorization: Bearer [REDACTED-LAB-TOKEN]
Content-Length: 214
Content-Type: multipart/form-data; boundary=9f1167246e65c3b70584c79ad4a00969

--9f1167246e65c3b70584c79ad4a00969
Content-Disposition: form-data; name="profile_picture"; filename="../../../../tmp/pwned.txt"
Content-Type: text/plain

PWNED-BY-PENTEST
--9f1167246e65c3b70584c79ad4a00969--
HTTP response
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 136
Access-Control-Allow-Origin: *
Server: Werkzeug/2.0.1 Python/3.9.25
Date: Wed, 30 Sep 2026 03:13:08 GMT

{
  "file_path": "static/uploads/533021_tmp_pwned.txt",
  "message": "Profile picture uploaded successfully",
  "status": "success"
}
CAPTURE 02 / 2
HTTP request
GET /static/uploads/533021_tmp_pwned.txt HTTP/1.1
User-Agent: python-requests/2.33.1
Accept-Encoding: gzip, deflate, br, zstd
Accept: */*
Connection: keep-alive

HTTP response
HTTP/1.1 200 OK
Content-Disposition: inline; filename=533021_tmp_pwned.txt
Content-Type: text/plain; charset=utf-8
Content-Length: 16
Last-Modified: Wed, 30 Sep 2026 03:13:08 GMT
Cache-Control: no-cache
Date: Wed, 30 Sep 2026 03:13:09 GMT
Access-Control-Allow-Origin: *
Server: Werkzeug/2.0.1 Python/3.9.25

PWNED-BY-PENTEST