MST
星途 面试题库

面试题:网络编程:WebSocket全双工通信与安全机制深度剖析

WebSocket全双工通信在带来便捷的同时也伴随着安全风险。请深入分析WebSocket通信过程中可能存在的安全漏洞,如跨站WebSocket劫持(CSWSH)等,并阐述如何在设计和开发过程中构建全面且高效的安全机制来防范这些风险。
13.9万 热度难度
后端开发网络编程

知识考点

AI 面试

面试题答案

一键面试

WebSocket通信安全漏洞分析

  1. 跨站WebSocket劫持(CSWSH)
    • 原理:攻击者利用用户在已认证的站点上的登录状态,通过在恶意页面中创建WebSocket连接,劫持用户与目标WebSocket服务器的通信。由于浏览器会自动带上目标站点的Cookie等认证信息,恶意页面就能以用户身份与WebSocket服务器交互。
    • 危害:攻击者可以获取用户敏感数据,如在即时通讯应用中获取聊天记录,或者执行未经授权的操作,如在金融应用中发起转账指令。
  2. 未授权访问
    • 原理:如果WebSocket服务器没有适当的身份验证和授权机制,恶意用户可能直接连接到WebSocket服务器,获取敏感信息或干扰正常服务。例如,在一个多租户的应用中,某个租户的用户可能尝试连接其他租户的WebSocket服务端口。
    • 危害:数据泄露、服务中断等,影响系统的可用性和数据保密性。
  3. 注入攻击
    • 原理:类似于SQL注入,攻击者通过WebSocket发送恶意构造的数据,若服务器端没有对输入进行严格验证和过滤,可能导致命令执行、数据篡改等后果。例如,在一个基于WebSocket的命令执行系统中,攻击者发送恶意命令字符串。
    • 危害:服务器被控制、数据被非法修改,严重威胁系统安全。
  4. 中间人攻击
    • 原理:攻击者在客户端和服务器之间的通信链路中拦截、篡改WebSocket消息。由于WebSocket通常使用HTTP升级机制,在初始握手阶段可能被中间人利用,修改握手信息,之后就能监听和篡改通信内容。
    • 危害:数据泄露、数据完整性被破坏,用户可能收到伪造的信息,做出错误决策。

安全机制构建

  1. 针对CSWSH的防范
    • 使用Origin头部验证:服务器在接收到WebSocket连接请求时,检查Origin头部字段,确保请求来自合法的源。如果Origin头部缺失或不匹配合法站点,拒绝连接。例如,在Node.js的WebSocket服务器中,可以通过如下代码实现:
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', function connection(ws, req) {
    const origin = req.headers.origin;
    const allowedOrigins = ['http://example.com', 'https://example.com'];
    if (!allowedOrigins.includes(origin)) {
        ws.close(1008, 'Invalid origin');
        return;
    }
    // 处理正常连接
});
  • 使用CSRF令牌:在客户端生成一个随机的CSRF令牌,在WebSocket连接握手时,将令牌作为参数发送到服务器。服务器验证令牌的有效性,确保请求是合法的用户操作发起的。例如,在HTML页面中生成令牌并在JavaScript中使用:
<input type="hidden" id="csrf-token" value="{{csrf_token()}}">
<script>
    const csrfToken = document.getElementById('csrf-token').value;
    const socket = new WebSocket('ws://example.com/socket?csrf=' + csrfToken);
</script>
  1. 身份验证和授权
    • 用户认证:在WebSocket连接建立前,要求用户进行身份验证。可以复用现有Web应用的认证机制,如JWT(JSON Web Token)。在客户端将JWT包含在WebSocket连接请求中,服务器验证JWT的有效性:
// 客户端
const jwt = localStorage.getItem('jwt_token');
const socket = new WebSocket('ws://example.com/socket?token=' + jwt);

// 服务器端(Node.js示例)
const jwt = require('jsonwebtoken');
wss.on('connection', function connection(ws, req) {
    const token = req.url.split('=')[1];
    try {
        const decoded = jwt.verify(token, 'your-secret-key');
        // 认证通过,处理连接
    } catch (err) {
        ws.close(1008, 'Authentication failed');
    }
});
  • 授权机制:基于用户角色或权限进行授权。在用户通过身份验证后,服务器检查用户是否有权限访问特定的WebSocket资源。例如,在一个文档管理系统中,只有文档所有者和具有特定权限的用户才能通过WebSocket实时编辑文档。
  1. 输入验证和过滤
    • 验证数据格式:在服务器端,对收到的WebSocket消息进行严格的数据格式验证。例如,如果期望接收的是JSON格式的数据,使用JSON.parse()方法解析时捕获异常,若解析失败则拒绝该消息。
wss.on('message', function incoming(message) {
    try {
        const data = JSON.parse(message);
        // 处理合法数据
    } catch (err) {
        // 拒绝非法数据
    }
});
  • 过滤敏感字符:对于可能导致注入攻击的敏感字符,如SQL语句中的特殊字符、操作系统命令中的特殊字符等,进行过滤或转义。可以使用正则表达式匹配并处理敏感字符。
  1. 防范中间人攻击
    • 使用TLS/SSL加密:在WebSocket通信中使用TLS/SSL协议,确保数据在传输过程中的保密性和完整性。这会对客户端和服务器之间的所有数据进行加密,中间人无法直接读取或篡改数据。在Node.js中,可以使用https模块创建安全的WebSocket服务器:
const https = require('https');
const fs = require('fs');
const WebSocket = require('ws');

const options = {
    key: fs.readFileSync('privatekey.pem'),
    cert: fs.readFileSync('certificate.pem')
};

const server = https.createServer(options);
const wss = new WebSocket.Server({ server });

server.listen(443, function () {
    console.log('Server listening on port 443');
});
  • 证书验证:客户端在连接到WebSocket服务器时,验证服务器的SSL证书的有效性。这可以防止中间人使用伪造的证书进行攻击。现代浏览器通常会自动进行证书验证,但在自定义客户端开发中,需要确保正确配置证书验证逻辑。