/** * 输入清理和验证工具 * 防止命令注入、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路径遍历 // 脚本执行 /]*>/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>(obj: T): T { const sanitized = { ...obj }; for (const key in sanitized) { if (typeof sanitized[key] === "string") { sanitized[key] = sanitizeString(sanitized[key]) as T[Extract]; } else if (typeof sanitized[key] === "object" && sanitized[key] !== null) { sanitized[key] = sanitizeObject(sanitized[key]) as T[Extract]; } } 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, }; }