АКЦИЯ: бесплатные месячные курсы по созданию сайтов
на выбор: верстка, JavaScript, PHP или фреймворки. Сегодня последний день для записи! Жми!
65 of 95 menu
НОВИНКА: Практика на Реальных Проектах и Работы в Портфолио. Бесплатный курс! Жми для записи!

Просмотр чужих данных через SQL в PHP

В данном уроке мы разберем уязвимость, связанную с возможностью просмотра закрытой информации. Пусть для примера у нас есть таблица notes, в которой хранятся заметки пользователей (см. тестовые таблицы в начале раздела). Пусть мы хотим сделать так, чтобы каждый пользователь мог просматривать только свои заметки.

Пусть на странице notes.php мы будем выводить ссылки на заметки пользователя. На этой странице мы будем выводить только заметки данного пользователя, беря его id из сессии:

<?php $user_id = $_SESSION['id']; $query = "SELECT * FROM notes WHERE user_id=$user_id"; for ($data = []; $row = mysqli_fetch_assoc($res); $data[] = $row); ?>

Выведем ссылки на заметки:

<?php foreach ($data as $key => $note) { echo '<a href="note.php?id=' . $note['id'] . '"'>' . $key . '</a>'; } ?>

На странице note.php мы будем показывать конкретную заметку при переходе пользователем по ссылке:

<?php $note_id = $_GET['id']; $query = "SELECT * FROM notes WHERE id=$note_id"; ?>

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

Пофиксим проблему следующим образом:

<?php $id = $_GET['id']; $user_id = $_SESSION['id']; $query = "SELECT * FROM notes WHERE id=$id and user_id=$user_id"; ?>

Так мы будем показывать запись:

<?php $note = mysqli_fetch_assoc($res); if ($note) { // показываем } else { // попытка обращения к чужой // или несуществующей записи } ?>

Воспроизведите пример, приведенный в уроке. Проверьте наличие уязвимости. Устраните ее.

Проверьте, нет ли в нашем коде проблем с SQL-инъекциями. Если есть, устраните проблему.

В следующем пример автор кода выводит различные сообщения, когда запись несуществует и когда запись чужая:

<?php $id = $_GET['id']; $query = "SELECT * FROM notes WHERE id=$id"; $note = mysqli_fetch_assoc($res); if ($note) { $user_id = $_SESSION['id']; if ($note['user_id'] === $user_id) { // показываем запись var_dump($note); } else { echo 'запись с таким id вам не принадлежит'; } } else { echo 'запись с таким id нет'; } ?>

Объясните, почему так лучше не делать.