По роду своей деятельности, мне приходится выполнять аудиты безопасности исходного кода веб-приложений.
Много веб-приложений и много кода…
В этой статье я хотел бы поделиться одной простой (очень простой) истиной и статистикой, которые вывел и многократно проверил в течении трех последний лет просмотра тонн РНР кода.
Не секрет, что уязвимости внедрения операторов СУБД (SQL injections) являются самыми распространенными из всех серверных уязвимостей веб-приложений. Есть платформы и фреймворки, где такие вещи практически полностью исключены, например ORM'ом и прочим. Но статистика упорно говорит нам об абсолютном преобладании на просторах Интернета веб-приложений с простыми конкатенированными SQL запросами. Кроме того, есть случаи, где ORM вообще применим быть не может. Например, когда от пользовательских данных должны зависеть не только параметры выражений, но и сама логика запроса на уровне операторов.
Итак, начнем.
Бесполезное экранирование символов
Найдено в 83% РНР веб-приложений, уязвимых к SQL-инъекциям
Применение функции экранирования символов, таких как
mysql_escape_string
mysql_real_escape_string
addslashes
без обрамления кавычками. Чаще всего проявляется в числовых параметрах (всевозможные *_id).
Пример
$sql = "SELECT user FROM userslist WHERE userid=".mysql_real_escape_string($_GET['uid']);
На вид, это безопасный код, но только на вид. Сюда закрался самый частый в моей практике шаблон SQL-инъекций в РНР. Для проведения атаки на эту уязвимость от злоумышленника требуется просто не использовать символы " ' x00 r n x1a в векторе атаки.
Например:
/index.php?uid=-777 UNION SELECT password FROM userlist
Поиск в коде
Осложнен семантикой языка. Для простого поиска можно использовать egrep:
egrep -Rin "(select|update|insert|delete|replace).*(from|set|into).*(mysql_escape_string|mysql_real_escape_string|addslashes)" . | grep -v "["']['"]"
Логика поискового выражения такая — найти все строки, в которых слева от функций фильтрации нет последовательности символов кавычек ('', "", "', '"). Метод, разумеется, далеко не 100%, но требовать от регулярного выражения выполнить семантический анализ невозможно.
Для удобства вывода информации, можно подсветить функцию цветом в консоли:
egrep -Rin "(select|update|insert|delete|replace).*(from|set|into).*(mysql_escape_string|mysql_real_escape_string|addslashes)" . | grep -v "["']['"]" | egrep --color "(mysql_escape_string|mysql_real_escape_string|addslashes)"
Для защиты от этой шаблонной уязвимости, лучше всего использовать приведение типов.
Это всегда быстрее работает и надежнее чем всевозможные фильтрации и экранирования.
Для примера выше, патч может быть таким:
$sql = "SELECT user FROM userslist WHERE userid=".intval($_GET['uid']);
На этом короткий очерк окончен. Призываю всех веб-разработчиков попробовать гренуть свои исходники на предмет таких конструкций. А еще лучше, расширить приведенный поисковый скрипт для людей.
Автор: d0znpp