Research: Bypass Werkzeug Debug PIN
Flask / Werkzeug Debug PIN – Full Theory & Exploitation Guide
1. Tổng quan bài toán
Dạng bài này xuất hiện rất thường xuyên trong CTF Web / Pentest lab khi:
- Server chạy Flask ở chế độ debug
- Debugger của Werkzeug được bật
- Truy cập debugger yêu cầu PIN
- Ứng dụng tồn tại primitive đọc file tùy ý (LFI, path traversal, SSRF → file)
Mục tiêu cuối cùng:
Tính toán chính xác Werkzeug Debug PIN để truy cập interactive console → RCE
2. Điều kiện tiên quyết (Prerequisites)
Bài bắt buộc phải có ít nhất một trong các primitive sau:
- LFI:
../../../../etc/passwd - Read arbitrary file
- SSRF đọc được
file:// - Debug endpoint leak source code
Nếu không đọc được file hệ thống, bài này không giải được.
3. Workflow tổng quát
1 | [ Read file primitive ] |
4. Bước 1 – Xác định Werkzeug dùng MD5 hay SHA1
4.1 File cần đọc
1 | /<python-site-packages>/werkzeug/__init__.py |
Hoặc:
1 | /usr/local/lib/pythonX.Y/site-packages/werkzeug/debug/__init__.py |
4.2 Cách nhận biết
| Dấu hiệu | Kết luận |
|---|---|
hashlib.md5() |
Werkzeug cũ → MD5 |
hashlib.sha1() |
Werkzeug ≥ 2.x → SHA1 |
Flask cũ / CTF cổ điển thường dùng MD5
5. Bước 2 – Lý thuyết Werkzeug Debug PIN
5.1 Công thức tổng quát
Werkzeug sinh PIN từ 2 nhóm dữ liệu:
Public bits (có thể đoán / đọc được)
usernamemodnameappnamepathtới file Flask
Private bits (bắt buộc phải leak)
- MAC address (
uuid.getnode()) - Machine ID (
/etc/machine-id) - Cgroup suffix (
/proc/self/cgroup)
6. Bước 3 – Thu thập dữ liệu cần thiết
6.1 Public bits
| Giá trị | Cách lấy |
|---|---|
| username | /etc/passwd, user chạy web (www-data, flask, root) |
| modname | thường là flask.app |
| appname | Flask, wsgi_app, DebuggedApplication |
| flask path | stacktrace (làm chương trình bị exception) hoặc đoán (thường nằm ở /home/<username>/.local/lib/pythonX.Y/site-packages/flask/app.py) |
6.2 Private bits (quan trọng)
MAC address
Đọc từ:
1 | /sys/class/net/eth0/address (thông thường là cái này) |
Có thể brute các interface phổ biến:
1 | eth0, ens33, docker0, lo |
Hoặc đọc file /proc/net/arp để xác định device:
1 | IP address HW type Flags HW address Mask Device |
Werkzeug dùng:
1 | uuid.getnode() → integer |
Machine ID
1 | /etc/machine-id |
Fallback:
1 | /proc/sys/kernel/random/boot_id |
Cgroup
1 | /proc/self/cgroup |
Ví dụ:
1 | 0::/init.scope |
Werkzeug chỉ lấy phần sau dấu /
1 | init.scope |
7. Cách Werkzeug xử lý machine-id + cgroup
Pseudo-code:
1 | linux = machine_id |
Ví dụ:
1 | machine-id = abc123 |
8. Tool sinh PIN – MD5 version
File: gen-md5-pin.py
👉 Dùng khi Werkzeug sử dụng hashlib.md5
- Chuẩn hóa MAC (string → integer)
- Ghép machine-id + cgroup
- Hash theo đúng thứ tự Werkzeug
- Format PIN giống hệt thật
1 | #!/usr/bin/env python3 |
9. Tool sinh PIN – SHA1 version
File: gen-sha1-pin.py
👉 Dùng khi Werkzeug dùng hashlib.sha1
Tool này:
- Có brute modname / appname
- Generate cookie debugger
- Dùng cho CTF nâng cao
Link tool: https://github.com/SidneyJob/Werkzeuger/blob/main/gen.py
10. Checklist giải bài nhanh
- Có primitive đọc file
- Xác định MD5 hay SHA1
- Đọc
/etc/machine-id - Đọc
/proc/self/cgroup - Lấy MAC address
- Xác định flask path
- Generate PIN offline
- Truy cập debugger → RCE
11. Lưu ý thực tế CTF
- Docker luôn có cgroup
- Sai 1 byte → PIN sai
- MAC phải convert đúng integer
- Sai appname/modname → brute
12. Tổng kết
Werkzeug Debug PIN KHÔNG phải random
Nó là:
- Deterministic
- Phụ thuộc hệ thống
- Có thể tính offline nếu leak đủ thông tin
👉 Đây là design flaw có chủ đích, phục vụ debug, nhưng trở thành critical vuln trong CTF.
Lab luyện tập:
- https://dreamhack.io/wargame/challenges/74
- https://www.root-me.org/en/Challenges/Web-Server/Flask-Development-server
Happy hacking.
Ngoài lề: Vì hơi lười nên mình prompt bài viết này (thật ra là AI viết hay hơn mình) :>








