Возможна ли в этом коде SQL-инъекция?
Введение
Я взял на себя обслуживание действительно грязной страницы PHP, которая является платформой бронирования апартаментов для отдыха, но это не важно. Код изначально был написан дизайнером (а не программистом), и он действительно плох. Передача логических переменных строками "true" и "false" является одним из второстепенных WTF. Я хочу убедить владельца страницы, дать мне время (и деньги, конечно), чтобы очистить его код (или переписать его).
По-видимому, оригинал "разработчик" никогда не слышал о SQL-инъекции, потому что он использует переменные POST и GET непосредственно в своих SQL-операторах. Чтобы убедить владельца, я хочу немного шокировать его, войдя в систему как администратор без использования его пароля.
Tl;dr (или: Фактический вопрос)
Это утверждение (где $p_username - это переменная POST, которая содержит содержимое поля ввода "Имя пользователя"):
"SELECT password FROM user WHERE username = '$p_username'"
Возвращенная строка (которая является несоленым MD5-хэшем пароля, который был сохранен в база данных) затем сравнивается с (также хэшированной) строкой, которая была введена в поле "Пароль", и если обе строки совпадают, пользователь входит в систему как введенный пользователь. Можно ли ввести что-то в поле имени пользователя, чтобы войти в систему как "поддельный" администратор?
Примечание: Сервер БД - MySQL, PHP находится в версии 5 и magic_quotes
включен.
6 answers
Как отметил полковник Дж. Шрапнель, magic_quotes
делает это невозможным, если только вы не бежите в каких-то очень особых обстоятельствах.
Однако, если то, что вы говорите, правда, вполне вероятно, что первоначальный разработчик мало что знал о magic_quotes, поэтому, скорее всего, он ошибся, если когда-либо сохранял значения GET/POST/COOKIE где-либо еще, кроме операторов SQL. Короче говоря, ищите места, где '
и "
были бы законными, и проверьте, не перепутались ли они.
Также - знал ли он о htmlspecialchars()
, или инъекция HTML/Javascript все еще возможна?:)
С включенными магическими кавычками это было бы невозможно.
Если это полный запрос и проверка пароля выполняется на стороне PHP, вы не сможете войти в систему как администратор (даже если magic_quotes отключен), потому что вам все равно придется сопоставлять хэш пароля.
Как отмечали другие, получить одинарную кавычку после магических кавычек сложно, но если это можно сделать, запрос является тостом. Подумайте, не могли бы мы ввести следующее:
SELECT password FROM user WHERE username = 'unlikely'
UNION ALL SELECT CHAR(102,111,111); #'
Это вернет строку "foo" в PHP в качестве пароля, поэтому все, что нам нужно сделать, это убедиться, что наша форма отправляет нашу инъекцию для имени пользователя $ и "foo" для пароля $.
РЕДАКТИРОВАТЬ
Существует несколько векторов атаки с addslashes()
. Первый, который я выбрал ниже, был основан на статье, ранее приведенной в ответе, в котором она цитировалась в поддержку противоположный претензия. По крайней мере, еще один - с слишком длинными строками, использующими кодировку не ниже UTF-8.
Http://www.erich-kachel.de/?tag=addslashes
Можно было бы построить аналогичную технику, описанную ниже. Короче говоря, команда MySQL сочла нужным уйти в отставку magic_quotes
, а также настоятельно не рекомендуется притворяться, что addslashes() - это реальная форма защиты. Может быть, вы знаете, что команда MySQL знала бы лучше? Как бы то ни было, mysql_real_escape_string также имеет некоторые уязвимости в крайнем случае, но, поскольку он специфичен для MySQL, а не только для PHP, он делает еще один шаг вперед. Лучшим решением было бы использовать параметры запроса.
Следует оригинальный ответ
Да, можно войти в систему как администратор. Ни в одном иди, но двух проходов будет достаточно.
Ссылка - http://shiflett.org/blog/2006/jan/addslashes-versus-mysql-real-escape-string (Да, это та же ссылка из другого ответа, но вместо этого моя интерпретация заключается в том, что это обычно возможно для любого многобайтового набора символов, кроме utf8)
Вы не указали, является ли ваша система многобайтовой, но, поскольку вопрос открыт, я буду считать, что это так.
$p_username = chr(0xbf) . chr(0x27) . ';' .
"update user set password='password', '.
"username='" . chr(0xbf) . "' where username='admin' /*';
"SELECT password FROM user WHERE username = '$p_username'"
Я изменил имя пользователя И пароль "администратора" пользователь
Этот тип атаки возможен с любой кодировкой символов, где есть допустимый многобайтовый символ, заканчивающийся на 0x5c
Я думаю, что важно проверить все входные переменные и экранировать все специальные символы, даже если включена функция magic_quotes.
Чтобы быть уверенным, вы можете протестировать свой код с помощью sqlmap.