В данном райтапе речь пойдет о таске Цирковой трюк из категории веб.
Приложение банальное, есть форма авторизации, через которое нам нужно попасть на правах администратора.
Открываем код и находим интересные вещи:
PHP:
Код:
";
$password = "";
$dbname = "users";
$conn = new mysqli($servername, $username, $password, $dbname);
if ($conn->connect_error) {
die("Ошибка подключения: " . $conn->connect_error);
}
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$login = $_POST['login'];
$password = $_POST['password'];
$sql = "SELECT password_hash FROM user_creds WHERE login = '$login'";
$result = $conn->query($sql);
if (!$result) {
$error = "Ошибка SQL: " . $conn->error;
} else {
if ($result->num_rows > 0) {
$row = $result->fetch_assoc();
if (hash('sha256', $password) == $row['password_hash']) {
$success = true;
if ($login === 'administrator') {
$flag = file_get_contents('/opt/flag.txt');
if ($flag === false) {
$error = "Не удалось прочитать флаг.";
}
} else {
$flag = null;
}
} else {
$error = 'Неверный логин или пароль';
}
} else {
$error = 'Неверный логин или пароль';
}
}
}
$conn->close();
?>
Вход | Цирковой трюк
body {
background-color: #f8f9fa;
font-family: 'Arial', sans-serif;
}
.container {
max-width: 500px;
margin-top: 100px;
}
h2 {
text-align: center;
margin-bottom: 20px;
}
.alert {
margin-bottom: 20px;
}
Успешная авторизация! Забирайте флаг -
.
Добро пожаловать,
!
Авторизация
Логин
Пароль
Войти
Остановимся на этих ключевых моментах:
1. Если логин пользователя —
administrator, то происходит попытка прочитать файл /opt/flag.txt:
PHP:
Код:
if
(
$login
===
'administrator'
)
{
$flag
=
file_get_contents
(
'/opt/flag.txt'
)
;
if
(
$flag
===
false
)
{
$error
=
"Не удалось прочитать флаг."
;
}
}
else
{
$flag
=
null
;
}
2. Этот запрос представляет собой SQL-запрос, который выполняется в базе данных для извлечения хешированного пароля пользователя с указанным логином:
PHP:
Код:
$sql
=
"SELECT password_hash FROM user_creds WHERE login = '$login'"
;
3. Если запрос выполнен успешно и возвращается хотя бы одна строка (пользователь найден), происходит проверка пароля:
PHP:
Код:
if
(
hash
(
'sha256'
,
$password
)
==
$row
[
'password_hash'
]
)
{
$success
=
true
;
}
Достаем из базы все, что есть:
sqlmap -u http://62.173.140.174:16064/login.php --data='login=vov4ick&password=1' --dump --dbms='MySQL' -batch
Здесь нам нужен хеш администратора, если обратить на него внимание, то это даст нам нужный вектор.
На поле выходит новый игрок!
В PHP есть такая особенность (называемая
PHP Type Juggling), когда
нестрогое сравнение (==) приводит строки, начинающиеся с
0e, к
числу 0. Это значит, что если хеш строки начинается с 0e, это может привести к тому, что хеш и введенный пароль, если оба приведены к числу
0, будут приравнены друг к другу при
нестрогом сравнении.
PHP:
Код:
if
(
hash
(
'sha256'
,
$password
)
==
$row
[
'password_hash'
]
)
{
В данном случае нам не обязательно знать пароль от учетки администратора. Если взять строку, которая при преобразовании в sha256 получает хеш, который начинается с 0e, то мы сможем использовать ее вместо пароля.
Пробуем авторизоваться и успешно забираем флаг:
