Вступление
Современные реалии бизнеса диктуют свои достаточно жёсткие требования к web-разработке. В основном заказчиков интересуют функциональные характеристики продукта, его дизайн и юзабилити, при этом не уделяют достаточно внимания безопасности. Причин сложившейся ситуации много, основная - удорожание продукта при внедрении принципов «безопасного программирования». Поэтому, для тех, кто решил закрыть глаза на вопросы безопасности, оправдывая себя фразами типа «кому мы нужны?» или «захотят взломать — взломают», мы накидали несколько «вредных» советов.
Вредный совет первый
Откажитесь от фильтрации и проверки данных на стороне сервера и клиента. Фильтрация данных приведет к появлению «лишнего кода», что увеличит возможность ошибки и приведёт к удорожанию разработки. Некорректная фильтрация данных возникает в том случае, когда данные, получаемые веб-приложением от пользователей, недостаточно экранируются или недостаточно фильтруются перед непосредственным выполнением в коде. Подобные ошибки приводят к возникновению уязвимостей SQLi, RCE, XXE, XSS, и тд. Рассмотрим подробнее на примере SQL injection (далее SQLi). Допустим, есть числовой параметр id, с помощью которого веб-приложение запрашивает соответствующую запись в БД. Если код, отвечающий за этот функционал, выглядит примерно так:
$id = $_GET['id']
$query = "SELECT * FROM some_table_name WHERE id=$id"
то запрос к БД будет выглядеть так:
SELECT * FROM some_table_name WHERE id=1
Если не производить фильтрацию данных или экранирование символов, которые принимаются в качестве аргумента, то при поиске уязвимости будет подставляться спецсимвол «'», а в БД будет отправляться запрос типа:
SELECT * FROM some_table_name WHERE id=1'
который нарушит синтаксис запроса, и в ответе от веб-приложения атакующий получит ошибку от базы данных, которая будет маркером возможности проведения SQLi. Дальнейшая эксплуатация уязвимости приведет к полной компрометации базы данных, где может храниться не только информация о логинах и паролях пользователей, но и другая конфиденциальная информация, например, реквизиты кредитных карт или персональные данные. Однако стоит отметить, на основе информации от багтрекер-площадки HackerOne, что в период за 2019-2020 год наблюдается тенденция к снижению количества случаев эксплуатации популярной уязвимости SQLi. Это подтверждается и статистикой компании Acunetix , которая предоставила отчет веб-уязвимостей за 2019-2020 год, где SQLi были обнаружены у 8% сайтов, так что скоро можно будет спать спокойно.
Вредный совет второй
Например при работе с пользователем ваше приложение создает экземпляр класса, почему бы не хранить его на стороне пользователя, это же удобно?! При этом дополнительными настройками безопасности можно не заморачиваться, мы же доверяем нашим пользователям. Пример использования десериализации. В данном примере есть класс Injection, в котором реализован магический метод __wakeup(). Данный метод выполняется во время десереализации объекта и выполняет код, который хранится в переменной $some_data.
<?php
class Injection {
public $some_data;
function __wakeup(){
if( isset( $this->some_data ) ){
eval( $this->some_data );
}
}
}
if( isset( $_REQUEST['data'] ) ){
$result = unserialize( $_REQUEST['data'] );
// ...
}
?>
<?php
class Injection {
public $some_data;
function __wakeup(){
if( isset( $this->some_data ) ){
eval( $this->some_data );
}
}
}
$inj = new Injection();
$inj->some_data = "phpinfo();";
echo( serialize( $inj ) );
?>
Зная исходный код создадим строку с полезной нагрузкой в виде сериализованного объекта, который будет иметь следующий вид:
O:9:"Injection":1:{s:9:"some_data";s:10:"phpinfo();";}
Передав пейлоад в уязвимое веб-приложение выполнится, в нашем случае, функция phpinfo().
Вредный совет третий
Если мы никому не нужны, то зачем заморачиваться с шифрованием паролей, тем более если директор пользователь забудет и запросит у нас свой пароль, мы всегда ему сможем напомнить. Вот простой пример кода для реализации не зашифрованного хранения пароля в базе данных:
$LINK = new mysqli($DB_HOST, $DB_USER, $DB_PASS, $DB_NAME);
$user_name = $_GET['login'];
$user_password = $_GET['password'];
$query = $LINK->prepare("select id from user where login = '$user_name' and user_password='$user_password'");
$query->execute();
Вредный совет четвертый
Создание приложения со сложной политикой аутентификации, определенно затратно и более длительно по времени, да и зачем усложнять себе и пользователям жизнь, если можно придумать «длинный пароль», например от 123456789. А чтобы не заморачиваться с защитой от перебора логина и пароля
можно этот пароль усложнить спецсимволом, например вот так: $123456789 или так 123456789#. Самый надежный пароль - это длинный пароль, и этого вполне достаточно для надежной аутентификации.
Согласно официальной статистике компании NordPass, специализирующейся на разработке менеджера паролей, по-прежнему лидирует пароль 123456, на втором месте — 123456789, стоит отметить, что придуманного выше пароля в статистике нет (а там более 200 паролей), значит злоумышленник «хапнет горя» от перебора.
Внедрение двухфакторной аутентификации имеет смысл если социальные сети и крупнейшие интернет-порталы, поэтому можно обойтись капчей и сложным универсальным паролем.
Бонус. Хотя это не связанно с парольной политикой, но все же, вспомните как часто при авторизации на сайтах, вы вводили не верные данные, а понять, где ошибка в логине или в пароле сразу сложно и приходится заполнять обе формы по новой. Раздражает, правда?!
В популярном CMS WordPress можно проводить проверку пользователей средствами движка из «коробки». На стандартной странице логина при валидном имени пользователя, но неправильном пароле выдается ошибка, что для существующего пользователя введен неправильный пароль. Но если ввести несуществующий логин, то и ошибка будет нам говорить о том, что такого пользователя не существует. Возможно кому-то такой подход покажется интересным, хотя в какой-то степени это тоже является раскрытием конфиденциальной информации, и злоумышленник может этим воспользоваться для последующего перебора паролей.
Вредный совет пятый
Учитесь экономить правильно! Не нужно переплачивать опытному админу, для обслуживания одного — двух веб-серверов, достаточно студента профильного вуза третьего курса и выше. Приведем некоторые ошибки конфигурации параметров безопасности на которые при желании можно обратить внимание:
включены и используются учетные записи по умолчанию. Тут все просто, если заметите это раньше злоумышленника - лучше сразу отключить;
включено индексирование директорий веб-приложения, позволяющее просматривать их содержимое.
Такой пример конфигурации ngnix:
http {
autoindex on;
include etc/nginx/mime.types;
default_type application/octet-stream;
приведет к такой проблеме:
включено отображение ошибок веб-приложения для пользователя. Это не так страшно звучит, можно подзабить;
Что делать с обновлением ПО на сервере? Практически в 90% случаев при правильной первой установке компонентов сервера, мы имеем актуальные версии пакетов. Мы «рекомендуем» после того как сервер будет запущен и ваше приложение уже работает, сделать резервную копию, отключить обновление и забыть навсегда о них. Многие сервера Linux работают десятилетиями без обновлений и перезагрузок. Сам же процесс обновление ПО на сервере особенно под управлением Unix подобных систем, рисковое дело - можно все сломать, а уязвимости одни латают, другие появляются - тут тоже можно пренебречь. Админы сами говорят «работает не - трогай!».
Если есть необходимость временно запустить на сервере дополнительный сервис и открыть его в мир - используйте порты выше 1024. Эти порты не так популярны для сканирования у мамкиных хакеров.
В идеале сбор логов должен быть централизован, а значит нужно обзавестись отдельным сервером и настроить перенаправление. С другой стороны, есть человек которому и так вы платите деньги, и следить за ситуацией и читать лог-файлы, входит в его обязанности. Вопрос, успеет ли он вовремя заметить критические сообщения? Да — должен! все равно ничего не делает!
Заключение
Все вышеперечисленные советы имеют саркастический характер, мы рекомендуем ответственно подходить к вопросу безопасности web-приложений начиная с этапа его проектирования и разработки, заканчивая администрированием.
В настоящее время под атаками могут находиться любые приложения в независимости от размера вашей компании и рода деятельности.
Для обеспечения защиты веб-приложения от многих видов информационных атак на прикладном уровне существуют файрволы веб-приложений (WAF). Такие решения достаточно функциональны и надежны, но требуют и внимания, и контроля со стороны администратора, это связанно с ручной обработкой новых типов атак для расширения сигнатур WAF. Для упрощения этой задачи и увеличения процента точности современные WAF используют модули машинного обучения. Примером такого файрвола является наш продукт Nemesida WAF — он содержит модуль машинного обучения благодаря которому способен выявлять атаки с минимальным количеством ложных срабатываний. Для отображении информации об атаках и выявленных уязвимостей Nemesida WAF содержит удобный личный кабинет.
Для тех кто заинтересован в углубленном изучении природы уязвимостей различного рода информационных систем мы предлагаем пройти курсы этичного хакинга, на которых под руководством опытного куратора вы не только изучите теоретическую часть но и отточите полученные знания в в пентест-лаборатории.