Первый рубеж — фронтенд и передача данных. Даже перед отправкой на сервер данные могут быть перехвачены или форма подвергнута атаке.
Пример уязвимости: отправка формы по незащищенному HTTP или наличие уязвимостей XSS (межсайтового скриптинга), которые могут украсть данные прямо из браузера.
Меры защиты:
- Обязательное использование HTTPS (TLS) для всего трафика. Это базис.
- Защита от XSS. Экранируйте (escape) весь пользовательский контент перед выводом на страницу. Используйте современные фреймворки (React, Vue, Angular), которые делают это по умолчанию, но не забывайте об опасностях dangerouslySetInnerHTML или v-html.
- Валидация данных на клиенте и сервере. Клиентская валидация — для удобства пользователя, серверная — для безопасности. Никогда не доверяйте данным с фронтенда.
const Joi = require('joi'); // Библиотека для валидации схем
const resumeSchema = Joi.object({
fullName: Joi.string().min(2).max(100).required(),
email: Joi.string().email().required(),
phone: Joi.string().pattern(/^\+?[\d\s\-\(\)]+$/).required(),
// Запрещаем HTML/JS в поле "опыт"
experience: Joi.string().max(5000).disallow('')
});
app.post('/api/resume', async (req, res) => {
const { error, value } = resumeSchema.validate(req.body);
if (error) {
return res.status(400).json({ error: error.details[0].message });
}
// Далее работаем с очищенным `value`
});
Второй и главный рубеж — бэкенд и база данных.
Уязвимость №1: SQL-инъекция. Классика, но до сих пор встречается.
НЕПРАВИЛЬНО (уязвимый код на Python с SQL-конкатенацией):
cursor.execute(f"INSERT INTO resumes (name, phone) VALUES ('{name}', '{phone}')")
ПРАВИЛЬНО: Всегда используйте параметризованные запросы (prepared statements).
# Пример на Python (psycopg2 для PostgreSQL)
cursor.execute(
"INSERT INTO resumes (name, phone) VALUES (%s, %s)",
(name, phone)
)
# Пример на Node.js (библиотека pg)
await client.query(
'INSERT INTO resumes (name, phone) VALUES ($1, $2)',
[name, phone]
);
Уязвимость №2: Небезопасное хранение конфиденциальных данных. Хранение паспортных данных, номеров телефонов или email в открытом виде в БД.
Меры защиты:
- Шифрование. Конфиденциальные поля должны храниться в зашифрованном виде. Используйте сильные алгоритмы (AES-256-GCM) и надежно управляйте ключами шифрования (желательно через специализированные сервисы, например, AWS KMS, или аппаратные модули). Никогда не храните ключи в коде или репозитории.
- Хеширование для данных, которые не нужно восстанавливать. Например, если требуется только проверка уникальности email, можно хранить его хеш (с солью).
- Маскирование при выводе. В интерфейсе рекрутера показывать не полный номер телефона, а, например, "+7 (***) ***-**-12".
const crypto = require('crypto');
const algorithm = 'aes-256-gcm';
const key = crypto.randomBytes(32); // Ключ должен храниться в безопасном месте (env, vault)
const iv = crypto.randomBytes(16);
function encrypt(text) {
const cipher = crypto.createCipheriv(algorithm, key, iv);
let encrypted = cipher.update(text, 'utf8', 'hex');
encrypted += cipher.final('hex');
const authTag = cipher.getAuthTag().toString('hex');
return { encrypted, iv: iv.toString('hex'), authTag };
}
// В БД сохраняем объект `encrypt('+79991234567')`
Уязвимость №3: Неправильные права доступа (Authorization). Рекрутер из одного департамента не должен видеть резюме, загруженные для другого.
Мера защиты: Реализация системы ролевого доступа (RBAC) или атрибутивного доступа (ABAC) на уровне API и БД. Всегда проверяйте права пользователя на операцию.
app.get('/api/resume/:id', authenticate, async (req, res) => {
const resume = await db.getResume(req.params.id);
// Проверка: принадлежит ли резюме отделу текущего пользователя?
if (resume.department_id !== req.user.department_id) {
return res.status(403).json({ error: 'Forbidden' });
}
res.json(resume);
});
Третий рубеж — инфраструктура и файлы.
Резюме часто загружаются в виде файлов (PDF, DOC). Эти файлы должны храниться вне корневой веб-директории, иметь случайные имена и проверяться на наличие малвари. Доступ к ним должен осуществляться через защищенный endpoint бэкенда, который проверяет авторизацию.
Защита — это многослойный процесс. Недостаточно просто поставить HTTPS. Необходим security-first подход на всех этапах: от кода формы до политики хранения резюме в компании (сроки, удаление). Регулярный аудит кода, penetration-тестирование и соблюдение принципа минимальных привилегий (как для пользователей, так и для сервисов) сведут риски к минимуму. Помните, что защита персональных данных — это не только техническая, но и юридическая ответственность по 152-ФЗ.
Комментарии (5)