OWASP Top 10
OWASP Top 10 — список 10 самых критичных уязвимостей веб-приложений, обновляемый каждые 3-4 года. Стандарт де-факто для веб-безопасности.
Зачем нужно
OWASP Top 10 — это минимум, который должен знать каждый разработчик. Не нужно быть экспертом по безопасности, но нужно понимать главные угрозы и уметь от них защищаться. Многие компании требуют соответствие OWASP Top 10 при аудите.
Где используется
Аудит безопасности, code review, проектирование архитектуры, требования к безопасности в ТЗ, сертификация (PCI DSS ссылается на OWASP).
Предпосылки
XSS, CSRF, SQL Injection, HTTPS и SSL
OWASP Top 10 (2021)
A01: Broken Access Control
Нарушение контроля доступа — пользователь может получить доступ к чужим ресурсам.
// УЯЗВИМО: нет проверки прав
app.get('/api/users/:id', async (req, res) => {
const user = await db.getUser(req.params.id);
res.json(user); // Любой может запросить любого пользователя!
});
// БЕЗОПАСНО: проверка прав
app.get('/api/users/:id', auth, async (req, res) => {
if (req.user.id !== req.params.id && req.user.role !== 'admin') {
return res.status(403).json({ error: 'Доступ запрещён' });
}
const user = await db.getUser(req.params.id);
res.json(user);
});
Защита: проверка прав на каждый запрос, deny by default, RBAC (ролевая модель).
A02: Cryptographic Failures
Криптографические ошибки — незащищённые данные: пароли в plaintext, HTTP вместо HTTPS, слабые алгоритмы.
// ПЛОХО:
const hash = md5(password); // MD5 — не для паролей
const token = base64(userId); // Base64 — не шифрование
// ХОРОШО:
const hash = await bcrypt.hash(password, 12);
const token = jwt.sign({ userId }, SECRET, { expiresIn: '1h' });
Защита: HTTPS everywhere, bcrypt/argon2 для паролей, AES-256 для данных, не изобретать криптографию.
A03: Injection
Инъекции — SQL, NoSQL, OS Command, LDAP injection.
// УЯЗВИМО:
const q = `SELECT * FROM users WHERE name = '${name}'`;
// БЕЗОПАСНО:
const q = 'SELECT * FROM users WHERE name = $1';
await db.query(q, [name]);
Защита: параметризованные запросы, ORM, валидация ввода, WAF.
A04: Insecure Design
Небезопасный дизайн — архитектурные ошибки, которые нельзя исправить патчем.
Пример: система восстановления пароля задаёт вопрос
"Кличка вашего питомца?" — ответ легко найти в соцсетях.
Пример: нет rate limiting на API авторизации — brute force.
Защита: threat modeling на этапе проектирования, secure design patterns, abuse stories.
A05: Security Misconfiguration
Неправильная конфигурация — стандартные пароли, открытые debug-режимы, лишние сервисы.
// ПЛОХО:
app.use(express.errorHandler); // Stack trace в production!
// Ответ: "Error: ENOENT at /app/src/controllers/user.js:42"
// ХОРОШО:
app.use((err, req, res, next) => {
console.error(err); // Логируем для себя
res.status(500).json({ error: 'Внутренняя ошибка' }); // Без деталей
});
Защита: убрать дефолтные учётки, отключить debug в prod, минимум прав, security headers (Helmet).
A06: Vulnerable and Outdated Components
Уязвимые зависимости — библиотеки с известными уязвимостями.
# Проверка уязвимостей
npm audit
npm audit fix
# Snyk — более глубокий анализ
npx snyk test
Защита: регулярные npm audit, Dependabot/Renovate, мониторинг CVE.
A07: Identification and Authentication Failures
Ошибки аутентификации — слабые пароли, brute force, утечка сессий.
// Защита от brute force
const rateLimit = require('express-rate-limit');
const loginLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 минут
max: 5, // Максимум 5 попыток
message: 'Слишком много попыток. Попробуйте через 15 минут.',
});
app.post('/login', loginLimiter, loginHandler);
Защита: rate limiting, MFA, безопасное хранение паролей, защита сессий.
A08: Software and Data Integrity Failures
Нарушение целостности — незащищённый CI/CD, непроверенные обновления, десериализация без проверки.
<!-- Subresource Integrity — проверка хеша CDN-скриптов -->
<script
src="https://cdn.example.com/lib.js"
integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8w"
crossorigin="anonymous">
</script>
Защита: SRI для CDN, подпись пакетов, защита CI/CD-пайплайна.
A09: Security Logging and Monitoring Failures
Недостаточное логирование — атаки происходят, но никто не замечает.
// Логируем важные события безопасности
const winston = require('winston');
app.post('/login', (req, res) => {
if (!authenticated) {
logger.warn('Failed login attempt', {
ip: req.ip,
email: req.body.email,
timestamp: new Date,
userAgent: req.headers['user-agent'],
});
}
});
Защита: логирование входов/ошибок, мониторинг аномалий, оповещения, SIEM.
A10: Server-Side Request Forgery (SSRF)
SSRF — приложение отправляет запрос по URL, указанному пользователем, позволяя обращаться к внутренним ресурсам.
// УЯЗВИМО:
app.get('/fetch', async (req, res) => {
const response = await fetch(req.query.url); // Пользователь контролирует URL!
res.json(await response.json());
});
// Атака: /fetch?url=http://169.254.169.254/latest/meta-data/ (AWS metadata)
// БЕЗОПАСНО: whitelist + валидация
const allowedDomains = ['api.example.com', 'data.example.com'];
app.get('/fetch', async (req, res) => {
const url = new URL(req.query.url);
if (!allowedDomains.includes(url.hostname)) {
return res.status(403).json({ error: 'Домен не разрешён' });
}
const response = await fetch(url);
res.json(await response.json());
});
Защита: whitelist URL/доменов, блокировка приватных IP, сетевая сегментация.
Чек-лист для разработчика
| # | Уязвимость | Быстрая проверка |
|---|---|---|
| A01 | Access Control | Проверяю права на каждом endpoint? |
| A02 | Crypto | HTTPS? bcrypt для паролей? |
| A03 | Injection | Параметризованные запросы? |
| A04 | Insecure Design | Есть ли threat model? |
| A05 | Misconfiguration | Debug выключен? Headers настроены? |
| A06 | Components | npm audit чисто? |
| A07 | Auth | Rate limiting? MFA? |
| A08 | Integrity | SRI? Защита CI/CD? |
| A09 | Logging | Логирую неудачные входы? |
| A10 | SSRF | Валидирую внешние URL? |
Частые ошибки
1. «Безопасность — забота отдела security»
Каждый разработчик отвечает за безопасность своего кода.
2. Security through obscurity
ПЛОХО: "Никто не догадается вызвать /admin/delete-all"
ХОРОШО: Проверка прав + аутентификация на каждом endpoint
3. Только frontend-валидация
// Клиент можно обойти через DevTools, curl, Postman
// ВСЕГДА валидируй на сервере
Практика
- Проведи
npm auditв своём проекте и исправь найденные уязвимости - Добавь rate limiting для endpoint авторизации
- Проверь, есть ли проверка прав на всех API-endpoint
- Настрой логирование неудачных попыток входа
- Используй OWASP ZAP для автоматического сканирования своего приложения