Я пишу намеренно уязвимое веб-приложение. Я хотел бы выяснить, как проверить имя пользователя и пароль на соответствие базе данных и друг другу.
Итак: если имя пользователя существует в базе данных и пароль существует в базе данных, а имя пользователя и пароль принадлежат вместе. Я полностью знаю, как отправить запрос, который проверяет оба параметра одновременно и возвращает либо истину, либо ложь, поэтому, пожалуйста, не начинайте с этого. Моя цель - индивидуально проверить оба, чтобы я мог сообщить пользователю, какой из них не работает.
Вот мой код, но, поскольку я на самом деле не специалист по PHP, он явно не работает:
<?php
if (isset($_POST["submit"])){
$username = mysqli_real_escape_string($conn, $_POST['username']);
$password = mysqli_real_escape_string($conn, $_POST['password']);
$sql_username = "SELECT id FROM users WHERE username = '$username'";
$sql_password = "SELECT id FROM users WHERE password = '$password'";
$result_username = mysqli_query($conn, $sql_username);
$result_password = mysqli_query($conn, $sql_password);
$row_username = mysqli_fetch_array($result_username);
$row_password = mysqli_fetch_array($result_password);
$count_username = mysqli_num_rows($result_username);
$count_password = mysqli_num_rows($result_password);
if ($count_username > 0 && $count_password < 0) {
echo "Invalied password";
} else if ($count_username < 0 && $count_password > 0) {
echo "Invalied username";
} else {
"Welcome";
}
}
?>
Какие-нибудь намеки?
Можно использовать $ conn, поскольку я получаю его из другого файла php.
Примечание. Объектно-ориентированный интерфейс mysqli значительно менее подробен, что упрощает чтение и аудит кода, и его нелегко спутать с устаревшим интерфейсом mysql_query. Прежде чем вы слишком увлечетесь процедурным стилем, стоит переключиться на него. Пример: $db = new mysqli(…) и $db->prepare("…"). Процедурный интерфейс является артефактом эпохи PHP 4, когда был представлен API mysqli, и его не следует использовать в новом коде.
mysqli вы должны использовать параметризованные запросы и bind_param для добавления пользовательских данных в свой запрос. НЕ использует для этого строковую интерполяцию или конкатенацию, потому что вы создали серьезный Ошибка SQL-инъекции. НИКОГДА помещает данные пользователя $_POST, $_GET или любой непосредственно в запрос, это может быть очень вредно, если кто-то попытается воспользоваться вашей ошибкой.
Вы никогда проверяете пароль в базе данных, потому что, если вы можете выполнить сопоставление с открытым текстом, у вас уже проблемы. Хороший алгоритм хеширования паролей производит по существу случайный результат, но его можно проверить, если и только если у вас есть правильное «предположение». Правильная процедура - найти соответствующую пользовательскую строку, загрузить эти данные и проверить хэш с помощью password_verify.
дорогой Тадман, большое спасибо за твои идеи. пожалуйста, игнорируйте все недостатки безопасности в моем коде и сосредоточьтесь на вопросе. Хотите верьте, хотите нет, но моя абсолютная цель - сделать приложение настолько уязвимым, насколько это возможно - отсюда и подробная пользовательская информация об имени пользователя и пароле. Спасибо.
Этот код позволит вам войти, если я введу «admin», который является пользователем, и «pass123», который является паролем для кто-нибудь. Это не проверяет правильность пароля администратора.
Ни один из этих кодов не имеет смысла. Почему бы просто не впустить их, даже не пытаясь, если это цель? Реальный код входа в систему структурирован не так, поэтому я не уверен, что вы пытаетесь доказать, даже с академической точки зрения. Если бы вы могли лучше объяснить эту часть, мы, вероятно, могли бы заняться этим конкретно.
это, к сожалению, неверно, этот код не дает никакой реакции на любой ввод. Я предполагаю, что он не может отправить более 1 запроса одним нажатием кнопки.
Это запускает два запроса на запрос. Не уверен, куда вы идете с этим. Если у вас есть одна строка с «admin» в качестве имени пользователя и другая, совершенно не связанная с этим строка с «pass123» в качестве пароля, то угадывание этой комбинации позволит войти.






<?php
//set up a connection and all that prerequisite stuff
$sqlConnectionNameHere = new mysqli($sql_host, $sql_username, $sql_password, $sql_dbname);
$username = 'bob'; //the username that will be checked
$password = 'securepassword1'; //the password that will be checked
$query = $sqlConnectionNameHere->query("SELECT username, password FROM users WHERE username='$username' LIMIT 1"); //make your query
if ($query->num_rows != 1){ //if the datbase didn't return any rows, the user with $username must not exist
die('User not found!');
}
while ($user = $query->fetch_assoc()){
if ($user['password'] != $password){
die('Invalid Password');
}
}
//if they've made it here, the user exists and the password matches!
echo 'Welcome!';
?>
Это действительно простой способ сделать это. Вы можете добавить к этому дополнительную безопасность.
Надеюсь это поможет. Удачи тебе!
Я знаю, что вы просто пытаетесь помочь, но эти быстрые решения создают больше проблем, чем решают.
1. этот пример недействителен, потому что он повторно использует переменную $username для подключения и для проверки пользователем 2. в этом примере вводится SQL-инъекция
Я знаю, что это круче, чтобы пользователь знал, неверны ли имя пользователя или пароль. Но это на самом деле помогает нежелательным особям пройти этот тест. Поскольку они могут проверить, присутствует ли конкретный пользователь или нет. Оттуда этот человек может подобрать пароль. Поэтому рекомендуется просто проверить имя пользователя и пароль.
Кроме того, вы можете сохранить пароль в виде хеша. Таким образом, даже хост вашей базы данных не имеет прямого доступа к паролям. Используйте MD5 или SHA. Например, учетные данные в вашей базе данных будут выглядеть так:
User Password
Admin 098f6bcd4621d373cade4e832627b4f6
Это хеш MD5. Вы получите этот хеш, если обработаете md5('test'). Хеш - это функция «шифрования» в одну сторону. Вы проверяете это путем хеширования пользовательского ввода и сравнения этого результата с сохраненным хешем.
Если вы проверите этот пароль, вы привяжете его следующим образом:
$stmt->bind_param("ss", $_POST['username'], md5($_POST['password']));
$mysqli = new mysqli("localhost", "my_user", "my_password", "my_db");
Открытый пароль (не рекомендуется!) - подготовленный выбор
$stmt = $mysqli->prepare("SELECT id FROM users WHERE username=? AND password=?");
// type string, string ("ss")
$stmt->bind_param("ss", $_POST['username'], $_POST['password']);
// hashed (recommended)
// $stmt->bind_param("ss", $_POST['username'], md5($_POST['password']));
$stmt->execute();
// set target for the id-column
$stmt->bind_result($id);
// Will be TRUE if a row has been found
if ( $stmt->fetch() ) {
echo "Welcome! user:{$id}";
} else {
echo "Invalid username or password";
}
Подробности смотрите на mysqli подготовить И еще немного, связанное с безопасностью: Хеширование паролей
Я ценю вашу заботу и помощь Пилану, но на самом деле причиной этого кода является представление уязвимостей. :) Спасибо за ваш вклад!
о :( - ну, теперь этот код общедоступен и будет скопирован - я могу спать лучше, если знаю, что здесь есть ответ, указывающий на это
спать спокойно дружище :)