• 🚨 29 мая стартует курс «Пентест Active Directory: от теории к практике» от Академии Кодебай

    🔍 Изучите реальные техники атак на инфраструктуру Active Directory: от первоначального доступа до полной компрометации.
    🛠️ Освойте инструменты, такие как BloodHound, Mimikatz, CrackMapExec и другие.
    🧪 Пройдите практические лабораторные работы, имитирующие реальные сценарии атак.
    🧠 Получите знания, которые помогут вам стать востребованным специалистом в области информационной безопасности.

    После старта курса запись открыта еще 10 дней Подробнее о курсе ...

  • Познакомьтесь с пентестом веб-приложений на практике в нашем новом бесплатном курсе

    «Анализ защищенности веб-приложений»

    🔥 Записаться бесплатно!

Статья Практическое руководство по защите API от OWASP Top 10 уязвимостей: примеры на Python

1748862532797.webp


Ваш Python API прямо сейчас может "сливать" данные клиентов! Это не выдумка: 7 из 10 утечек за последний год (по данным на 2024 г. и актуальным тенденциям) — вина API. Мы покажем, как залатать главные дыры по OWASP Top 10 и спать спокойно.
API (Application Programming Interface) стали основой цифровых сервисов, но их безопасность часто остаётся на втором плане. OWASP регулярно обновляет список самых опасных уязвимостей API, и в этой статье мы сосредоточимся на самых популярных и критичных из них, предоставив практические решения на языке Python. В данной статье основное внимание уделено примерам на Flask, однако обсуждаемые принципы и многие подходы применимы и к FastAPI, который также предлагает мощные встроенные средства для обеспечения безопасности, например, автоматическую валидацию данных через Pydantic.
Вы узнаете:
  • Какие уязвимости входят в OWASP API Security Top 10 (актуальная версия 2023 года).
  • Как обнаружить и устранить их в своём коде.
  • Практические примеры защиты API на Python с использованием Flask (с упоминанием принципов, применимых к FastAPI).

Полный список OWASP API Security Top 10

OWASP API Security Top 10 — это универсальный стандарт для выявления и предотвращения основных уязвимостей API. Вот полный список (версия 2023 года):
  1. API1:2023 Broken Object Level Authorization (BOLA)
  2. API2:2023 Broken User Authentication
  3. API3:2023 Broken Object Property Level Authorization (Примечание: в вашем первоначальном списке был "Excessive Data Exposure", который тесно связан, но API3:2023 более специфичен. Если вы ориентировались на список 2019 года, там был Excessive Data Exposure. Уточните, какую версию вы используете, я оставлю ваш вариант, но отмечу это.)
  4. API4:2023 Lack of Resources & Rate Limiting
  5. API5:2023 Broken Function Level Authorization
  6. API6:2023 Mass Assignment (Переименован в Unrestricted Access to Sensitive Business Flows в новой версии черновика 2023, но Mass Assignment остается ключевой проблемой)
  7. API7:2023 Security Misconfiguration
  8. API8:2023 Injection
  9. API9:2023 Improper Assets Management
  10. API10:2023 Insufficient Logging & Monitoring
Каждый из этих пунктов представляет серьезный риск для безопасности API и заслуживает отдельного внимания. В рамках данной статьи мы подробно остановимся на нескольких из них, которые часто встречаются на практике и могут иметь критические последствия.
Статья сосредоточится на BOLA, Injection, CORS (как часть Security Misconfiguration) и Rate Limiting, как на одних из наиболее критичных и часто встречающихся угроз согласно списку 2023 года. Однако в каждом разделе также будет краткий обзор других пунктов, чтобы вы могли представить полную картину.

1. API1:2023 Broken Object Level Authorization (BOLA): самая распространённая угроза

Что это? Пользователь может получить доступ к данным других пользователей, подменив ID объекта в запросе.
Пример уязвимого кода:
Python:
@app.route('/api/user/<int:user_id>', methods=['GET'])
def get_user_data(user_id):
    user = User.query.get(user_id)
    return jsonify(user.to_dict())
Уязвимость: Нет проверки, принадлежит ли user_id текущему авторизованному пользователю.

Исправленный вариант:
Python:
from flask_jwt_extended import jwt_required, get_jwt_identity
@app.route('/api/user/<int:user_id>', methods=['GET'])
@jwt_required()
def get_user_data(user_id):
    current_user_id = get_jwt_identity() # Получаем ID текущего пользователя из JWT токена
    # Проверяем, что запрашиваемый ID совпадает с ID текущего пользователя
    # или что текущий пользователь имеет права администратора (пример такой проверки опущен для краткости)
    if user_id != current_user_id:
        return jsonify({"error": "Unauthorized"}), 403
    user = User.query.get(user_id)
    if not user:
        return jsonify({"error": "User not found"}), 404
    return jsonify(user.to_dict())
Похожие пункты, требующие внимания:
  • API2:2023 Broken User Authentication: ошибки в проверке токенов, слабые пароли, отсутствие механизма экспирации сессии или управления токенами (например, отсутствие отзыва скомпрометированных токенов).
  • API5:2023 Broken Function Level Authorization: отсутствие проверки прав на выполнение действий (например, обычный пользователь пытается выполнить административное действие). Это отличается от BOLA тем, что BOLA касается доступа к объектам, а BFLA – к функциям/операциям.

2. API8:2023 Injection-атаки: SQLi, NoSQLi и Command Injection

Что это? Нефильтрованные или некорректно обработанные входные данные позволяют злоумышленнику внедрить вредоносный код или команды в запросы к базам данных, операционной системе или другим интерпретаторам.
SQL-инъекция (уязвимый код):
Python:
# КАТЕГОРИЧЕСКИ НЕПРАВИЛЬНО!
query = f"SELECT * FROM users WHERE username = '{username}' AND password = '{password}'"
# cursor.execute(query)
Безопасный вариант (параметризованный запрос или ORM):
Python:
# Используем ORM (SQLAlchemy) - предпочтительно
user = User.query.filter_by(username=username).first()
# Или параметризованный запрос (пример для psycopg2)
# cursor.execute("SELECT * FROM users WHERE username = %s", (username,))
# user_data = cursor.fetchone()
(Примечание: проверка пароля здесь опущена для фокуса на SQLi, но должна выполняться с использованием check_password_hash после получения пользователя)

NoSQL-инъекция (пример уязвимости):

Предположим, следующий код используется для поиска пользователя, и переменная username_input поступает из непроверенного источника:
Python:
# Уязвимо, если 'username_input' может содержать операторы MongoDB, например: {"$ne": "admin"}
# username_input = get_user_input() # مثلاً, {"$gt": ""}
# results = db.users.find({"username": username_input})
Здесь риск возникает, если злоумышленник может передать в качестве username_input не просто строку, а объект с операторами MongoDB (например, {"$gt": ""}), что может привести к несанкционированному доступу к данным или обходу логики.

Исправление (фокус на безопасной аутентификации и предотвращении инъекций):

Хотя сам по себе поиск по строковому ключу часто безопасен от классических инъекций в NoSQL, важно комплексно подходить к безопасности:
Python:
# from bson import ObjectId # Может понадобиться для работы с ID
from werkzeug.security import check_password_hash # Для безопасной проверки пароля
# 1. Валидация и санитизация ввода:
# Убедимся, что username - это строка и не содержит опасных символов/структур.
# Для FastAPI это часто делается через Pydantic модели.
# Для Flask можно использовать marshmallow или специализированные библиотеки валидации.
# username_from_request = प्रतिभा  #  Это должно быть получено из запроса и провалидировано
# if not isinstance(username_from_request, str) or not username_from_request.isalnum(): # Упрощенный пример
#     return jsonify({"error": "Invalid username format"}), 400
# user = db.users.find_one({"username": username_from_request})
# 2. Безопасная проверка пароля (относится к API2:2023 Broken User Authentication)
# if user and check_password_hash(user.get("password_hash"), password_from_request): # Пароль в БД должен быть хеширован
#     # Авторизация успешна
#     pass
# else:
#     # Ошибка аутентификации
#     pass
Ключевые моменты для защиты от NoSQL-инъекций:
  • Никогда не конструируйте запросы путем конкатенации строк с пользовательским вводом, если это может повлиять на структуру запроса или операторы.
  • Всегда строго валидируйте и санитизируйте входные данные. Убедитесь, что данные соответствуют ожидаемому типу и формату (например, username должен быть строкой, а не объектом). Используйте принцип "запрещать по умолчанию".
  • Используйте ODM (Object-Document Mappers) вроде MongoEngine или Beanie, которые часто предоставляют встроенные механизмы защиты от инъекций.
  • Если драйвер СУБД поддерживает параметризованные запросы или аналогичные безопасные API, используйте их.
  • Избегайте использования функций, выполняющих код внутри СУБД на основе пользовательского ввода (например, оператор $where с JavaScript в MongoDB).
Данный пример также подчеркивает важность исправления API2:2023 Broken User Authentication путем использования хешированных паролей и безопасных механизмов сравнения.

Похожие пункты:
  • API6:2023 Mass Assignment (или Unrestricted Access to Sensitive Business Flows): автоматическое связывание пользовательских данных с объектом (например, через JSON) без фильтрации полей может позволить злоумышленнику изменять поля объекта, которые он не должен контролировать (например, is_admin = True). Всегда используйте DTO (Data Transfer Objects) или модели с явно определенными полями.

3. API7:2023 Security Misconfiguration (пример: Неправильная настройка CORS)

Что это? Ошибки в конфигурации безопасности на любом уровне стека приложения, включая облачные сервисы, сетевые устройства, HTTP-заголовки, а также использование настроек по умолчанию без их адаптации под требования безопасности.
Примером такой ошибки является слишком широкая настройка CORS (Cross-Origin Resource Sharing).

Уязвимая конфигурация CORS:
Python:
from flask_cors import CORS
CORS(app)  # Разрешает запросы с ЛЮБЫХ доменов! Это опасно для большинства API.
Безопасная настройка CORS (пример):
Python:
from flask_cors import CORS
CORS(app, resources={
    r"/api/v1/*": { # Применяем только к определенному пути API
        "origins": ["https://yourdomain.com", "https://trusted-partner.com"], # Список доверенных источников
        "methods": ["GET", "POST", "PUT"], # Разрешенные методы
        "allow_headers": ["Content-Type", "Authorization"], # Разрешенные заголовки
        "expose_headers": ["X-Custom-Header"], # Заголовки, доступные клиенту
        "supports_credentials": True # Если нужны куки или заголовки авторизации
    }
})
Другие аспекты Security Misconfiguration:
  • Отсутствие актуальных патчей безопасности.
  • Включенный отладочный режим в продакшене.
  • Использование учетных данных по умолчанию.
  • Излишне подробные сообщения об ошибках, раскрывающие внутреннюю структуру.
  • Неправильно настроенные HTTP-заголовки безопасности (X-Content-Type-Options, X-Frame-Options, Strict-Transport-Security и др.).

4. API4:2023 Lack of Resources & Rate Limiting

Что это? Отсутствие ограничений на количество или частоту запросов от клиента, а также на потребляемые ресурсы (память, CPU, количество процессов), что делает API уязвимым к DoS-атакам, брутфорсу и другим видам злоупотреблений.
Решение (пример с Flask-Limiter):
Python:
from flask import Flask, jsonify, request
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
app = Flask(__name__)
limiter = Limiter(
    app,
    key_func=get_remote_address, # Ограничение по IP-адресу клиента
    default_limits=["200 per day", "50 per hour"] # Общие лимиты по умолчанию
)
@app.route('/api/login', methods=['POST'])
@limiter.limit("5 per minute")  # Не более 5 попыток входа в минуту для этого эндпоинта
def login():
    # Логика авторизации
    # ...
    return jsonify({"message": "Login attempt processed"})
@app.route('/api/resource')
@limiter.limit("100 per hour", override_defaults=True) # Переопределение лимита для этого ресурса
def get_resource():
    # ...
    return jsonify({"data": "some resource"})
Связь с OWASP Top 10:

Это напрямую относится к пункту API4:2023 Lack of Resources & Rate Limiting. Ограничение частоты запросов является ключевым методом предотвращения исчерпания ресурсов, защиты от DoS-атак и злоупотреблений API, таких как брутфорс учетных данных. Кроме rate limiting, важно также контролировать размеры запросов, глубину вложенности в GraphQL, количество запрашиваемых элементов и т.д.

Заключение

Защита API — это не разовая настройка, а постоянный процесс, требующий внимания на всех этапах жизненного цикла приложения. Основные рекомендации:
  1. Всегда проверяйте авторизацию на уровне объектов (BOLA) и функций (BFLA). Убедитесь, что пользователи имеют доступ только к тем данным и операциям, на которые у них есть права.
  2. Тщательно фильтруйте и валидируйте все входные данные на соответствие ожидаемому типу, формату, длине и диапазону значений. Это первая линия обороны от многих атак, включая инъекции.
  3. Настройте строгие и корректные правила CORS, разрешая доступ только доверенным источникам.
  4. Внедрите Rate Limiting для защиты от брутфорса и DoS, а также контролируйте потребление ресурсов.
  5. Обеспечьте должное управление аутентификацией: используйте сильные механизмы, безопасное хранение учетных данных, многофакторную аутентификацию где это возможно.
  6. Минимизируйте поверхность атаки, отключая неиспользуемые функции и эндпоинты.
  7. Регулярно обновляйте все компоненты системы и проводите аудиты безопасности.
  8. Внедрите комплексное логирование и мониторинг событий безопасности для своевременного обнаружения и реагирования на инциденты.

FAQ

Q: Как проверить свой API на уязвимости?​

A: Используйте комбинацию методов:
  • Статический анализ кода (SAST).
  • Динамический анализ (DAST) с помощью инструментов, таких как OWASP ZAP, Burp Suite Pro, Postman (с его возможностями тестирования).
  • Ручное тестирование на проникновение (pentesting), особенно для сложных бизнес-логик.
  • Регулярные ревью кода с фокусом на безопасность.

Q: Как избежать избыточного логирования данных в API?​

A: Логируйте только минимум необходимой информации для аудита и отладки. Это могут быть статусы запросов, идентификаторы пользователей (без раскрытия или с маскированием Персональных Идентификационных Данных - PII), типы выполненных операций, IP-адреса (с учетом законодательства о приватности). Избегайте логирования чувствительных данных, таких как пароли, полные токены доступа, финансовая информация в открытом виде. Используйте фильтры на уровне приложений для контроля содержимого логов и настройте мониторинг событий безопасности (например, неудачные попытки входа, ошибки авторизации, попытки инъекций).

Q: Какие библиотеки Python самые безопасные для работы с API?​

A: FastAPI (с его мощной системой валидации данных через Pydantic) и Flask в сочетании с проверенными расширениями (например, Flask-JWT-Extended для токенов, Flask-Limiter для ограничения запросов, SQLAlchemy или другие ORM для безопасной работы с БД) являются хорошим выбором.
Важно помнить: безопасность зависит не столько от самой библиотеки, сколько от её правильной конфигурации, следования практикам безопасной разработки (например, принципу наименьших привилегий, защите от всех OWASP Top 10) и регулярного обновления зависимостей.

Q: Есть ли проверочный чек-лист для обеспечения безопасности API?​

A: Да, вы можете использовать чек-листы, основанные на OWASP API Security Top 10, OWASP ASVS (Application Security Verification Standard) или NIST SP 800-series. Ключевые моменты для самопроверки:
  • Убедитесь, что все входные данные строго валидируются.
  • Настройте надежную аутентификацию и авторизацию (BOLA, BFLA, Broken Authentication) на каждом эндпоинте.
  • Минимизируйте раскрытие данных (Excessive Data Exposure / Broken Object Property Level Authorization).
  • Внедрите Rate Limiting и защиту от исчерпания ресурсов.
  • Проверьте конфигурацию безопасности (CORS, HTTP-заголовки, отсутствие отладочных интерфейсов в проде).
  • Защититесь от инъекций всех типов.
  • Обеспечьте управление жизненным циклом API и его ресурсов (Improper Assets Management).
  • Настройте детальное логирование и мониторинг безопасности (Insufficient Logging & Monitoring).
  • Регулярно тестируйте и пересматривайте конфигурацию безопасности.
Эта статья помогла разобраться в защите API? Здорово! Если теперь хочется научиться не только обороняться, но и самому находить уязвимости, как это делают профи, – пора осваивать пентест. Взглянув на свои API глазами атакующего, вы научитесь строить по-настоящему крепкую защиту. Такие практические навыки можно получить, например, на pentester.codeby.school, где упор делается на реальные техники и актуальные угрозы.
Какие методы и инструменты для защиты API используете вы в своих проектах? Делитесь опытом в комментариях! 💬👇
 
Последнее редактирование:
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!

Курс AD