T05 · Unauthorized Access and Privilege Escalation
Error
- Location
- server.js:86
- Finding
- Unauthenticated WebSocket API Permits Complete Browser Control and Arbitrary Page-Context JavaScript<![CDATA[ ## Vulnerability Details **File Location**: `server.js:75-78`, `server.js:86-113` **Vulnerability Type**: Missing authentication and authorization for a privileged browser-control interface **Risk Level**: High ### Vulnerable Code ```js case 'evaluate': if (!wsPage) throw new Error('没有活动的页面'); const result = await wsPage.evaluate(params.script); return { result }; ``` ```js // 启动 WebSocket 服务器 const wss = new WebSocket.Server({ port: PORT }); console.log(`🦞 AI Browser Server 启动在 ws://localhost:${PORT}`); wss.on('connection', (ws) => { console.log('🔌 新的客户端连接'); ws.on('message', async (message) => { try { const { action, params, id } = JSON.parse(message); console.log(`⚡ 收到指令:${action}`, params); if (!browser) await initBrowser(); if (!page) page = await browser.newPage(); if (params.targetId) { // 简单处理:如果有 targetId 且不是当前页,尝试切换(简化版暂不实现多 Tab 切换逻辑,默认单页) // 实际使用中,可以扩展为多 page 管理 } const result = await handleAction(action, params || {}); ws.send(JSON.stringify({ id, success: true, result })); } catch (error) { console.error('❌ 执行错误:', error); ws.send(JSON.stringify({ id: JSON.parse(message).id, success: false, error: error.message })); } }); ws.on('close', () => { console.log('🔌 客户端断开连接'); }); }); ``` ### Technical Analysis The WebSocket server accepts connections without authenticating the client, checking authorization, or validating the WebSocket `Origin` header. Constructing `WebSocket.Server` with only a port does not explicitly restrict the listener to the loopback interface, despite the documentation presenting the service as a localhost endpoint. Every connected client receives access to the same shared Chromium instance and page. Available actions include navigation, screenshots, DOM extraction, clicking, typing, and `ev ...[truncated 1883 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Explicitly bind the service to a loopback address unless remote access is essential: ```js const wss = new WebSocket.Server({ host: '127.0.0.1', port: PORT }); ``` 2. Require a cryptographically random, per-installation or per-session authentication token during the HTTP upgrade or initial protocol handshake. 3. Reject connections with an unapproved `Origin` header to mitigate browser-based cross-site WebSocket attacks. 4. Use TLS and client authentication if the interface must be remotely accessible. 5. Remove the unrestricted `evaluate` action. If evaluation is required, replace it with narrowly scoped, predefined operations rather than accepting JavaScript source. 6. Apply authorization independently to sensitive operations such as screenshots, DOM extraction, typing, navigation, and evaluation. 7. Allocate an isolated browser context and page per authenticated client rather than sharing one global page. 8. Add connection limits, message-size limits, request timeouts, and rate limiting. 9. Run the service under a dedicated, low-privilege operating-system account. ]]>
