""" SQL注入防护测试套件 测试范围: 1. 用户输入SQL注入测试 2. 查询参数注入测试 3. 排序字段注入测试 4. 搜索关键词注入测试 5. 批量操作注入测试 作者: 张翔 日期: 2026-04-01 """ import pytest from api.auth_api import AuthAPI from api.user_api import UserAPI from api.role_api import RoleAPI from api.menu_api import MenuAPI from config.settings import settings @pytest.mark.security @pytest.mark.asyncio class TestSQLInjection: """SQL注入防护测试类""" async def test_user_search_sql_injection(self, authenticated_client): """ SEC-SQL-01: 用户搜索SQL注入测试 验证点: 1. 搜索框无法注入SQL 2. 特殊字符被正确处理 3. 查询参数化 """ user_api = UserAPI(authenticated_client) sql_injection_payloads = [ "admin' OR '1'='1", "admin'; DROP TABLE users; --", "admin' UNION SELECT * FROM users --", "admin' AND 1=1 --", "admin' AND 1=2 --", "admin' OR 'x'='x", "1; SELECT * FROM users", "admin'/*", "admin'--", "' OR 1=1#", "admin' AND SLEEP(5)--", "admin'; WAITFOR DELAY '0:0:5'; --" ] for payload in sql_injection_payloads: response = await user_api.get_users_by_page( page=0, size=10, username=payload ) assert response.status_code in [200, 400], \ f"SQL注入payload '{payload}' 导致异常响应" if response.status_code == 200: data = response.json() assert "content" in data or "users" in data, \ f"响应格式异常,payload: {payload}" async def test_user_create_sql_injection(self, authenticated_client): """ SEC-SQL-02: 用户创建SQL注入测试 验证点: 1. 用户名字段防注入 2. 邮箱字段防注入 3. 电话字段防注入 """ user_api = UserAPI(authenticated_client) malicious_user_data = { "username": "test'; DROP TABLE users; --", "password": "Test123!@#", "email": "test@example.com'; DROP TABLE users; --", "phone": "13800138000'; DROP TABLE users; --", "nickname": "测试用户", "status": 1 } response = await user_api.create_user(malicious_user_data) if response.status_code in [201, 200]: user_id = response.json().get("id") if user_id: await user_api.delete_user(user_id) users_response = await user_api.get_users_by_page() assert users_response.status_code == 200, "用户表应该仍然存在" else: assert response.status_code in [400, 422], \ "恶意数据应被拒绝或清洗" async def test_role_search_sql_injection(self, authenticated_client): """ SEC-SQL-03: 角色搜索SQL注入测试 验证点: 1. 角色名搜索防注入 2. 角色键搜索防注入 """ role_api = RoleAPI(authenticated_client) injection_payloads = [ "admin' OR '1'='1", "admin'; DELETE FROM roles WHERE '1'='1", "admin' UNION SELECT * FROM roles --" ] for payload in injection_payloads: response = await role_api.get_roles_by_page( page=0, size=10, roleName=payload ) assert response.status_code in [200, 400], \ f"SQL注入payload '{payload}' 导致异常" async def test_menu_search_sql_injection(self, authenticated_client): """ SEC-SQL-04: 菜单搜索SQL注入测试 验证点: 1. 菜单名搜索防注入 2. 菜单路径搜索防注入 """ menu_api = MenuAPI(authenticated_client) injection_payloads = [ "系统管理' OR '1'='1", "系统管理'; DROP TABLE menus; --", "/system' UNION SELECT * FROM menus --" ] for payload in injection_payloads: response = await menu_api.get_menus( menuName=payload ) assert response.status_code in [200, 400], \ f"SQL注入payload '{payload}' 导致异常" async def test_order_by_sql_injection(self, authenticated_client): """ SEC-SQL-05: 排序字段SQL注入测试 验证点: 1. 排序字段防注入 2. 排序方向防注入 """ user_api = UserAPI(authenticated_client) malicious_sort_fields = [ "id; DROP TABLE users", "id; SELECT * FROM users", "id UNION SELECT * FROM users", "(SELECT CASE WHEN 1=1 THEN id ELSE username END)", "id; INSERT INTO users VALUES (999, 'hacker', 'hacked')" ] for sort_field in malicious_sort_fields: response = await user_api.get_users_by_page( page=0, size=10, sortBy=sort_field, sortOrder="asc" ) assert response.status_code in [200, 400], \ f"排序注入 '{sort_field}' 导致异常" async def test_batch_delete_sql_injection(self, authenticated_client): """ SEC-SQL-06: 批量删除SQL注入测试 验证点: 1. 批量删除ID列表防注入 2. 删除操作参数化 """ user_api = UserAPI(authenticated_client) malicious_ids = [ "1,2,3; DROP TABLE users", "1 OR 1=1", "1; DELETE FROM users WHERE 1=1" ] for ids in malicious_ids: try: response = await user_api.batch_delete_users(ids) assert response.status_code in [400, 404, 422], \ f"批量删除注入 '{ids}' 应被拒绝" except Exception: pass async def test_filter_sql_injection(self, authenticated_client): """ SEC-SQL-07: 过滤条件SQL注入测试 验证点: 1. 过滤参数防注入 2. 复杂查询条件安全 """ user_api = UserAPI(authenticated_client) injection_filters = { "status": "1 OR 1=1", "email": "test@example.com' OR '1'='1", "phone": "13800138000' OR '1'='1" } for field, value in injection_filters.items(): response = await user_api.get_users_by_page( page=0, size=10, **{field: value} ) assert response.status_code in [200, 400], \ f"过滤注入 '{field}={value}' 导致异常" async def test_time_based_sql_injection(self, authenticated_client): """ SEC-SQL-08: 时间盲注测试 验证点: 1. SLEEP函数被过滤 2. WAITFOR命令被过滤 3. 时间盲注无效 """ user_api = UserAPI(authenticated_client) time_based_payloads = [ "admin' AND SLEEP(5)--", "admin' AND (SELECT * FROM (SELECT(SLEEP(5)))a)--", "admin'; WAITFOR DELAY '0:0:5'; --", "admin' AND BENCHMARK(5000000,SHA1('test'))--" ] import time for payload in time_based_payloads: start_time = time.time() response = await user_api.get_users_by_page( page=0, size=10, username=payload ) elapsed_time = time.time() - start_time assert elapsed_time < 6, \ f"时间盲注 '{payload}' 可能成功,响应时间: {elapsed_time}秒" assert response.status_code in [200, 400] async def test_union_based_sql_injection(self, authenticated_client): """ SEC-SQL-09: UNION注入测试 验证点: 1. UNION SELECT被阻止 2. 列数探测无效 """ user_api = UserAPI(authenticated_client) union_payloads = [ "admin' UNION SELECT NULL--", "admin' UNION SELECT NULL,NULL--", "admin' UNION SELECT NULL,NULL,NULL--", "admin' UNION SELECT username,password,email FROM users--", "admin' UNION ALL SELECT 1,2,3,4,5,6,7,8,9,10--" ] for payload in union_payloads: response = await user_api.get_users_by_page( page=0, size=10, username=payload ) assert response.status_code in [200, 400], \ f"UNION注入 '{payload}' 导致异常" if response.status_code == 200: data = response.json() content = data.get("content", []) for item in content: assert isinstance(item, dict), \ f"UNION注入可能成功,返回了非预期数据: {item}"