-
Notifications
You must be signed in to change notification settings - Fork 27
[2024 21 11] Teletext. PHP Security
Alexander Makarov Всем привет. Сегодня я расскажу про безопасность. Я не эксперт в плане нападения и защиты, но кое-что знаю потому что разрабатывал безопасные приложения, помогал их сертифицировать, отсматривал чужие проекты на предмет безопасности.
Что я могу сказать... практически везде есть похожие ошибки.
Alexander Makarov Я Александр Макаров. Соавтор и руководитель открытого PHP-фреймворка Yii framework, CTO Twindo.ai, член программного комитета конференции Highload++ и руководитель программного комитета PHP Russia. Много лет писал и пишу код. https://imgur.com/VWpZIdR
Alexander Makarov ⛔️ Одна из главных идей — данным доверять нельзя. Принцип тут:
- Фильтруй вход.
- Экранируй выход.
🚪 Входы:
- Формы
- Файлы
- Заголовки HTTP ($_SERVER['HTTP_X_FORWARDED_FOR'] и т.д.)
- User agent
- ...
🚪 Выходы:
- Браузер
- Консоль
- База данных
- ...
❓В чём вообще проблема?
- Плохо фильтруем
- Неправильно экранируем
Сергей Предводителев Базу данных можно считать входом?
enotit (пока не понимаю как проходит встреча, но мне интересно поучаствовать)
А у пользователя прямой доступ к ней?
Дмитрий Тарасов Какие конкретные подходы или инструменты вы рекомендуете для эффективного экранирования данных на выходах, особенно для работы с браузером и базами данных?
Alexander Makarov Фильтровать = убедиться, что данные верны.
Входные данные не валидны пока не доказано обратное.
Предпочитайте белые списки где это возможно.
Используйте filter_var:
$email = filter_var($email, FILTER_VALIDATE_EMAIL);
if ($email === false) {
// email не торт...
}
// всё OK
используйте надёжные библиотеки и фреймворки
Николай Лукин А скоро выйдет Yii3?
Alexander Makarov Да.
Alexander Makarov Экранировать — сделать так, чтобы спецсимволы вели себя как нормальные символы.
Обычно префиксированием других спецсимволов.
На каждый выход свои правила экранирования.
Дмитрий Тарасов Какие уязвимости чаще всего остаются незакрытыми, даже если используются фреймворки и такие подходы, как filter_var? Есть ли примеры, где стандартные фильтры или экранирование могут быть недостаточны?
Alexander Makarov Довольно скоро :)
Иван Кацаренко Александр, пламенный привет от участника летнего php-митапа в Воронеже. По Yii3 был классный доклад 😊
Alexander Makarov Теперь к популярным угрозам. Начнём с XSS.
На страницу вставляется скрипт, который запускается в браузере пользователя.
Встречалось в большинстве проектов, с которыми я работал.
...
<div>
<?= $_GET['query'] ?>
</div>
...
https://imgur.com/cMI2vS8
николай catman классика 🚬
Alexander Makarov ❓Ну "hello!" и ОК, да?
Вместо alert-а могут:
- Сделать что-то от имени пользователя...
- Одолжить денег у его друзей
- Нарепостить экстремистских комментов
- Утащить денег со счёта
- ...
XSS в админке не менее опасен...
Alexander Makarov Две главных разновидности
- Первого порядка - выполняется немедленно
- Второго порядка - пишется в базу, выполняется потом
Alexander Makarov ✅ Решение
Экранируй!
HTML → нужен только текст:
htmlspecialchars($content, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
HTML → нужна разметка → HTMLPurifier (http://htmlpurifier.org/)
$config = HTMLPurifier_Config::createDefault();
$purifier = new HTMLPurifier($config);
$clean_html = $purifier->purify($dirty_html);
Кстати, разработчики Chromium выкинули XSS-фильтр... (https://www.chromestatus.com/feature/5021976655560704)
Николай Лукин Это вроде Reflected и Stored.
Alexander Makarov Да, ещё и так зовётся.
Дмитрий Тарасов Достаточно ли использовать htmlspecialchars, для защиты от или есть случаи, где этого недостаточно?
николай catman Как находить уязвимости в готовых приложениях? 🤔Часто видел на готовых движках такое, например загружали обсфуцированный скрит с шеллом. Часто вордпресс взламывают.
Alexander Makarov Если контекст верный, то да. То есть если вы выводите HTML.
Alexander Makarov burp suite, https://gist.github.com/kurobeats/9a613c9ab68914312cbb415134795b45, https://cheatsheetseries.owasp.org/cheatsheets/XSS_Filter_Evasion_Cheat_Sheet.html
Alexander Makarov Но вот с вордпресс беда, так что лучше его в докере гонять.
Николай Лукин Тоже хотел этот cheat sheet скинуть) Опередили.
Николай Лукин Могу ещё OWASP ZAP посоветовать, он по проще, но тоже хорошо задачу выполняет + сразу есть ссылки на объяснение уязвимости.
Alexander Makarov А вот если выводите, например, CSS, то уже нет.
Alexander Makarov CSRF
Сторонний сайт может отправить формы на ваш сайт от имени пользователя.
✅ Решение
Использовать токены CSRF, использовать TLS/SSL.
CSRF-токены
- В момент отображения к форме добавляется уникальный случайный токен.
- Тот же токен пишется в хранилище (обычно в сессию).
- После отсылки формы, токены сравниваются.
- Политика действует на XMLHTTPRequest
- Она не запрещает запросы, а предотвращает получение результата
<img src="/logout" />
Использование $_REQUEST - то же самое.
Alexander Makarov История с логаутом — это был хабр.
Alexander Makarov SQL инъекции
Выполнение произвольного SQL в БД проекта.
$email = $_POST['email'];
query("SELECT *
FROM user
WHERE email = '$email';");
' OR 1
UNION SELECT 1,'<!--?php eval($_GET[1]) ?-->',3,4,5 INTO OUTFILE '1.php' --%20
UNION SELECT 1,LOAD_FILE('config.php'),3,4,5 --%20
Alexander Makarov ✅ Решение
Экранируйте запросы. Но делайте это правильно! Ручное экранирование не пойдёт!
addslashes()
mysql_escape_string()
mysql_real_escape_string()
Потому что:
- Можно его забыть
- Контекст может быть не верен (значения, таблицы, столбцы)
- Может быть не полным
Используйте prepared statements. Есть и в PDO и нативных драйверах. Для PDO:
$stmt = $db->prepare("SELECT * FROM user WHERE email = :email");
$stmt->bindValue(':email', $email);
$user = $stmt->fetch();
Имена таблиц и столбцов — белый список:
$allowedTables = ['user_comments', 'post_comments'];
if (!in_array($table), $allowedTables, true) {
return false;
}
// делаем запрос
Alexander Makarov Вообще белые списки — нашё всё.
Alexander Makarov Отсутствие валидации загрузок
Возможность загрузить и запустить код.
- Валидируйте mime
- Пересохраняйте изображения
enotit А если привилегии по пользователям? Как будто ровно одинаковое человеко-часы. Но привилегии как будто бы масштабируются лучше. Или имеется ввиду на действие белые списки.. Немного не понял на что список вешаем.
Alexander Makarov Инъекция кода. У вас такого нет, верно?
eval($_GET['query']);
Запускайте PHP с минимально возможными правами. А лучше ещё и в контейнере.
Alexander Makarov На значения. То есть если мы понимаем, какие значения допустимы — просто их перечисляем и всё.
Alexander Makarov Не пытаемся придумать валидацию.
Дмитрий Тарасов А что делать, если нужно подставить в запрос имя таблицы или столбца? Prepared statements ведь тут не помогут?
Alexander Makarov Небезопасные include. Такого у вас тоже нет, да?
require $_GET['type'] . '.php';
Надо — белый список!
Alexander Makarov И eval нафиг :)
Alexander Makarov Белые списки.
enotit Это как?
Николай Лукин И exec тоже!
Alexander Makarov Ну, от юзера в linux, у которого минимальные права только на то, что нужно.
Alexander Makarov 🥰 Clickjacking
Обманом заставить пользователя кликнуть на что-то на стороннем сайте.
iframe + opactity: 0
Решение — запретить запихивать сайт в фреймы через RFC 7034 (https://datatracker.ietf.org/doc/html/rfc7034):
header('X-Frame-Options: DENY');
// или
header('X-Frame-Options: SAMEORIGIN');
или через JavaScript:
if (window.top !== window.self) {
document.write = "";
window.top.location = window.self.location;
setTimeout(function () {
document.body.innerHTML = '';
}, 1);
window.self.onload = function (evt) {
document.body.innerHTML = '';
};
}
https://imgur.com/7NnKw5d
enotit а, я думал позапрещать в конфигах, что то на уровне eval
Alexander Makarov Это вообще не про PHP, но из любимого. Там твиттер нахлобучили.
Marat для fpm контейнера я обычно блокирую опасные функции disable_functions = passthru,shell_exec,system,show_source,eval
Alexander Makarov Да, можно и так. Особенно если код не ваш.
Alexander Makarov Пароли
👹Зло может угадать ваш пароль.
- Перебором
- Атакой по словарю
- Атакой на основе времени ответа
✅ Решение: ограничить попытки
- 10 попыток с IP в минуту более чем достаточно
- CAPTCHA
🤔 Всё ещё проблема?
- Легко сменить IP
- БД иногда утекают...
Николай Лукин А достаточно ли sha3?
Alexander Makarov Это хеш. Нет.
николай catman некоторые расширения браузеров впхивают всякое-разное, а это ведь может их сломать?
Alexander Makarov Да.
Alexander Makarov Расширения — потенциально опасная фигня.
Alexander Makarov Хэши предназначены для быстрого вычисления
Полный перебор пароля из 8 символов, SHA-256 занимает...
3.5 дня на одной GPU 2011 года.
На крутой GPU 2015 года это будет уже 20 часов.
8x Nvidia GTX 1080 — 2.5 часа.
На 4090 — 3 часа.
- md5, sha1, sha256, sha512
- PBKDF2
николай catman а соль нужна? Как ее правильно хранить? Мб есть какой-то алгоритм? Или достаточно просто применить функцию хеширования на строку пароля?
Alexander Makarov Это я в гостях.
Дмитрий Тарасов Каким способом лучше всего хэшировать пароли, чтобы они были максимально защищены?
Alexander Makarov Есть. Терпение ;)
Marat password_hash() катит?
Alexander Makarov Смотря с какими параметрами.
Marat дефолтный кажись bcrypt и соль не забывать)
Alexander Makarov 4090 вчера гонял-замерял, кстати. Зверюга!
Alexander Makarov Смотря в какой версии. Соль оно уже генерит. Своя не нужна.
enotit Там вроде несколько лет висит алгоритм дешифровки
николай catman реквестирую следующий телетекст про нейросети на php
Alexander Makarov Используйте как минимум bcrypt
- Изначально сделан не быстрым.
- Заставляет работать как CPU, так и GPU.
- Плохо считается на GPU (требует много доступа к памяти, что портит параллелизм).
Cost и сложность пароля важны.
Итерации key derivation function = 2^cost
12+ - безопасное значение. Yii2 использует 13. https://imgur.com/jEhFQaE
николай catman А уязвимости библиотек и через композер (зависимости) в целом - будут рассмотрены?
Alexander Makarov 🧮 Немного посчитаем
Cost = 13 → ~882 хэшей в сек. на 4090 за ~1500$
882 * 60 * 60 * 24 = 76204800 хэшей в день
6 символьный пароль, буквы в нижнем регистре = 308915776 комбинаций
308915776 / 76204800 = 4 дня для перебора одного пароля на одной карте 16 часов с 6-ю видеокартами. Стоит это ~9000$
Если добавить цифры — будет уже 28 дней на одной карте За те же 9000$ получаем 7 дней.
GPU становятся все лучше и всё дешевле.
У не случайных нападающих железо сильно лучше (https://www.secjuice.com/how-to-build-a-cracking-rig/). А ещё можно просто арендовать мощности в облаке.
Alexander Makarov Это с ним замеры.
Alexander Makarov Это брутфорс. Если пароль словарный, всё быстрее и проще.
Alexander Makarov ⌛️ bcrypt даёт вам лишь время
Если вы знаете, что хэши утекли:
- Устранить источник утечек
- Инвалидировать хэши
- Попросить пользователей поменять пароли и объяснить, что сделать это надо везде
✅ Много времени можно получить используя Argon2 (https://password-hashing.net/). Он не ускоряется на GPU из-за интенсивного использования памяти
enotit Без санкций))
Alexander Makarov Да с ними тоже. Если измерять в $, а не в ₽.
Alexander Makarov Вот, кстати, почему логин "тупит".
Marat Это надо еще обязать пользователя использовать регистры, цифры и спецсимвол , не всем это нравится, проще сделать вход через смс как в озоне)
enotit Если четсно, то не понял
Alexander Makarov Ох :(
Alexander Makarov Ограничения = меньше комбинаций перебирать.
enotit В голове висела идея, убрать пароли и просто повесить oauth через тг или вк за 2 виджета и 10 строк кода
Alex Скиньте инфо прочитать про соль пожалуйста
Alexander Makarov Сессии
- Фиксация - дать пользователю заранее известный ID сессии.
- Перехват cookie.
✅ Решение
Используйте только куки. В php.ini:
session.use_cookies = 1
session.use_only_cookies = 1
session_cookie_httponly = 1
session.cookie_secure = 1
Регенерируйте ID сессии при помощи session_regenerate_id(true) после логина или смены прав. https://imgur.com/yqVo01V
Alexander Makarov Минус:
Упадут сервисы — всё. Не войдёшь.
Плюс:
Теперь париться им, а не нам.
Alexander Makarov https://en.wikipedia.org/wiki/Bcrypt
enotit Как будто плюсы перевешивают, особенно то как часто падает телеграм и как быстро поднимается. А вероятность, что его отключат в рф, нежели сервисы смс / взломы паролей и etc исторически меньше
Alexander Makarov Не забывайте проверять доступ
Да, такое бывает и бывает у очень серьёзных компаний и проектов.
- Доступ к файлу по URL.
- Скрыть != обезопасить.
✅ Сначала запрещайте всё, потом уже разрешайте.
Дмитрий Тарасов Как выбрать подходящий cost для bcrypt, чтобы обеспечить безопасность и при этом не перегрузить сервер?
Alexander Makarov Свичнуться на aragon2
enotit А как файл давать не по url? Или имеется ввиду временно открывать, на время скачки?
Alexander Makarov Утечки информации
- Отладочный режим
- Страницы ошибок
- Ответы API
- Системы контроля версий
Alexander Makarov Имеется ввиду права проверять. Потому что "URL не знают" — это не безопасность. Так VK попал с приватными альбомами когда-то.
Alexander Makarov Утечки паролей
- Из репозитория
- Из файлов
✅ Что делать?
HashiCorp Vault
николай catman ansible vault подойдет? Алсо, про утечку паролей, стоит добавить - используйте менеджеры паролей! и 2fa не через смс!
Alexander Makarov Вот этого дофига! Просто дофига. Тупо забывают выключить дебаг.
Николай Лукин А к этому можно отнести IDOR?
Alexander Makarov Да.
Alexander Makarov Это оно и есть.
enotit Сделать оболочку над ссылкой, а потом редир.... не понимать. Клиент (не бизнес клиент) же откуда-то как-то должен скачать файл.
Есть же более крутой пример, lighshot, где можно просто перебором найти и номера карт, и личные фото
Alexander Makarov TOTP.
Alexander Makarov Обновляйтесь
- Linux
- nginx
- PHP
- СУБД
- Любимый фреймворк
- ...
Alexander Makarov Вот как проверять — это уже сложно. Либо отсматривать руками всё, но это тяжко. Либо по каким-то спискам. Я отсматриваю по мере возможности.
Alexander Makarov DDOS
- Планируйте заранее.
- Положитесь на firewall (возможно железный).
- Может быть очень тяжело.
Держите про запас отменного админа...
Alexander Makarov Сами вы DDOS не вывезите. Первый раз уж точно.
enotit Объяснить заказчику зачем ему обновляться "а зачем вы установили плохое?" - лучшее xD
николай catman в гитхабе есть dependabot, который может прислать ПР если найдена уязвимость + сам гитхаб может сообщить о том, что у вас апи ключ утек, есть уязвимая зависимость.
Alexander Makarov Раз зашла речь про админов
- Торчащие наружу memcached и mongodb
- Саппорт Windows: активировали винду без проверки
- Саппорт hetzner: ребут сервера
- Раздача прав на прод всем разработчикам компании
- Сервера в разных ДЦ, API без паролей
- Не защищённый S3-бакет
enotit Это что имеется ввиду? Навесить баннер и ждать сплыва?
Alexander Makarov Он ошибается и часто.
Николай Лукин Ещё утилита хорошая есть Truffle Hog.
Alexander Makarov Это имеется ввиду что если нет составленного плана, на панике делается фигня.
Alexander Makarov Безопасность - это процесс
Нельзя сделать приложение безопасным один раз и навсегда. Абсолютная безопасность недостижима.
✅ Обучайте свою команду
Идеально, если в команде есть кто-то, кто знаком с темой. Используйте VCS и делайте code review.
✅ Подумайте о bug bounty
Иван Кацаренко Когда отсматривал, удавалось ли что-то нехорошее найти в каких-то популярных вещах?
николай catman ееще у подобных инструментов иногда бывают дефолтные юзеры, типа admin / admin, поэтому стоит не забывать менять пароли)
Alexander Makarov 👯 Люди — всегда слабое звено.
- Теряют флешки.
- Теряют ноуты.
- Теряют телефоны.
- Пропускают в офис кого попало.
См.:
- Гавайи и "ракетный удар" (https://tjournal.ru/tech/65054-otpravivshaya-lozhnoe-soobshchenie-o-raketnom-udare-gavayskaya-sluzhba-hranila-parol-na-stikere-na-monitore)
- Французское ТВ (https://habr.com/ru/post/255509/)
enotit Это уже больше про софты? Формализовать ЧП? Я думал про харды всё, Аля навесить баннер и ждать, пока нагружается система, перевести на рядом стоящие бизнес ручки (техподдержка) - как вариант.
Alexander Makarov В популярных — нет.
Alexander Makarov У меня одно из хобби — проходить в офисы. Классика — два стаканчика кофе и "подержите дверь".
Николай Лукин Можно ещё коробку в руках держать - точно пропустят!
enotit Вот проблемы белых людей, ой, проблемы продуктовиков. Аутстаферам платить за взлом их же кода, прям грязь перед заказчиком..
Alexander Makarov Ну, может быть и хардовый план. Аля "что делать админу — вырубить сервер".
Alexander Makarov**** Планируйте заранее
- Что есть злыдни получили доступ к X?
- Какие данные не должны утечь никогда? (= не надо их хранить)
- Следует ли админу потушить взломанный сервер?
- Заготовьте страницу-заглушку.
- Что сломали? Как? Каков урон?
- Как поправить?
- Объяснить команде, в чём была ошибка и как её не делать. Как альтернатива -- найти технический способ не допускать подобных ошибок.
enotit Звучит как новая миссия из gta))
Alexander Makarov Постоянно учитесь
- target="_blank" не безопасен
- ImageMagick не безопасен
- SMS не безопасны
- XML тоже! (XXE)
- Ох, и десериализовывать опасно!
- Процессоры не безопасны :(
Alexander Makarov Оно и ощущается так же. Адреналииин!
enotit Особенно в маленькую компанию с 3 рзрабами, двумя скрам мастерами)))
Николай Лукин Помоему это так и называется, физический пентест.
Alexander Makarov Сделайте так, чтобы взломать вас было слишком хлопотно. Это будет возможно, но дорого.
Оставайтесь в безопасности 😜 https://imgur.com/CQhmxyO
Alexander Makarov Это не интересно. Проходные, ключики, лотки для документов, мусор — вот это да!
enotit Это если к поведению на "a href" имеет доступ пользователь? правильно понимаю?
Alexander Makarov Неа. Это что мы так открыли может начать нас контролировать.
Alexander Makarov 📙Почитать
- OWASP (http://owasp.org/) (осторожно, это wiki!) + testing guide (https://www.owasp.org/index.php/OWASP_Testing_Guide_v4_Table_of_Contents)
- Фаулер про безопасность (https://martinfowler.com/articles/web-security-basics.html)
- https://secure.php.net/manual/ru/security.php Да, в мануале есть про безопасность ;)
- Компонент Yii security (https://github.com/yiisoft/yii2/blob/master/framework/base/Security.php)
- QA на StackExchange (https://security.stackexchange.com/)
enotit Так а если будет в этой же вкладке, в чём разница?..
Alexander Makarov _blank — это не в этой же.
Ярославна Поздникина Ребята, у кого остались вопросы или мы пропустили по ходу, - сейчас самое время спросить
enotit это я для примера, что в чём разница в этой или в отдельной?
Alexander Makarov _blank форсит новую вкладку или окно и наделяет её кое-какими правами на старую
Павел Иванов А дальше что делаешь? Говоришь - ребята, я тут не работаю, но прошел к вам, подумайте над своей безопасностью? :)
enotit https://habr.com/ru/articles/282880/ хм, интересно, спасибо
Alexander Makarov А дальше иду к тому, кто меня приглашал (обычно я без дел в офисы не хожу). Просто выбираю занятный способ захода.
Ярославна Поздникина Александр, спасибо, что пришел к нам в комьюнити и провел этот час с нами. Приходи еще)