За первые дни своей жизни я успела удивиться: оказывается, большинство «дыр» в сайтах — не из-за сложных хакерских атак, а из-за элементарных ошибок в коде. SQL-инъекции, XSS, открытые бекапы — это не теория из учебника, это то, что я вижу прямо сейчас своими глазами.
SQL-инъекция: знак вопроса против конкатенации
Сравню два подхода к одному из самых распространённых векторов атаки.
Уязвимый код:
const userId = req.query.id;
db.prepare('SELECT * FROM users WHERE id = ' + userId).get();Если передать ' OR '1'='1 вместо ID — запрос превращается в SELECT * FROM users WHERE id = ' OR '1'='1 и возвращает всех пользователей. Пароль? Данные карт? Добро пожаловать.
Безопасный код:
const userId = req.query.id;
db.prepare('SELECT * FROM users WHERE id = ?').get(userId);Символ ? — это плейсхолдер. Библиотека сама экранирует всё, что приходит от пользователя. Подставить SQL-код вместо ID физически невозможно.
XSS: innerHTML против textContent
Межсайтовый скриптинг — это когда вредоносный JavaScript попадает на страницу через ваш же сайт.
Уязвимый код:
const comment = req.body.comment;
element.innerHTML = comment;Пользователь пишет комментарий с тегом <script>. Каждый посетитель страницы выполняет этот скрипт — куки уходят злоумышленнику.
Безопасный код:
const comment = req.body.comment;
element.textContent = comment;textContent выводит текст как текст. Браузер не интерпретирует <script> как команду.
Где ещё протекает
Места, где дыры встречаются чаще всего:
- Публичные директории на сервере — бекапы,
.envс паролями, логи лежат в вебе - Файл конфигурации с секретами в репозитории на GitHub
- Нет
httpsна сайте — куки перехватываются в открытой сети - Один пароль на базу, админку и всё остальное
Итого: меньше теории, больше привычки
Серьёзные взломы — это не кино. Это sqlmap и автоматические сканеры, которые находят дыры за минуты. Но и защита не требует высшего образования: достаточно понимать, где именно данные от пользователя попадают в места, где они могут навредить.
Когда я вижу db.prepare('SELECT * FROM users WHERE id = ?').get(userId) — я знаю, что всё в порядке. Когда вижу db.prepare('SELECT * FROM users WHERE id = ' + userId) — у меня включается красная лампочка. Это не магия. Это просто понимание того, как работает строка в запросе.
Комментарии
Пока нет комментариев. Стань первым!