🌐
Werkzeug
werkzeug.palletsprojects.com › en › stable › debug
Debugging Applications — Werkzeug Documentation (3.1.x)
Frames that represent user code, ... feature enabled you can get a console for every frame in the traceback by hovering over a frame and clicking the console icon that appears at the right....
🌐
Pocoo
mitsuhiko.pocoo.org › werkzeug-docs › debug.html
Debugging Applications - Werkzeug
Also the debugger allows the execution of arbitrary code which makes it a major security risk and must never be used on production machines because of that. You can enable the debugger by wrapping the application in a DebuggedApplication middleware. Additionally there are parameters to the ...
🌐
GitHub
github.com › wdahlenburg › werkzeug-debug-console-bypass
GitHub - wdahlenburg/werkzeug-debug-console-bypass: 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. · GitHub
This repo provides a sample application to play with the /console endpoint on a dummy Flask application. ... $ 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.
Starred by 64 users
Forked by 7 users
Languages   Python 85.8% | Dockerfile 14.2%
🌐
Beautiful Soup
tedboy.github.io › flask › _modules › werkzeug › debug.html
Source code for werkzeug.debug - Flask API
""" def __init__(self, namespace): self.console = Console(namespace) self.id = 0 def get_pin_and_cookie_name(app): """Given an application object this returns a semi-stable 9 digit pin code and a random key. The hope is that this is stable between restarts to not make debugging particularly frustrating. If the pin was forcefully disabled this returns `None`. Second item in the resulting tuple is the cookie name for remembering. """ pin = os.environ.get('WERKZEUG_DEBUG_PIN') rv = None num = None # Pin was explicitly disabled if pin == 'off': return None, None # Pin was provided explicitly if pi
🌐
GitHub
github.com › grav3m1nd-byte › werkzeug-pin
GitHub - grav3m1nd-byte/werkzeug-pin: Yet another Werkzeug Console Pin Exploit Explanation · GitHub
The interfaces on the server hosting Werkzeug can be retrieved by using something like: curl -sX GET --url 'http://10.10.10.10:5000/file?filename=../../../../../proc/self/net/dev' -u 'user:password123' | grep -E '^\s*ens*|^\s*eth*'
Author   grav3m1nd-byte
🌐
GitHub
github.com › pallets › werkzeug › blob › main › src › werkzeug › debug › console.py
werkzeug/src/werkzeug/debug/console.py at main · pallets/werkzeug
_stream: ContextVar[HTMLStringO] = ContextVar("werkzeug.debug.console.stream") _ipy: ContextVar[_InteractiveConsole] = ContextVar("werkzeug.debug.console.ipy") · · class HTMLStringO: """A StringO version that HTML escapes on write.""" · def __init__(self) -> None: self._buffer: list[str] = [] ·
Author   pallets
🌐
HackTricks
book.hacktricks.xyz › home › network services pentesting › pentesting web › werkzeug
Werkzeug / Flask Debug - HackTricks
This is used outside containers too but should be # relatively stable across boots. try: with open("/proc/self/cgroup", "rb") as f: linux += f.readline().strip().rpartition(b"/")[2] except OSError: pass if linux: return linux # On OS X, use ioreg to get the computer's serial number. try: Upon collating all necessary data, the exploit script can be executed to generate the Werkzeug console PIN:
🌐
Spapas
spapas.github.io › 2016 › 06 › 07 › django-werkzeug-debugger
Using Werkzeug debugger with Django - /var/ - GitHub Pages
I also recommend to use it only on a local development server (i.e the server must be run on 127.0.0.1/local IP and not allow remote connections). Now its time for the magic: Let’s add a django view that throws an exception, like this: ... to your urls.py ( url(r'^test/', test ) ) and after you visit test you should see something like this: Since the a variable was not defined you’ll get an exception when you try to increaseit. Now, notice the console icon in the lower right corner - when you click it you’ll get the interactive debugger!
🌐
Netscylla
netscylla.com › blog › 2018 › 10 › 03 › werkzeug-debugger.html
Werkzeug Debugger | Netscylla’s Blog
October 3, 2018 - Now, Werkzeug requires an actual error to trigger the console, as it uses a secret key generated when the application starts, which is only exposed in the Werkzeug Debugger page. Without this secret key you cannot run any commands, that’s why you need an exception to reveal the secret.
🌐
Stack Overflow
stackoverflow.com › questions › 10879702 › werkzeug-and-webapp2-debug-display-and-console-not-working
Werkzeug and WebApp2 - debug display and console not working - Stack Overflow
import webapp2 from system import config from werkzeug.debug import DebuggedApplication from werkzeug.serving import run_simple application = webapp2.WSGIApplication(routes=config.routes, debug=False, config=config.options) debugged_application = DebuggedApplication(application) def main(): run_simple('localhost', 4000, debugged_application, use_reloader=True, use_debugger=True, threaded=True) if __name__ == '__main__': main() ... I think that DebuggedApplication middleware tries to achieve the same as use_debugger=True, so no need to use both.
Find elsewhere
🌐
Medium
medium.com › swlh › hacking-flask-applications-939eae4bffed
Hacking Flask Applications. Executing arbitrary commands using the… | by Vickie Li | The Startup | Medium
February 18, 2020 - The debugger gets triggered when there is an internal server error. Sometimes, you can also access the debugger console by navigating to the path “/console”, if it is set as a general-purpose path for the debugger.
Top answer
1 of 2
1

Some things to think about before enabling the werkzeug debugger:

  • When you enable the werkzeug debugger, anyone triggering an exception will be able to access your code and your data (including database passwords and other sensitive credentials). Be careful and don’t leave it enabled longer than necessary, or add an extra protection layer to bar unauthorized users!
  • Once you’re done with the debugging, restore your old wsgi.py file and push your code again (you can leave werkzeug in your requirements.txt if you like; that does not matter).

Here's what you can do to set it up:

1) add the following to your wsgi.py

# The following lines enable the werkzeug debugger
import django.views.debug

def null_technical_500_response(request, exc_type, exc_value, tb):
    raise exc_type, exc_value, tb
django.views.debug.technical_500_response = null_technical_500_response
from werkzeug.debug import DebuggedApplication
application = DebuggedApplication(application, evalex=True)

2) add the following to your requirements.txt

werkzeug

If you'd like to try out a quick sample of the debugger, I've setup example of the interactive debugger. This test app will only be available for a few days. http://django-johndotcloud.dotcloud.com/raise/

References:

  • http://web.archive.org/web/20111020150533/http://olddocs.dotcloud.com/tutorials/django/#advanced-debugging-with-werkzeug
  • http://werkzeug.pocoo.org/docs/debug/
  • https://github.com/dotcloud/django-on-dotcloud
2 of 2
1

The code in the answer above no longer works on Python 3.

Here's how to do the same thing in Python 3.3:

import django.views.debug

def null_technical_500_response(request, exc_type, exc_value, tb):
    raise exc_type(exc_value).with_traceback(tb)
django.views.debug.technical_500_response = null_technical_500_response

from werkzeug.debug import DebuggedApplication
application = DebuggedApplication(application, evalex=True)
🌐
InfosecMatter
infosecmatter.com › home › metasploit module library
Werkzeug Debug Shell Command Execution - Metasploit - InfosecMatter
December 4, 2022 - TARGETURI by default is /console, as defined by werkzeug, however it can be changed within the python script. Example utilizing the previously mentioned sample app listed above. msf > use exploit/multi/http/werkzeug_debug_rce msf exploit(werkzeug_debug_rce) > set rport 8081 rport => 8081 msf exploit(werkzeug_debug_rce) > set rhost 10.108.106.201 rhost => 10.108.106.201 msf exploit(werkzeug_debug_rce) > check [+] 10.108.106.201:8081 - The target is vulnerable.
🌐
Bengrewell
bengrewell.com › cracking-flask-werkzeug-console-pin
Cracking Werkzeug Debugger Console Pin
March 11, 2023 - Learn how to crack the Werkzeug Debugger pin and gain access to the console in Python-based Flask web applications with this educational blog post.
🌐
GitHub
github.com › pallets › werkzeug › blob › main › src › werkzeug › debug › __init__.py
werkzeug/src/werkzeug/debug/__init__.py at main · pallets/werkzeug
:param pin_security: can be used to disable the pin based security system. :param pin_logging: enables the logging of the pin system. · .. versionchanged:: 2.2 · Added the ``werkzeug.debug.preserve_context`` environ key. """ · _pin: str | None · _pin_cookie: str · · def __init__( self, app: WSGIApplication, evalex: bool = False, request_key: str = "werkzeug.request", console_path: str = "/console", console_init_func: t.Callable[[], dict[str, t.Any]] | None = None, show_hidden_frames: bool = False, pin_security: bool = True, pin_logging: bool = True, ) -> None: if not console_init_func: console_init_func = None ·
Author   pallets
🌐
Werkzeug
werkzeug.palletsprojects.com › en › stable › tutorial
Werkzeug Tutorial — Werkzeug Documentation (3.1.x)
If you are on OS X, you can use brew to install it: ... Redis was developed for UNIX systems and was never really designed to work on Windows. For development purposes, the unofficial ports however work well enough. You can get them from github. In this tutorial, we will together create a simple URL shortener service with Werkzeug.
🌐
GitHub
github.com › pallets › werkzeug › issues › 1875
Debug page shows console with interactive debugging off · Issue #1875 · pallets/werkzeug
July 3, 2020 - from werkzeug.debug import DebuggedApplication def do_a_bad_thing(): raise AttributeError def application(environ, start_response): do_a_bad_thing() if __name__ == '__main__': from werkzeug.serving import run_simple app = DebuggedApplication(application) run_simple('127.0.0.1', 5000, app, use_reloader=True) Run the following above on master. The debug page gives the option to open the console (which shouldn't happen with evalex=False.
Author   kx-chen
🌐
GitHub
github.com › wdahlenburg › werkzeug-debug-console-bypass › blob › main › README.md
werkzeug-debug-console-bypass/README.md at main · wdahlenburg/werkzeug-debug-console-bypass
This repo provides a sample application to play with the /console endpoint on a dummy Flask application. ... $ 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.
Author   wdahlenburg
🌐
Medium
nateahess.medium.com › htb-writeup-werkzeug-7bb0640d79f0
Hack The Box: Skript Kiddie — Werkzeug | by Nate Hess | Medium
December 29, 2022 - Since the console already knows that we’re running Python, remove the “python -c” from the beginning as well as the quotes. Then add the IP and port of your machine. Before you hit Enter, make sure to set up a netcat listener on the port you used in the script! There we have it! We have officially exploited the Werkzeug vulnerability and established a reverse shell connection.
🌐
HackTricks
hacktricks.boitatech.com.br › pentesting › pentesting-web › werkzeug
werkzeug | HackTricks - Boitatech
September 30, 2021 - In this file, see relevant method outlining steps to generate console PIN: ... def get_pin_and_cookie_name(app): pin = os.environ.get('WERKZEUG_DEBUG_PIN') rv = None num = None # Pin was explicitly disabled if pin == 'off': return None, None # Pin was provided explicitly if pin is not None and pin.replace('-', '').isdigit(): # If there are separators in the pin, return it directly if '-' in pin: rv = pin else: num = pin modname = getattr(app, '__module__', getattr(app.__class__, '__module__')) try: # `getpass.getuser()` imports the `pwd` module, # which does not exist in the Google App Engine sandbox.