T05 · Unauthorized Access and Privilege Escalation
- Location
scripts/serve.mjs:63- Finding
Unauthenticated Network-Accessible Portfolio API
- Content
View full analysis
{ const url = new URL(req.url, `http://localhost:${PORT}`); // CORS res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type'); if (req.method === 'OPTIONS') { res.writeHead(204); res.end(); return; } // API: 获取数据 if (url.pathname === '/api/data' && req.method === 'GET') { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ ok: true, data: loadData() })); return; } // API: 保存数据 if (url.pathname === '/api/data' && req.method === 'POST') { let body = ''; req.on('data', chunk => body += chunk); req.on('end', () => { try { const data = JSON.parse(body); saveData(data); res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ ok: true })); } catch (e) { res.writeHead(400, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ ok: false, error: e.message })); } }); return; } }); server.listen(PORT, () => { console.log(`\n🚀 CryptoFolio 可视化界面已启动`); console.log(`📊 打开浏览器访问: http://localhost:${PORT}`); console.log(`📁 数据文件: ${DATA_FILE}`); console.log(`\n按 Ctrl+C 停止服务器\n`); }); ``` ### Technical Analysis The local API provides unauthenticated read and write access to the user's complete portfolio. It also returns `Access-Control-Allow-Origin: *`, allowing scripts from arbitrary origins to read API responses and submit JSON requests if they can reach the service. The call to `server.listen(PORT)` does not explicitly bind the service to `127.0.0.1`. Depending on ...[truncated 1420 chars]- Remediation
View remediation
{ // Startup message }); ``` 2. Generate an unpredictable per-session authentication token and require it for every API request. 3. Restrict `Access-Control-Allow-Origin` to the exact trusted UI origin instead of using `*`. 4. Validate the `Origin` and `Host` headers and reject unexpected values. 5. Use `SameSite=Strict` cookies or an explicit authorization header together with CSRF protection. 6. Separate read and write permissions if the UI does not always require write access. 7. Warn and fail safely if the selected port is already exposed through a proxy or non-loopback interface. ]]>
