id: authentication-headers-required name: API认证头部要求规则 description: 验证API请求是否包含必要的认证头部,如Authorization、X-API-Key等 category: Security version: 1.0.0 severity: error is_enabled: true tags: - security - authentication - headers - authorization target_type: APIRequest lifecycle: RequestPreparation scope: RequestHeaders required_headers: - name: Authorization pattern: "^(Bearer|Basic|Digest) [A-Za-z0-9\\-\\._~\\+\\/]+=*$" description: 认证令牌,格式应为"Bearer token"、"Basic base64"或"Digest value" - name: X-API-Key pattern: "^[A-Za-z0-9]{32,64}$" description: API密钥,应为32-64位的字母数字字符 - name: X-Request-ID pattern: "^[A-Za-z0-9\\-]{8,36}$" description: 请求ID,用于跟踪请求,应为8-36位的字母数字和连字符 check_mode: any # 可以是"all"或"any",表示是需要满足所有头部还是任一头部 code: | def validate(context): """验证API请求是否包含必要的认证头部""" request = context.get('api_request') if not request: return {'is_valid': False, 'message': '缺少API请求对象'} headers = request.headers or {} required_headers = context.get('required_headers', []) check_mode = context.get('check_mode', 'any') # 获取缺失的头部和无效的头部 missing_headers = [] invalid_headers = [] valid_headers = [] import re for header in required_headers: header_name = header.get('name') header_pattern = header.get('pattern') if header_name not in headers: missing_headers.append({ 'name': header_name, 'description': header.get('description', '') }) continue header_value = headers[header_name] # 如果指定了模式,验证头部值是否符合模式 if header_pattern and not re.match(header_pattern, header_value): invalid_headers.append({ 'name': header_name, 'value': header_value, 'pattern': header_pattern, 'description': header.get('description', '') }) else: valid_headers.append(header_name) # 根据检查模式判断是否验证通过 if check_mode == 'all': # 需要所有头部都存在且有效 is_valid = not missing_headers and not invalid_headers else: # 'any' # 至少有一个有效的头部即可 is_valid = len(valid_headers) > 0 if is_valid: message = '请求包含有效的认证头部' if check_mode == 'any': message += f": {', '.join(valid_headers)}" else: if check_mode == 'all': if missing_headers: message = f"请求缺少必要的认证头部: {', '.join([h['name'] for h in missing_headers])}" else: message = f"请求包含无效的认证头部: {', '.join([h['name'] for h in invalid_headers])}" else: # 'any' message = f"请求不包含任何有效的认证头部,至少需要其中之一: {', '.join([h['name'] for h in required_headers])}" return { 'is_valid': is_valid, 'message': message, 'details': { 'check_mode': check_mode, 'valid_headers': valid_headers, 'missing_headers': missing_headers, 'invalid_headers': invalid_headers } }