JavaScript 应用安全:初学者的十大漏洞
Web 应用安全是每位开发者最重要的课题之一。JavaScript(尤其是在 Node.js 服务端)因其流行性常成为攻击者的目标。本文将介绍初学者最容易遇到的 10 个常见漏洞,并展示如何避免它们。
1. XSS(跨站脚本攻击)
XSS 是最常见的攻击之一,攻击者将恶意脚本注入网页。当用户数据未经过转义直接插入 HTML 时就会发生这种情况。
危险代码(存在漏洞):
app.get('/search', (req, res) => { const query = req.query.q; res.send(`<h1>Search results: ${query}</h1>`);});安全代码(防护措施):
const escapeHtml = require('escape-html');
app.get('/search', (req, res) => { const query = escapeHtml(req.query.q); res.send(`<h1>Search results: ${query}</h1>`);});2. SQL 注入
如果使用 SQL 数据库(例如 SQLite 或 PostgreSQL),未转义的查询可能导致数据泄露。
危险代码:
const user = req.body.username;db.query(`SELECT * FROM users WHERE name = '${user}'`);安全代码(使用参数化查询):
const user = req.body.username;db.query('SELECT * FROM users WHERE name = $1', [user]);3. 不安全的反序列化
对不可信数据使用 JSON.parse() 可能导致“原型污染”攻击。
漏洞示例:
const data = JSON.parse(req.body.jsonData);// 如果 data 包含 __proto__,可能会修改 Object 原型防护措施:始终在解析前验证数据,或使用 fast-json-stable-stringify 等库。
4. 缺乏输入验证
永远不要信任用户数据。始终检查数据的类型、长度和格式。
// 错误做法:接受一切app.post('/profile', (req, res) => { const { name, age } = req.body; // ...});
// 正确做法:进行验证const schema = { name: 'string', age: 'number' };if (typeof req.body.name !== 'string') throw new Error('Invalid name');5. CSRF(跨站请求伪造)
一种攻击方式,攻击者强制已认证用户在网站上执行非预期操作。
防护措施:使用 CSRF 令牌。
const csrf = require('csurf');app.use(csrf({ cookie: true }));
app.get('/form', (req, res) => { res.render('form', { csrfToken: req.csrfToken() });});6. 错误信息泄露
永远不要向用户显示详细的错误信息——这会让黑客获取应用架构信息。
错误做法:
app.use((err, req, res, next) => { res.status(500).send(err.stack); // 泄露调用堆栈!});正确做法:
app.use((err, req, res, next) => { console.error(err.stack); // 记录日志供自己查看 res.status(500).send('Internal server error');});7. 不安全地使用 eval() 和 Function()
eval() 和 new Function() 函数将字符串作为代码执行——如果字符串包含用户数据,这将极其危险。
// 危险!永远不要这样做const userInput = req.body.code;eval(userInput); // 攻击者可执行任意代码替代方案: