RouterSpace

Enumeration

Full TCP nmap scan

   1    # Nmap 7.91 scan initiated Sun Mar 20 23:13:40 2022 as: nmap -v -sC -sV -p- -oN full_tcp_nmap.txt 10.129.14
        0.184
   2    Nmap scan report for 10.129.140.184
   3    Host is up (0.047s latency).
   4    Not shown: 65533 filtered ports
   5    PORT   STATE SERVICE VERSION
   6    22/tcp open  ssh     (protocol 2.0)
   7    | fingerprint-strings: 
   8    |   NULL: 
   9    |_    SSH-2.0-RouterSpace Packet Filtering V1
  10    | ssh-hostkey: 
  11    |   3072 f4:e4:c8:0a:a6:af:66:93:af:69:5a:a9:bc:75:f9:0c (RSA)
  12    |   256 7f:05:cd:8c:42:7b:a9:4a:b2:e6:35:2c:c4:59:78:02 (ECDSA)
  13    |_  256 2f:d7:a8:8b:be:2d:10:b0:c9:b4:29:52:a8:94:24:78 (ED25519)
  14    80/tcp open  http
  15    | fingerprint-strings: 
  16    |   FourOhFourRequest: 
  17    |     HTTP/1.1 200 OK
  18    |     X-Powered-By: RouterSpace
  19    |     X-Cdn: RouterSpace-55363
  20    |     Content-Type: text/html; charset=utf-8
  21    |     Content-Length: 65
  22    |     ETag: W/"41-lOOQHJZVTbICjg1CqLAEDLTlKeg"
  23    |     Date: Mon, 21 Mar 2022 03:15:44 GMT
  24    |     Connection: close
  25    |     Suspicious activity detected !!! {RequestID: J KJ blza e Ta0 r9 }
  26    |   GetRequest: 
  27    |     HTTP/1.1 200 OK
  28    |     X-Powered-By: RouterSpace
  29    |     X-Cdn: RouterSpace-39792
  30    |     Accept-Ranges: bytes
  31    |     Cache-Control: public, max-age=0
  32    |     Last-Modified: Mon, 22 Nov 2021 11:33:57 GMT
  33    |     ETag: W/"652c-17d476c9285"
  34    |     Content-Type: text/html; charset=UTF-8
  35    |     Content-Length: 25900
  36    |     Date: Mon, 21 Mar 2022 03:15:44 GMT
  37    |     Connection: close
  38    |     <!doctype html>
  39    |     <html class="no-js" lang="zxx">
  40    |     <head>
  41    |     <meta charset="utf-8">
  42    |     <meta http-equiv="x-ua-compatible" content="ie=edge">
  43    |     <title>RouterSpace</title>
  44    |     <meta name="description" content="">
  45    |     <meta name="viewport" content="width=device-width, initial-scale=1">
  46    |     <link rel="stylesheet" href="css/bootstrap.min.css">
  47    |     <link rel="stylesheet" href="css/owl.carousel.min.css">
  48    |     <link rel="stylesheet" href="css/magnific-popup.css">
  49    |     <link rel="stylesheet" href="css/font-awesome.min.css">
  50    |     <link rel="stylesheet" href="css/themify-icons.css">
  51    |   HTTPOptions: 
  52    |     HTTP/1.1 200 OK
  53    |     X-Powered-By: RouterSpace
  54    |     X-Cdn: RouterSpace-44933
  55    |     Allow: GET,HEAD,POST
  56    |     Content-Type: text/html; charset=utf-8
  57    |     Content-Length: 13
  58    |     ETag: W/"d-bMedpZYGrVt1nR4x+qdNZ2GqyRo"
  59    |     Date: Mon, 21 Mar 2022 03:15:44 GMT
  60    |     Connection: close
  61    |     GET,HEAD,POST
  62    |   RTSPRequest, X11Probe: 
  63    |     HTTP/1.1 400 Bad Request
  64    |_    Connection: close
  65    |_http-favicon: Unknown favicon MD5: A02EBA0F638697761956C2E041BEBEF3
  66    | http-methods: 
  67    |_  Supported Methods: GET HEAD POST OPTIONS
  68    |_http-title: RouterSpace
  69    |_http-trane-info: Problem with XML parsing of /evox/about

Port 80 is most likely the entry point.

Navigating to the home page there is a link for an APK file download.

Since there were no other links, and every single other route would return this error message below, I decided to move onto the APK.

Static Analysis of APK

Decompiling the APK, running it through MobSF, and doing manual static analysis got me no where. It’s a React Native application and was difficult to “reverse engineer”. So I moved on.

Dynamic Analysis of Android App

Naturally the next thing to do is to do some dynamic analysis. I loaded up the APK in Genymotion. The app only did one thing. It had a “Check Status” button that when you click it sends a POST request to /api/v4/monitoring/router/dev/check/deviceAccess

I added those headers and changed the method to POST to attempt to discover more endpoints but nothing. So far this single request is the only attack surface for this box.

The request/response pair is simple. Whatever gets sent in the id POST parameter gets echo’d back to the user.

Exploitation

With this information my instinct was to use Bash Command Substitution to see if the command would get executed. Annnnnnddd voila! RCE.

Initial Access

Trying to get a reverse shell payload was failing for some reason. So instead I created an SSH keypair on my attacker machine and then added the SSH public key to /home/paul/.ssh/authorized_keys

After that we can just use the private key to SSH onto target without needing a password.

Local Enumeration

Combing through the LinPEAS output I noticed the Linux Exploit Suggester output.

LinPEAS is kinda bad at detecting whether a box is actually vulnerable to PwnKit or not. I tried it anyways and wasted some time. Well on to the next, sudo Baron Samedit I had not heard of this CVE/Exploit before but LinPEAS was kind enough to provide a link to a GitHub repo which made it easy and convenient. I began reading the writeup for the exploit and hit the “I believe” button. Heap based buffer overflows and Linux kernel exploitation / LPE are not a strong suit of mine.

Privilege Escalation

PE was straightforward and about as “script kiddie” level easy as you can get.

  1. Clone the repo
  2. Transfer the exploit_nss.py script to target
  3. Run the script & get root

Since outbound connections seemed to be blocked I used SCP with the private key from earlier to transfer files onto target.

Voila! Root.

Lessons Learned

  1. Never pass user input to exec() or similar functions that execute OS commands!
  2. Patch your systems especially when there is high/critical vulnerabilities.