[2] - Безопасный PHP. Защита от SQL-Injection

[2] - Безопасный PHP. Защита от SQL-Injection

@webware

t.me/webware

Всем Салам и всех с Новым Годом. Праздники праздниками, но знания получать нужно, чем мы сейчас займемся. Как вы уже знаете по названию, сегодня мы будем разбирать SQL-Injection в PHP. Как подметили в прошлой статье про XSS, что XSS тематика обширная и не все рассмотрено.


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


[0] - SQL-Injection. Что такое?

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


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

https://www.root-me.org/en/Challenges/Web-Server/SQL-injection-numeric

Как мы видим у нас тут есть какой-то CMS и какие-то ссылки. Ну для начала тупо тыкаем по ссылкам.

И видим сразу, в базу передаются данные GET запросом, и если тыкнуть кавычку, то запрос рушится и получаем ошибку. Произошло из-за того, что запросы не экранируются, а напрямую передаются в БД.

Теперь определим количество полей и будем получать данные с помощью UNION, т.е. объединения запросов из БД. И как видим ниже, количество полей =< 3

В итоге получаем админский доступ.

[1] - Эксплуатация SQL-Injection в PHP

На данный момент безопасно мы можем коннектится к БД и проводить с ним определенные манипуляции с помощью PDO или MySQLI. Разберем оба момента.


[1.1] - PDO

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

$id = $_GET['id'] ?? 'Пусто';
$connect = new PDO('mysql:dbname=codeby;host=localhost', 'root', '');
$sql = "SELECT username, password FROM codeby_sql WHERE id = " . $id;
foreach ($connect->query($sql) as $row) {
    echo 'Username: ' .$row['username']. '<br>';
    echo 'Password: ' .$row['password'];

[1.2] - MySQLI

Теперь рассмотрим уязвимость, если MySQLI.

$id = $_GET['id'] ?? 'Пусто';
$connect = new mysqli('localhost', 'root', '', 'codeby');
if ($connect->connect_error) {
    die($connect->connect_errno);
}
$query = "SELECT username, password FROM codeby_sql WHERE id = " . $id;
foreach ($connect->query($query) as $row) {
        echo 'Username: ' .$row['username']. '<br>';
        echo 'Password: ' .$row['password'];
}


И думаю вы понимаете, что может произойти, если злоумышленник получает доступ к нашему БД, тупо удалить все и еще многое другое.


[2] - Как обезопасить PHP от SQL-Injection

Также рассмотрим варианты закрытия этих уязвимостей. И сразу скажу, что экранировать мы наши запросы будем с помощью хранимых процедур (prepared statements)

[2.1] - PDO

Код:

$id = $_GET['id'] ?? 'Пусто';
$connect = new PDO('mysql:dbname=codeby;host=localhost', 'root', '');
$sql = "SELECT username, password FROM codeby_sql WHERE id = :id";
$sth = $connect->prepare($sql, [PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY]);
$sth->execute([':id' => $id]);
while ($row = $sth->fetch()) {
    echo 'Username: ' .$row['username']. '<br>';
    echo 'Password: ' .$row['password'];
}
}

Как видим, какие либо SQL запросы и кавычки и все остальное у нас фильтруются.

[2.2] - MySQLI


В MySQLI, для этого у PHP имеется своя функция mysqli_real_escape_string(), почти нас защищает, но все-таки тут также лучше использовать хранимые процедуры.

$id = $_GET['id'] ?? 'Пусто';
$connect = new mysqli('localhost', 'root', '', 'codeby');
$query = "SELECT username, password FROM codeby_sql WHERE id = ?";
$sth = $mysqli->stmt_init();
if ($sth->prepare($query)) {
    $sth->bind_param("i", $id);
    $sth->execute();
    $result = $sth->get_result();
    while ($row = $result->fetch_array(MYSQLI_NUM)) {
        echo 'Username: ' .$row['username']. '<br>';
        echo 'Password: ' .$row['password'];
    }
}

На этом наверное у нас все, если интересуют какие-то отдельные моменты, то можете писать в комментах

В конце как и говорил, выложу список ссылок для подробного изучения SQL-Injection.

И забыл упомянуть, что нужно иметь какие-то базовые знания по SQL.

Подробности:

  1. Серия статей SQL-Injection для начинающих: https://habrahabr.ru/post/148151/
  2. Мощный, полный мануал по эксплуатации: https://rdot.org/forum/showthread.php?t=124
  3. По SQL мне сильно нравится: http://2sql.ru/
  4. Для тренировки можете использовать: root-me.org, alexbers.com/sql/, habrahabr.ru/post/250551/, dvwa.co.uk

Для понимания того, как мы экранируем запросы:

Всем удачи. И профита в Новом году!

Источник codeby.net

Report Page