Проверьте, защищена ли система входа в систему от внедрения sql

Так что для школьного проекта мне нужно сделать сайт с системой авторизации. В нем есть поле для имени пользователя и пароля, а также кнопка отправки. Он сравнивает имя пользователя и пароль с таковыми в базе данных MySQL. Если комбинация находится в базе данных, пользователь может продолжить, иначе он будет перенаправлен на страницу входа в систему. Я использую подготовленные операторы PDO для подключения к базе данных.

Теперь мой учитель хочет, чтобы я проверил безопасность, выполнив атаки sql на систему входа. К сожалению, я не знаю, что положить в эти коробки и каков будет результат. Например, я попытался ввести значения как в поля имени пользователя, так и в поле пароля, которые вернут истину, например:

1==1,  1===1,  0 is null

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

HTML-код:

<form method="post" action="includes/login.php">
<input type="text" name="gebruikersnaam" >
<input type="password" name="wachtwoord" >
<input type="submit"  value="login">
</form>

Аутентификация php:

$myusername=$_POST['gebruikersnaam']; 
$mypassword=$_POST['wachtwoord']; 
$sql="SELECT * FROM leerling WHERE leerlingnummer='$myusername' and wachtwoord='$mypassword'";
$sql2="SELECT * FROM lop WHERE gebruikersnaam='$myusername' and wachtwoord='$mypassword'";
$statement2=$conn->prepare($sql2);
$statement2->execute();
$count2=$statement2->rowcount();

if($count2==1){proceed}

$statement = $conn->prepare($sql);
$statement->execute();
$count= $statement->rowcount();

if($count==1){proceed}

else {deny access}

person JJJ    schedule 12.04.2014    source источник
comment
en.wikipedia.org/wiki/SQL_injection - P.S Код может нам помочь.   -  person Marco Acierno    schedule 12.04.2014
comment
Как я уже сказал, я пробовал эти вещи, однако я не знаю, была ли какая-либо система под угрозой.   -  person JJJ    schedule 12.04.2014
comment
А без кода чем мы можем вам помочь?   -  person Marco Acierno    schedule 12.04.2014
comment
Вы используете mysqli, но не используете подготовленные операторы ... ваш текущий код небезопасен! Прочтите php.net/manual/en/mysqli.quickstart. подготовленные-операторы.php   -  person Marco Acierno    schedule 12.04.2014
comment
@MarcoAcierno Я использую PDO, а не mysqli. $ conn - это мое подключение к PDO.   -  person JJJ    schedule 12.04.2014
comment
Хорошо, проблема та же. - it2.php.net/pdo.prepared-statements   -  person Marco Acierno    schedule 12.04.2014


Ответы (3)


Представьте себе этот запрос:

SELECT id FROM users WHERE email=? AND password=? LIMIT 1

Теперь представьте, что значениями будут [email protected] и пустая строка для password:

SELECT id FROM users WHERE email='[email protected]' AND password='' LIMIT 1

Это не повредит, если этих учетных данных нет в вашей базе данных. Теперь давайте дадим другой ввод:

Для email мы заполняем пустую строку, а для password мы вставляем ' OR 1=1 (обратите внимание на первый апостроф)

Ваш учитель хочет, чтобы вы выяснили, означает ли это, что ваш SQL-сервер выполнит следующий запрос:

SELECT id FROM users WHERE email='' AND password='' OR 1=1 LIMIT 1

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

person user3526869    schedule 12.04.2014
comment
Что ж, я пробовал это, и он возвращает «неправильные учетные данные», так что это означает, что он отказывает мне в доступе. Что самое смешное, я не знаю, по крайней мере, не знаю почему. Защищает ли меня здесь функция prepare ()? - person JJJ; 12.04.2014
comment
Потому что создатели функции prepare позаботились о том, чтобы, когда вы помещаете вопросительный знак, не оценивается ничего, кроме 1 ввода для значения до знака равенства. password=? будет следить за тем, чтобы только значение пароля считалось правильным вводом. Ваш учитель хотел показать вам, что это действенная защита от SQL-инъекций. Она также должна посоветовать вам не давать переменным голландских имен. - person user3526869; 12.04.2014

Как бы то ни было, он восприимчив к SQL-инъекциям.

При попытке внедрить нужно обратить внимание на то, могу ли я закрыть оператор, в котором я сейчас нахожусь, и добавить что-то еще в конец.

поэтому, если вы введете username = 123456' --, оператор SQL станет SELECT * FROM leerling WHERE leerlingnummer='123456' --' and wachtwoord='unimortant'

- начинает комментарий, поэтому все, что он делает, это выбирает любой введенный номер ученика, игнорируя пароль.

У PDO есть хорошие альтернативы для предотвращения этого, называемые Подготовленные отчеты. Вы объявляете свои SQL-запросы и вводите только туда, где будет вводиться пользовательская информация, используя ? или :lable, а затем привязываете вводимые пользователем данные к этим точкам. Страница лучше объясняет это. Таким образом, все пользовательские данные четко отделены от остальной части команды и будут рассматриваться как буквальная строка, а не как команда. Остановка SQL-инъекции.

person Stephan    schedule 12.04.2014
comment
У меня вопрос, действительно ли этот сценарий защищает меня от этого? Предотвращает ли это функция prepare ()? - person JJJ; 12.04.2014
comment
Обновление проясняет. Это не так, вы должны использовать подготовленные операторы. (подготовленные операторы не помогут, если вы не используете часть привязки параметров). - person Stephan; 12.04.2014
comment
Это не сработает, вы не можете подготовить несколько утверждений. - person Gumbo; 12.04.2014
comment
Ты прав, не подумал об этом. То, что я отредактировал, должно работать. - person Stephan; 12.04.2014

$sql="SELECT * FROM users WHERE username = '{$_REQUEST['username']}' AND password = '{$_REQUEST['password']}";

Запись запроса в таком формате позволит избежать внедрения sql.

    $sql = 'SELECT * FROM users WHERE username = ? AND password = ?';
    $query = $db->prepare($sql);
    $query->bindParam(1, $_REQUEST['username']);
    $query->bindParam(2, $_REQUEST['password']);

Или передайте параметр функции mysql_real_escape_string, а затем перейдите к запросам.

$username=mysql_real_escape_string($_REQUEST['username']);
$password=mysql_real_escape_string($_REQUEST['password']);
person Parimal    schedule 12.04.2014