面试题答案
一键面试SQL 注入漏洞
- 根本原因:
- 当应用程序在构建 SQL 查询时,直接使用用户输入,而没有对输入进行适当的转义或参数化处理。例如,在使用
mysql2
等数据库驱动与 Next.js API Routes 结合时,如果代码类似const query =
SELECT * FROM users WHERE username = '${req.body.username}'``,这里直接将用户输入嵌入 SQL 语句,恶意用户可以通过构造特殊的输入字符串来改变 SQL 查询的逻辑,如输入'; DROP TABLE users; --
,就可能导致整个users
表被删除。
- 当应用程序在构建 SQL 查询时,直接使用用户输入,而没有对输入进行适当的转义或参数化处理。例如,在使用
- 修复步骤和方法:
- 参数化查询:以
mysql2
为例,使用参数化查询。例如:
- 参数化查询:以
import mysql from'mysql2';
const connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'password',
database: 'test'
});
export default async function handler(req, res) {
const { username } = req.body;
const query = 'SELECT * FROM users WHERE username =?';
connection.query(query, [username], (error, results, fields) => {
if (error) {
res.status(500).json({ error: 'Database error' });
return;
}
res.status(200).json(results);
});
}
- 使用 ORM(对象关系映射):如
Sequelize
或TypeORM
。以Sequelize
为例:
const Sequelize = require('sequelize');
const sequelize = new Sequelize('database', 'username', 'password', {
host: 'localhost',
dialect:'mysql'
});
const User = sequelize.define('user', {
username: Sequelize.STRING
});
export default async function handler(req, res) {
const { username } = req.body;
try {
const users = await User.findAll({ where: { username } });
res.status(200).json(users);
} catch (error) {
res.status(500).json({ error: 'Database error' });
}
}
- 代码审查预防:
- 检查所有数据库查询代码,确保没有直接拼接用户输入到 SQL 语句中。
- 确认是否使用了参数化查询或 ORM 进行数据库操作。
- 自动化工具检测:
- 使用工具如
sqlmap
对 API 进行扫描,它可以检测出潜在的 SQL 注入漏洞。在 CI/CD 流程中集成sqlmap
,定期对 API 进行扫描。
- 使用工具如
XSS 漏洞
- 根本原因:
- 在 Next.js 项目中,当直接将用户输入输出到 HTML 页面而没有进行适当的转义时,就可能引发 XSS 漏洞。例如,在 API Routes 返回的数据被前端直接渲染,如
res.status(200).send(
${req.body.message}
)
,如果恶意用户输入<script>alert('XSS')</script>
,这段脚本就会在页面加载时执行,从而获取用户的 cookie 等敏感信息。
- 在 Next.js 项目中,当直接将用户输入输出到 HTML 页面而没有进行适当的转义时,就可能引发 XSS 漏洞。例如,在 API Routes 返回的数据被前端直接渲染,如
- 修复步骤和方法:
- 输出转义:在 Node.js 中,可以使用
DOMPurify
库对输出进行净化。首先安装DOMPurify
:npm install dompurify
。
- 输出转义:在 Node.js 中,可以使用
import DOMPurify from 'dompurify';
export default async function handler(req, res) {
const { message } = req.body;
const cleanMessage = DOMPurify.sanitize(message);
res.status(200).send(`<p>${cleanMessage}</p>`);
}
- 在前端渲染时转义:如果是 React 前端,React 本身默认会对数据进行转义。但是如果使用了
dangerouslySetInnerHTML
,需要特别小心。例如:
import React from'react';
const { message } = props;
return <div dangerouslySetInnerHTML={{ __html: message }} />; // 危险,不要这样做
// 应该对数据进行预处理
import DOMPurify from 'dompurify';
const cleanMessage = DOMPurify.sanitize(message);
return <div dangerouslySetInnerHTML={{ __html: cleanMessage }} />;
- 代码审查预防:
- 检查所有将用户输入输出到 HTML 的地方,确认是否进行了适当的转义或净化。
- 对于使用
dangerouslySetInnerHTML
的情况,确保输入数据是经过净化处理的。
- 自动化工具检测:
- 使用工具如
xsshunter
进行 XSS 漏洞扫描。在 CI/CD 流程中集成相关扫描工具,对前端和 API 进行定期扫描,检测潜在的 XSS 漏洞。
- 使用工具如