- 添加速率限制中间件,防止API滥用和DDoS攻击 - 添加可疑请求检测,基于行为模式识别攻击 - 添加输入清理和验证,防止命令注入和XSS攻击 - 更新middleware.ts,集成所有安全功能 - 添加fail2ban安装脚本,防止SSH暴力破解 - 不依赖IP黑名单,适用于所有攻击者 安全功能: - API速率限制:每分钟100次请求 - 认证速率限制:每分钟5次请求 - 自动检测可疑请求模式 - 输入清理和验证 - 详细的安全日志记录
125 lines
3.0 KiB
TypeScript
125 lines
3.0 KiB
TypeScript
/**
|
||
* 输入清理和验证工具
|
||
* 防止命令注入、XSS等攻击
|
||
*/
|
||
|
||
// 危险命令和关键词模式
|
||
const DANGEROUS_PATTERNS = [
|
||
// 命令执行
|
||
/[;&|`$(){}[\]]/g, // 命令分隔符
|
||
/\b(wget|curl|nc|netcat|bash|sh|python|perl|ruby|node)\s+/gi,
|
||
/\b(exec|eval|system|spawn|execSync|execFile)\s*\(/gi,
|
||
|
||
// 文件操作
|
||
/\.\.\//g, // 路径遍历
|
||
/\.\.\\/g, // Windows路径遍历
|
||
|
||
// 脚本执行
|
||
/<script[^>]*>/gi,
|
||
/javascript:/gi,
|
||
/on\w+\s*=/gi, // 事件处理器
|
||
|
||
// SQL注入模式(虽然我们使用ORM,但作为额外保护)
|
||
/('|(\\')|(--)|(;)|(\/\*)|(\*\/)|(\+)|(\%27)|(\%22))/gi,
|
||
|
||
// 命令注入常见模式
|
||
/\|\s*(bash|sh|nc|wget|curl)/gi,
|
||
/;\s*(wget|curl|nc|bash|sh)/gi,
|
||
/\$\s*\(/g, // $(command)
|
||
/`[^`]*`/g, // 反引号命令执行
|
||
];
|
||
|
||
/**
|
||
* 清理字符串,移除危险字符
|
||
*/
|
||
export function sanitizeString(input: string): string {
|
||
if (typeof input !== "string") {
|
||
return String(input);
|
||
}
|
||
|
||
let sanitized = input;
|
||
|
||
// 移除危险模式
|
||
for (const pattern of DANGEROUS_PATTERNS) {
|
||
sanitized = sanitized.replace(pattern, "");
|
||
}
|
||
|
||
// 移除控制字符
|
||
sanitized = sanitized.replace(/[\x00-\x1F\x7F]/g, "");
|
||
|
||
// 限制长度(防止DoS)
|
||
if (sanitized.length > 10000) {
|
||
sanitized = sanitized.substring(0, 10000);
|
||
}
|
||
|
||
return sanitized.trim();
|
||
}
|
||
|
||
/**
|
||
* 验证字符串是否包含危险内容
|
||
*/
|
||
export function containsDangerousContent(input: string): boolean {
|
||
if (typeof input !== "string") {
|
||
return false;
|
||
}
|
||
|
||
for (const pattern of DANGEROUS_PATTERNS) {
|
||
if (pattern.test(input)) {
|
||
return true;
|
||
}
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* 清理对象中的所有字符串值
|
||
*/
|
||
export function sanitizeObject<T extends Record<string, any>>(obj: T): T {
|
||
const sanitized = { ...obj };
|
||
|
||
for (const key in sanitized) {
|
||
if (typeof sanitized[key] === "string") {
|
||
sanitized[key] = sanitizeString(sanitized[key]) as T[Extract<keyof T, string>];
|
||
} else if (typeof sanitized[key] === "object" && sanitized[key] !== null) {
|
||
sanitized[key] = sanitizeObject(sanitized[key]) as T[Extract<keyof T, string>];
|
||
}
|
||
}
|
||
|
||
return sanitized;
|
||
}
|
||
|
||
/**
|
||
* 验证请求体
|
||
*/
|
||
export async function validateRequestBody(body: any): Promise<{
|
||
valid: boolean;
|
||
sanitized?: any;
|
||
errors?: string[];
|
||
}> {
|
||
const errors: string[] = [];
|
||
|
||
// 将body转换为字符串进行检查
|
||
const bodyString = typeof body === "string" ? body : JSON.stringify(body);
|
||
|
||
// 检查危险内容
|
||
if (containsDangerousContent(bodyString)) {
|
||
errors.push("Request body contains potentially dangerous content");
|
||
}
|
||
|
||
// 如果body是对象,清理它
|
||
let sanitized = body;
|
||
if (typeof body === "object" && body !== null) {
|
||
sanitized = sanitizeObject(body);
|
||
} else if (typeof body === "string") {
|
||
sanitized = sanitizeString(body);
|
||
}
|
||
|
||
return {
|
||
valid: errors.length === 0,
|
||
sanitized: errors.length === 0 ? sanitized : undefined,
|
||
errors: errors.length > 0 ? errors : undefined,
|
||
};
|
||
}
|
||
|