
🔪 CRIME हमले का PoC : एक संपीड़न ओरेकल हमला जो CVE-2012-4929 को लक्षित करता है 🔪
CRIME हमला: एक संपीड़न ओरेकल हमला CVE-2012-4929 जिसे Juliano Rizzo और Thai Duong ने खोजा;
संपीड़न ओरेकल हमले में, चुने गए प्लेनटेक्स्ट और अज्ञात प्लेनटेक्स्ट के मिश्रण पर अनुकूली डेटा संपीड़न का उपयोग संपीड़ित टेक्स्ट की लंबाई में सामग्री-संवेदनशील परिवर्तन उत्पन्न कर सकता है, जिसे तब भी पहचाना जा सकता है जब संपीड़ित टेक्स्ट की सामग्री स्वयं एन्क्रिप्टेड हो। इसका उपयोग प्रोटोकॉल हमलों में यह पता लगाने के लिए किया जा सकता है कि इंजेक्ट किया गया ज्ञात प्लेनटेक्स्ट संदेश के गुप्त भाग की अज्ञात सामग्री से आंशिक रूप से भी मिलता-जुलता है या नहीं, जिससे गुप्त टेक्स्ट के लिए मेल खोजने की जटिलता बहुत कम हो जाती है। CRIME और BREACH हमले इस घटना का उपयोग करने वाले प्रोटोकॉल हमलों के उदाहरण हैं।
CRIME हमला आपको एन्क्रिप्टेड डेटा की लंबाई का उपयोग करके क्लाइंट द्वारा सर्वर को भेजे गए एन्क्रिप्टेड डेटा को प्राप्त करने की अनुमति देता है। यह आपको संदेश या HTTP अनुरोध को एन्क्रिप्ट करने के लिए उपयोग की जाने वाली निजी कुंजी प्राप्त करने की अनुमति नहीं देता है।
कई लेख बताते हैं कि CRIME हमला कैसे काम करता है, लेकिन यह सबसे अच्छा स्पष्टीकरण है जो मुझे इंटरनेट पर मिला:
यह हमला वास्तव में जटिल नहीं है, वास्तव में दिलचस्प हिस्सा कार्यान्वयन है जो 'सिद्धांत' से थोड़ा अलग है।
आइए लेख में वर्णित भोली विधि की जाँच करें, यह समझने का एक अच्छा तरीका है कि यह कैसे काम करता है:
हमलावर क्लाइंट द्वारा भेजे गए अनुरोध को नियंत्रित कर सकता है (उदाहरण के लिए जावास्क्रिप्ट का उपयोग करके)। लक्ष्य गुप्त कुकी को प्राप्त करना है। हमलावर इस तरह के कई अनुरोध भेजता है और एन्क्रिप्टेड डेटा की लंबाई की जाँच करता है:
| अनुरोध | लंबाई |
|---|---|
| GET /cookie= DATA cookie=quokkalight | 80 |
| GET /cookie=a DATA cookie=quokkalight | 81 |
| GET /cookie=b DATA cookie=quokkalight | 81 |
| GET /cookie=. DATA cookie=quokkalight | 81 |
| GET /cookie=q DATA cookie=quokkalight | 80 |
चूँकि cookie=q गुप्त कुकी के cookie=quokkalight से मेल खाता है, एन्क्रिप्टेड डेटा की लंबाई समान रहेगी और हमलावर को पता चल जाएगा कि उसे एक बाइट मिल गया है।
लेकिन यह विधि कभी-कभी विफल हो जाती है और इस पर भरोसा नहीं किया जा सकता, इसलिए हम एक अन्य विधि का उपयोग करेंगे।
पहले हम उस अक्षर के साथ एक अनुरोध भेजते हैं जिसे हम खोजना चाहते हैं, उसके बाद कई ऐसे वर्ण जो प्रारंभिक अनुरोध में नहीं पाए जा सकते, जैसे कुछ विशेष वर्ण :chr(i) + "#:/[@/&"। फिर हम एक दूसरा अनुरोध भेजते हैं लेकिन पेलोड को इस तरह उल्टा कर देते हैं: "#:/[@/&" + chr(i) और हम दोनों लंबाइयों की तुलना करते हैं। यदि len(enc(req1)) < len(enc(req2)) तो हमें एक बाइट मिली। यह विधि two_tries कहलाती है और यह कहीं अधिक विश्वसनीय है:
| बाइट q प्राप्त करने का अनुरोध | लंबाई |
|---|---|
| GET /cookie=a~#:/[@/& DATA cookie=quokkalight | 81 |
| GET /cookie=~#:/[@/&a DATA cookie=quokkalight | 81 |
| GET /cookie=b~#:/[@/& DATA cookie=quokkalight | 81 |
| GET /cookie=~#:/[@/&b DATA cookie=quokkalight | 81 |
| GET /cookie=q~#:/[@/& DATA cookie=quokkalight | 80 |
| GET /cookie=~#:/[@/&q DATA cookie=quokkalight | 81 |
हमलावर को एक बाइट मिल गई!
if len(enc(request1)) < len(enc(request2)):
print("found byte")
two_tries विधि जो मैंने लागू की है वह पूर्णतः पुनरावर्ती है, लेकिन क्यों? कभी-कभी एक से अधिक बाइट्स मिल सकती हैं क्योंकि संपीड़न कई पैटर्न से मेल खाता है।
आइए गुप्त को लें: cookie=quokkalight, अगर हम two_tries एल्गोरिथ्म चलाते हैं तो हमें निम्नलिखित परिणाम मिलेगा:
result 1: cookie=quokie=quokie=quokie=quokie=quokie=
result 2: cookie=quokkalight
सभी संभावित समाधान खोजने के लिए एल्गोरिथ्म को पेड़ में सभी पथों को लेना होगा।
हम सभी परिणामों को एक पेड़ के रूप में देख सकते हैं जिसे इस प्रकार दर्शाया जा सकता है:

स्ट्रीम साइफर मोड के विरुद्ध CRIME हमले का प्रमाण-अवधारणा फ़ाइल में पाया जा सकता है: CRIME-RC4-poc.py। यह पिछले स्पष्टीकरण का पायथन में एक कार्यान्वयन है।
python3 CRIME-RC4-poc.py
पूरा डेमो और परिणाम:
जब CBC सिफर मोड का उपयोग AES या DES के साथ किया जाता है, तो हमला RC4 जितना सरल नहीं होता। चूँकि सब कुछ ब्लॉक में विभाजित होता है, हमला थोड़ा पेचीदा हो जाता है (बहुत ज्यादा नहीं)।
उदाहरण के लिए, मान लें कि हम AES के साथ CBC सिफर मोड का उपयोग करते हैं, ब्लॉक 16 की लंबाई में विभाजित होगा और यदि len(data)%16 != 0 हो तो अंत में पैडिंग जोड़ी जाएगी।
CBC मोड में, यह ध्यान रखना महत्वपूर्ण है कि पेलोड payload=rand की लंबाई 16 होगी, 12 नहीं, क्योंकि एन्क्रिप्शन से पहले डेटा के अंत में पैडिंग जोड़ी जाएगी। इसलिए हमारा पिछला हमला काम नहीं कर सकता।
उदाहरण:
| ब्लॉक1 | ब्लॉक2 | ब्लॉक3 | लंबाई |
|---|---|---|---|
| GET /cookie= DA | TA cookie=quokka | light + PAD(11) | 48 |
| GET /cookie=a DA | TA cookie=quokka | light + PAD(10) | 48 |
| GET /cookie=b DA | TA cookie=quokka | light + PAD(10) | 48 |
| GET /cookie=. DA | TA cookie=quokka | light + PAD(10) | 48 |
| GET /cookie=q DA | TA cookie=quokka | light + PAD(11) | 48 |
इस उदाहरण में, लंबाई हमेशा समान रहेगी क्योंकि यदि हम एक बाइट जोड़ते या हटाते हैं, तो लंबाई हमेशा समान रहेगी, केवल पैडिंग बदलेगी। हमलावर केवल एन्क्रिप्टेड डेटा देखता है और उसके पास एन्क्रिप्टेड डेटा का उपयोग करके पैडिंग जानने का कोई तरीका नहीं है।
समाधान: CBC मोड की विशिष्टता के साथ खेलें, ताकि GARB चर में यादृच्छिक मान जोड़कर पैडिंग की लंबाई 1 हो जाए (GET पैरामीटर में, क्योंकि हमलावर GET और POST डेटा को नियंत्रित करता है)।
| ब्लॉक1 | ब्लॉक2 | ब्लॉक3 | ब्लॉक4 | लंबाई |
|---|---|---|---|---|
| GET /GARBc | ookie= DATA coo | kie=quokkalight + PAD(1) | 48 | |
| GET /GARBc | ookie=a DATA coo | kie=quokkalight | PAD(16) | 64 |
| GET /GARBc | ookie=b DATA coo | kie=quokkalight | PAD(16) | 64 |
| GET /GARBc | ookie=. DATA coo | kie=quokkalight | PAD(16) | 64 |
| GET /GARBc | ookie=q DATA coo | kie=quokkalight + PAD(1) | 48 |
यदि बाइट किसी पैटर्न से मेल खाता है, तो लंबाई समान रहेगी; यदि यह मेल नहीं खाता, तो लंबाई अलग होगी।
अगला, हमें बस RC4 भाग में बताई गई उसी विधि का उपयोग करना है, हम बस पहले एक कदम जोड़ते हैं।
adjust_padding() को कॉल करते हैं ताकि हमारे पास लंबाई 1 की पैडिंग हो सके।two_tries_recursive() को कॉल करते हैं और हम गुप्त FLAG पा सकते हैं!python3 CRIME-cbc-poc.py
बहुत जल्द आ रहा है...
\ /
\ _ /
----/_\----
x--------------( . )--------------x
x|x | |_|\_/|_| | x|x
x x x x