Шаг 1: Инвентаризация и анализ поверхности атаки (15 минут). Прежде чем защищать, нужно знать что. Составьте полный каталог всех ваших API-эндпоинтов: URL, методы (GET, POST, PUT, DELETE), принимаемые параметры (query, body, headers), требуемая аутентификация и роли. Инструменты вроде Swagger/OpenAPI спецификации — ваш лучший друг. Проанализируйте каждый эндпоинт с точки зрения злоумышленника: какие данные он открывает? Какие операции позволяет? Это критически важные (CRUD пользователей, платежи) или вспомогательные (получение справочников)?
Шаг 2: Внедрение базовых тестов аутентификации и авторизации (30 минут). Самые распространенные уязвимости — сломанная система контроля доступа. Ваши тесты должны это проверять автоматически. Для каждого эндпоинта напишите как минимум три тестовых сценария:
- Запрос без токена аутентификации (должен возвращать 401 Unauthorized).
- Запрос с валидным токеном пользователя с недостаточными правами (например, роль `user` к эндпоинту `/api/admin/users`) — должен возвращать 403 Forbidden.
- Запрос с валидным токеном и корректными правами (должен возвращать 2xx или 4xx, но не 401/403).
```python
import pytest
import requests
BASE_URL = "https://api.yourservice.com"
USER_TOKEN = "valid_user_jwt"
ADMIN_TOKEN = "valid_admin_jwt"
def test_admin_endpoint_requires_auth():
"""Эндпоинт администратора должен требовать аутентификацию."""
response = requests.get(f"{BASE_URL}/api/admin/users")
assert response.status_code == 401
def test_admin_endpoint_forbidden_for_user():
"""Эндпоинт администратора должен быть запрещен для обычного пользователя."""
headers = {"Authorization": f"Bearer {USER_TOKEN}"}
response = requests.get(f"{BASE_URL}/api/admin/users", headers=headers)
assert response.status_code == 403
def test_admin_endpoint_accessible_for_admin():
"""Эндпоинт администратора доступен для админа."""
headers = {"Authorization": f"Bearer {ADMIN_TOKEN}"}
response = requests.get(f"{BASE_URL}/api/admin/users", headers=headers)
assert response.status_code == 200
```
Такие тесты должны стать частью вашего основного набора интеграционных/API-тестов и запускаться при каждом коммите.
Шаг 3: Тестирование валидации входных данных и инъекций (40 минут). Второй по критичности класс уязвимостей. Напишите параметризованные тесты, которые проверяют, что ваш API корректно обрабатывает некорректные, неожиданные и зловредные данные. Используйте библиотеки вроде `faker` для генерации тестовых данных или заранее подготовленные векторы атак.
- **SQL/NoSQL-инъекции:** Попробуйте передать в строковые параметры значения вроде `' OR '1'='1` или `{"$ne": null}`.
- **XSS:** Попробуйте передать в поля скрипты: `alert(1)`.
- **Неверные типы данных:** Передайте строку туда, где ожидается число, массив вместо объекта и т.д.
- **Очень длинные строки** (Buffer Overflow): Отправьте параметр с длиной в 10000+ символов.
- **Path Traversal:** В параметрах, которые могут указывать на файлы, попробуйте `../../../etc/passwd`.
```python
import pytest
@pytest.mark.parametrize("malicious_input", [
"' OR '1'='1",
"alert('xss')",
"; DROP TABLE users;",
"../../../etc/passwd",
"a" * 10000 # Очень длинная строка
])
def test_user_search_input_sanitization(malicious_input):
"""Поиск пользователя должен быть защищен от инъекций."""
params = {"username": malicious_input}
response = requests.get(f"{BASE_URL}/api/users", params=params, headers=valid_headers)
# Ожидаем, что API не упадет с 500, а вернет 400 или пустой/фильтрованный результат
assert response.status_code in (200, 400)
if response.status_code == 200:
# Убедимся, что инъекция не сработала - результат должен быть пустым или безопасным
data = response.json()
assert data["total"] == 0 or not any(malicious_input in str(item) for item in data["items"])
```
Шаг 4: Интеграция в CI/CD и мониторинг (5 минут). Запускайте эти тесты безопасности наравне с функциональными в вашем пайплайне непрерывной интеграции. Настройте оповещения, если какой-либо из этих тестов начнет падать (это может сигнализировать как о регрессе в безопасности, так и об изменении бизнес-логики). Рассмотрите возможность использования специализированных инструментов статического анализа кода (SAST) для API, таких как `Checkmarx` или `Semgrep`, которые могут находить уязвимости в самом коде контроллеров.
Внедрение этих практик не сделает ваше API неуязвимым, но создаст мощный автоматизированный щит, который ловит самые распространенные и критические ошибки безопасности на самой ранней стадии — в момент написания кода. Это превращает безопасность из периодического аудита в неотъемлемую часть культуры разработки, где каждый коммит становится чуть более защищенным.
Комментарии (10)