在当今互联网时代,RESTful API 已成为前后端数据交互的主流方式。然而,由于 RESTful API 的开放性和公共性,安全成为 API 接口开发中必须注意的问题。本文将介绍 RESTful API 常见的安全漏洞及其防范措施,并提供示例代码加深理解。
1. SQL 注入攻击
SQL 注入攻击是指攻击者在实现输入数据时通过注入恶意 SQL 语句来获取、篡改或删除数据的行为。RESTful API 在处理查询参数时容易被注入攻击。
防范措施:
- 永远不要信任用户输入数据,对所有输入参数进行校验和过滤。
- 使用预编译语句或存储过程执行 SQL 查询操作,防止拼接 SQL 语句。
- 限制用户账号或角色在数据库中的操作权限。
示例代码:
// www.javascriptcn.com code example
// 漏洞代码:
app.get('/api/user/:id', (req, res) => {
const query = `SELECT * FROM users WHERE id=${req.params.id};`;
db.query(query, (err, result) => {
if (err) throw err;
res.send(result);
});
});
// 防范代码:
app.get('/api/user/:id', (req, res) => {
const id = parseInt(req.params.id);
if(isNaN(id)){
res.status(400).send({ message: 'id 参数不正确' });
return;
}
const query = 'SELECT * FROM users WHERE id=?;';
db.query(query, [id], (err, result) => {
if (err) throw err;
res.send(result);
});
});2. XSS 攻击
XSS 攻击是利用恶意注入脚本,比如 JavaScript,在目标网页上进行恶意操作。在 RESTful API 中,如果返回的数据容易被攻击者注入脚本,则会导致 XSS 攻击。
防范措施:
- 对所有用户输入的内容进行 XSS 过滤。
- 在输出数据时使用模板引擎或转义函数进行转义,例如使用
he模块。 - 清理所有请求参数,尤其是 GET 请求参数,以过滤恶意代码。
示例代码:
// www.javascriptcn.com code example
// 漏洞代码:
app.get('/api/search', (req, res) => {
const query = req.query.q;
const results = db.search(query);
res.send(results);
});
// 防范代码:
const he = require('he');
app.get('/api/search', (req, res) => {
const query = he.encode(req.query.q);
const results = db.search(query);
res.send(results);
});3. CSRF 攻击
CSRF 攻击是指攻击者冒充用户在被攻击网站上执行某些操作的一种攻击方式。RESTful API 在处理用户会话时容易受到 CSRF 攻击。
防范措施:
- 对所有 API 操作进行身份验证,例如使用 JWT 验证。
- 在服务端实现 CSRF Token 机制,验证每个请求的 CSRF Token 是否匹配。
示例代码:
// www.javascriptcn.com code example
// 漏洞代码:
app.post('/api/transfer', (req, res) => {
const from = req.body.from;
const to = req.body.to;
const amount = req.body.amount
db.transfer(from, to, amount);
res.send({ message: '转账成功' });
});
// 防范代码:
const jwt = require('jsonwebtoken');
const csrf = require('csurf')({ cookie: true });
const csrfSecret = 'secret';
app.post('/api/transfer', jwt.verify, csrf, (req, res) => {
const from = req.body.from;
const to = req.body.to;
const amount = req.body.amount;
db.transfer(from, to, amount);
res.send({ message: '转账成功' });
});
app.get('/api/csrf-token', (req, res) => {
const token = jwt.sign({ user: req.user }, csrfSecret);
res.cookie('XSRF-TOKEN', token);
res.send({ token: token });
});4. 文件上传漏洞
文件上传漏洞是指攻击者通过上传恶意文件来获得系统的控制权,或者通过上传大量文件来耗尽系统资源的一种漏洞。在 RESTful API 中,文件上传操作需要特别注意安全问题。
防范措施:
- 对上传的文件进行类型、大小、后缀等校验。
- 随机生成文件名或使用 UUID 作为文件名,避免文件名被攻击者猜到。
- 将上传的文件存储在非 Web 目录中,避免直接访问上传的文件。
示例代码:
// www.javascriptcn.com code example
// 漏洞代码:
const multer = require('multer');
const upload = multer({ dest: 'uploads/' });
app.post('/api/avatar', upload.single('avatar'), (req, res) => {
const file = req.file;
db.updateAvatar(req.user.id, `uploads/${file.filename}`);
res.send({ message: '上传成功' });
});
// 防范代码:
const fs = require('fs');
const path = require('path');
const uploadFolder = path.resolve(__dirname, 'uploads');
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, uploadFolder)
},
filename: function (req, file, cb) {
const ext = file.originalname.split('.').pop();
const filename = uuid();
cb(null, filename + '.' + ext)
}
})
const upload = multer({
storage: storage,
fileFilter: function (req, file, cb) {
const fileType = file.mimetype.split('/')[0];
if (fileType !== 'image') {
cb(new Error('文件类型不正确'));
} else {
cb(null, true);
}
}
});
app.post('/api/avatar', jwt.verify, upload.single('avatar'), (req, res) => {
const file = req.file;
fs.renameSync(file.path, path.resolve(uploadFolder, file.filename));
db.updateAvatar(req.user.id, `uploads/${file.filename}`);
res.send({ message: '上传成功' });
});结语
本文介绍了 RESTful API 常见的安全漏洞及其防范措施,并提供了示例代码。前端开发者应当注意在开发过程中加强安全意识,注重细节,根据具体业务需求切实加强 API 安全防范措施,确保代码的安全可靠性。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67d5c9c4a941bf7134b076d8