furniture-3d-system-Wu/tests/security/sql-injection.test.ts
WuYongJie 5a9482bc93 feat: 实现包装方案功能并修复所有类型错误
- 新增 PackagingPlan 数据库模型和迁移
- 实现包装方案 API (GET/POST/PUT/DELETE)
- 创建 PackagingEditor 组件用于管理包装方案
- 在产品详情页集成包装方案标签页
- 修复 API 路由 params Promise 类型适配 (Next.js 16)
- 修复脚本文件中 SKU ownerId 字段缺失问题
- 修复 jwt.ts、performance.ts、VirtualList.tsx 类型错误
- 修复测试文件导入路径和类型注解
- 所有 TypeScript 类型检查通过
2025-12-22 17:43:28 +08:00

276 lines
8.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* SQL 注入安全测试
*
* 测试目标:
* - 验证所有数据库查询都使用参数化查询
* - 确保 Prisma ORM 正确处理特殊字符
* - 测试各种 SQL 注入攻击向量
*
* @created 2025-12-13
*/
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
describe('SQL 注入安全测试', () => {
afterAll(async () => {
await prisma.$disconnect();
});
describe('用户查询 SQL 注入测试', () => {
it('应该安全处理包含 SQL 关键字的邮箱', async () => {
const maliciousEmail = "admin' OR '1'='1";
// Prisma 会自动使用参数化查询
const user = await prisma.user.findUnique({
where: { email: maliciousEmail },
});
// 应该返回 null,因为没有这个邮箱的用户
expect(user).toBeNull();
});
it('应该安全处理包含 SQL 注释的邮箱', async () => {
const maliciousEmail = "admin@example.com'; --";
const user = await prisma.user.findUnique({
where: { email: maliciousEmail },
});
expect(user).toBeNull();
});
it('应该安全处理包含 UNION 查询的邮箱', async () => {
const maliciousEmail = "admin@example.com' UNION SELECT * FROM User --";
const user = await prisma.user.findUnique({
where: { email: maliciousEmail },
});
expect(user).toBeNull();
});
it('应该安全处理包含 DROP TABLE 的输入', async () => {
const maliciousEmail = "admin@example.com'; DROP TABLE User; --";
const user = await prisma.user.findUnique({
where: { email: maliciousEmail },
});
expect(user).toBeNull();
// 验证 User 表仍然存在
const userCount = await prisma.user.count();
expect(userCount).toBeGreaterThanOrEqual(0);
});
});
describe('产品搜索 SQL 注入测试', () => {
it('应该安全处理包含 SQL 关键字的搜索查询', async () => {
const maliciousQuery = "'; DROP TABLE Product; --";
// 使用 contains 进行模糊搜索
const products = await prisma.product.findMany({
where: {
OR: [
{ name: { contains: maliciousQuery, mode: 'insensitive' } },
{ modelNumber: { contains: maliciousQuery, mode: 'insensitive' } },
],
},
});
// 应该返回空数组或正常结果,不会执行 DROP TABLE
expect(Array.isArray(products)).toBe(true);
// 验证 Product 表仍然存在
const productCount = await prisma.product.count();
expect(productCount).toBeGreaterThanOrEqual(0);
});
it('应该安全处理包含单引号的搜索查询', async () => {
const queryWithQuote = "O'Reilly";
const products = await prisma.product.findMany({
where: {
name: { contains: queryWithQuote, mode: 'insensitive' },
},
});
// 应该正常处理,不会导致 SQL 错误
expect(Array.isArray(products)).toBe(true);
});
it('应该安全处理包含反斜杠的搜索查询', async () => {
const queryWithBackslash = "test\\product";
const products = await prisma.product.findMany({
where: {
name: { contains: queryWithBackslash, mode: 'insensitive' },
},
});
expect(Array.isArray(products)).toBe(true);
});
});
describe('用户 ID 查询 SQL 注入测试', () => {
it('应该安全处理包含 SQL 关键字的 ID', async () => {
const maliciousId = "1 OR 1=1";
// Prisma 会验证 ID 类型
await expect(
prisma.user.findUnique({
where: { id: maliciousId },
})
).resolves.toBeNull();
});
it('应该安全处理包含特殊字符的 ID', async () => {
const maliciousId = "1'; DROP TABLE User; --";
await expect(
prisma.user.findUnique({
where: { id: maliciousId },
})
).resolves.toBeNull();
});
});
describe('复杂查询 SQL 注入测试', () => {
it('应该安全处理包含 SQL 注入的 WHERE 条件', async () => {
const maliciousName = "admin' OR '1'='1";
const maliciousEmail = "admin@example.com' OR '1'='1";
const users = await prisma.user.findMany({
where: {
AND: [
{ name: maliciousName },
{ email: maliciousEmail },
],
},
});
// 应该返回空数组,因为没有匹配的用户
expect(users).toEqual([]);
});
it('应该安全处理包含 SQL 注入的 ORDER BY', async () => {
// Prisma 的 orderBy 是类型安全的,不接受字符串
const products = await prisma.product.findMany({
orderBy: {
createdAt: 'desc',
},
});
expect(Array.isArray(products)).toBe(true);
});
it('应该安全处理包含 SQL 注入的分页参数', async () => {
// 测试恶意的 skip 和 take 参数
const maliciousSkip = "0; DROP TABLE Product; --";
const maliciousTake = "10 OR 1=1";
// Prisma 会验证参数类型,这些会导致类型错误
// 在实际应用中,应该在 API 层面验证这些参数
await expect(async () => {
await prisma.product.findMany({
skip: parseInt(maliciousSkip) || 0,
take: parseInt(maliciousTake) || 10,
});
}).not.toThrow();
});
});
describe('原始 SQL 查询安全测试', () => {
it('应该使用参数化查询执行原始 SQL', async () => {
const maliciousEmail = "admin' OR '1'='1";
// 使用 Prisma 的 $queryRaw 和参数化查询
const users = await prisma.$queryRaw`
SELECT * FROM "User" WHERE email = ${maliciousEmail}
` as unknown[];
// 应该返回空数组,参数被正确转义
expect(Array.isArray(users)).toBe(true);
expect(users.length).toBe(0);
});
it('不应该使用字符串拼接执行原始 SQL', async () => {
// 这是一个反例,展示不安全的做法
// 在实际代码中应该避免这种写法
const maliciousEmail = "admin' OR '1'='1";
// ❌ 不安全的做法(仅用于测试)
// const unsafeQuery = `SELECT * FROM "User" WHERE email = '${maliciousEmail}'`;
// ✅ 安全的做法:使用参数化查询
const safeUsers = await prisma.$queryRaw`
SELECT * FROM "User" WHERE email = ${maliciousEmail}
`;
expect(Array.isArray(safeUsers)).toBe(true);
});
});
describe('批量操作 SQL 注入测试', () => {
it('应该安全处理批量更新操作', async () => {
const maliciousData = {
name: "admin' OR '1'='1",
email: "admin@example.com'; DROP TABLE User; --",
};
// 尝试批量更新(实际上不会匹配任何记录)
const result = await prisma.user.updateMany({
where: {
email: maliciousData.email,
},
data: {
name: maliciousData.name,
},
});
// 应该返回 0 条更新记录
expect(result.count).toBe(0);
// 验证表仍然存在
const userCount = await prisma.user.count();
expect(userCount).toBeGreaterThanOrEqual(0);
});
it('应该安全处理批量删除操作', async () => {
const maliciousCondition = "1=1; DROP TABLE User; --";
// Prisma 的类型系统会阻止这种查询
// 这里我们测试正常的删除操作
const result = await prisma.user.deleteMany({
where: {
email: maliciousCondition,
},
});
expect(result.count).toBe(0);
});
});
});
/**
* 测试总结:
*
* Prisma ORM 的安全特性:
* 1. ✅ 自动使用参数化查询
* 2. ✅ 类型安全的查询构建
* 3. ✅ 自动转义特殊字符
* 4. ✅ 防止 SQL 注入攻击
*
* 最佳实践:
* 1. 始终使用 Prisma 的查询 API,避免原始 SQL
* 2. 如果必须使用原始 SQL,使用 $queryRaw 和参数化查询
* 3. 在 API 层面验证和清理用户输入
* 4. 使用 TypeScript 的类型系统增强安全性
*
* 结论:
* Prisma ORM 提供了强大的 SQL 注入防护,
* 只要正确使用其 API,系统就能有效防止 SQL 注入攻击。
*/