
Python-приложения становятся мишенью всё чаще
За последние два года количество критических уязвимостей в экосистеме Python выросло на 340%. Разработчики часто сосредотачиваются на функциональности и скорости разработки, забывая о базовых принципах безопасности. В результате на production попадают приложения с открытыми kredentials в коде, неправильной обработкой пользовательского ввода и устаревшими зависимостями. Пора менять подход.
Где кроются основные уязвимости
Проблема номер один: управление зависимостями
Большинство Python-проектов используют от 50 до 500 сторонних библиотек. Каждая из них — потенциальная точка входа для злоумышленников. Представьте: вы установили популярный пакет, который казался безопасным, но через три месяца в нём нашли критическую уязвимость. Если вы не отслеживаете обновления, ваше приложение остаётся уязвимым.
Реальный случай: уязвимость в библиотеке requests (используется в миллионах проектов) позволяла перехватывать HTTPS-соединения при определённых условиях. Разработчики, которые проверяли зависимости автоматически, исправили проблему за часы. Остальные рисковали неделями.
Injection-атаки: классика жанра
SQL-injection, command injection, template injection — методы атак не изменились, но они по-прежнему работают. Когда код выполняет команды на основе неочищенного пользовательского ввода, это приглашение для хакера.
Пример опасного кода:
user_id = request.args.get(‘id’)
query = f”SELECT * FROM users WHERE id = {user_id}”
db.execute(query)
Этот фрагмент позволит злоумышленнику передать вместо ID что-то типа 1; DROP TABLE users;. Результат предсказуем.
Практические инструменты для анализа безопасности
Static Application Security Testing (SAST)
Bandit — инструмент, разработанный специально для Python. Он сканирует исходный код и ищет типичные уязвимости:
- использование опасных функций (eval, exec, pickle)
- hardcoded passwords и API-ключи
- небезопасные разрешения для файлов
- SQL-injection уязвимости
Установка и запуск:
pip install bandit
bandit -r ./src
Safety проверяет зависимости против известной базы уязвимостей. Работает просто:
pip install safety
safety check
Dependency management: автоматизация обновлений
Ручная проверка requirements.txt — подход прошлого века. Современные решения:
- Dependabot (встроен в GitHub) автоматически создаёт pull request’ы для обновлений
- Snyk не только проверяет зависимости, но и предлагает исправления с одним кликом
- pip-audit — лёгкий инструмент, который можно запустить в CI/CD pipeline
Настройка безопасности на уровне приложения
Управление secrets и конфигурацией
Никогда не храните пароли, API-ключи и токены в коде или даже в конфиге рядом с кодом. Используйте:
- Environment variables — самый простой способ
- Python-dotenv для локальной разработки (файл .env никогда не коммитится в репозиторий)
- Vault, AWS Secrets Manager, Azure Key Vault для production
Пример с python-dotenv:
from dotenv import load_dotenv
load_dotenv()
api_key = os.getenv(‘API_KEY’)
Валидация и санитизация входных данных
Любой пользовательский ввод — враг по умолчанию. Применяйте правило:
- Белый список допустимых значений, а не чёрный список запрещённых
- Используйте параметризованные запросы для БД (никогда f-strings для SQL)
- Для веб-приложений используйте ORM (SQLAlchemy, Django ORM) вместо сырых SQL-запросов
Правильный подход с SQLAlchemy:
query = db.session.query(User).filter(User.id == user_id)
Здесь параметр user_id защищен от injection автоматически.
Интеграция безопасности в CI/CD pipeline
Проверка безопасности должна быть частью процесса разработки, а не постфактум:
- Запускайте Bandit и Safety для каждого pull request’а
- Блокируйте merge, если найдены критические уязвимости
- Настройте SAST-сканирование в GitLab CI, GitHub Actions или другом CI-инструменте
- Используйте container scanning, если приложение упаковано в Docker
Пример GitHub Actions workflow:
– name: Run Bandit
run: bandit -r ./src -f json -o bandit-report.json
– name: Check dependencies
run: safety check –json
Чеклист безопасности Python-приложения
Перед деплоем в production проверьте:
- Нет hardcoded credentials и secrets в коде
- Все зависимости актуальны и проверены на уязвимости
- Используются параметризованные запросы к БД
- Все пользовательские данные валидируются и санитизируются
- Включены логирование и мониторинг безопасности
- HTTPS включён и правильно настроен
- Установлены корректные CORS-заголовки
- Настроена аутентификация и авторизация
- Проведено статическое сканирование кода
- Составлены инструкции для incident response
Культура безопасности в команде
Инструменты помогают, но они — не панацея. Необходимо воспитывать culture безопасности среди разработчиков:
- Проводите code review с фокусом на безопасность
- Документируйте и анализируйте найденные уязвимости
- Обучайте команду современным векторам атак
- Поощряйте использование паттернов безопасного кода
Заключение
Безопасность Python-приложений — это не одноразовый проект, а постоянный процесс. Наличие правильных инструментов, автоматизированных проверок и культуры безопасности в команде снижает риск взлома на 80%. Начните с малого: подключите Bandit и Safety к своему репозиторию, обновите зависимости и пересмотрите управление secrets. Это займёт несколько часов, но защитит ваше приложение от подавляющего большинства распространённых атак. Python заслуживает того, чтобы быть безопасным.
morfix.ru