Как мне решить эту серьезную проблему?

Как улучшить защиту от SQL-инъекций в моем коде регистрации с использованием PDO? Я недавно обновил файл регистрации и теперь использую следующий код: <br/> <pre><code class="php">&lt;?php
	ini_set('display_errors', '1');
	ini_set('display_startup_errors', '1');
	error_reporting(E_ALL);
	session_start();
	require_once 'connect.php';

	$name = $_POST['name'];
	$surname = $_POST['surname'];
	$login = $_POST['username'];
	$password = $_POST['password'];
	$confirm_password = $_POST['confirm_password'];

	$check_username = $connect-&gt;prepare("SELECT `username` FROM `users` WHERE `username` = ':login'");
	$check_username-&gt;bindParam(':login', $login);
	$check_username-&gt;execute();

	if (mysqli_num_rows($check_username) &gt; 0) { 
		$_SESSION['err_message'] = 'Такой логин уже занят'; 
		header('Location: ../register.php'); 
	} else {
		if ($password != $confirm_password) {
			$_SESSION['err_message'] = 'Пароли не совпадают!'; 
			header('Location: ../register.php'); 
		} else {
			if (empty($name) or empty($surname) or empty($login) or empty($password) == true) {
				$_SESSION['err_message'] = 'Все поля должны быть заполнены!'; 
				header('Location: ../register.php'); 
			} else {
				if (preg_match('/^(?=.*[a-zA-Z])[a-zA-Z0-9]+$/i', $login)) {
					if (strlen($password) &lt; 5 or strlen($password) &gt; 30) {
						$_SESSION['err_message'] = 'Пароль не может быть короче 5 символов или длиннее 30'; 
						header('Location: ../register.php'); 
					} else { 
						$query = $connect-&gt;prepare("INSERT INTO `users` (`id`, `name`, `surname`, `username`, `password`) VALUES (NULL, ':name', ':surname', ':login', ':password')");
						$query-&gt;bindParam(':name', $name);
						$query-&gt;bin
  • 18 марта 2025 г. 13:04
Ответы на вопрос 1
Ваш код имеет несколько уязвимостей, которые могут привести к SQL-инъекциям, а также к неправильному поведению. Давайте разберем ваш код и внесем необходимые изменения для повышения безопасности.

1. **Использование параметризованных запросов**: Параметры должны быть переданы без кавычек в SQL-запросе. Например, вам нужно удалить кавычки вокруг параметров в запросах `SELECT` и `INSERT`.

2. **Проверка на наличие пользователя**: Используйте `fetch()` вместо `mysqli_num_rows()` для получения данных и проверки.

3. **Хэширование паролей**: Никогда не храните пароли в открытом виде. Вместо этого используйте функции `password_hash` для хэширования пароля перед его сохранением.

Вот исправленный код:

```php
<?php
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
error_reporting(E_ALL);
session_start();
require_once 'connect.php';

$name = $_POST['name'];
$surname = $_POST['surname'];
$login = $_POST['username'];
$password = $_POST['password'];
$confirm_password = $_POST['confirm_password'];

// Проверяем, что логин уже существует
$check_username = $connect->prepare("SELECT `username` FROM `users` WHERE `username` = :login");
$check_username->bindParam(':login', $login);
$check_username->execute();

if ($check_username->fetch()) { 
    $_SESSION['err_message'] = 'Такой логин уже занят'; 
    header('Location: ../register.php'); 
    exit();
} else {
    if ($password != $confirm_password) {
        $_SESSION['err_message'] = 'Пароли не совпадают!'; 
        header('Location: ../register.php'); 
        exit();
    } else {
        if (empty($name) || empty($surname) || empty($login) || empty($password)) {
            $_SESSION['err_message'] = 'Все поля должны быть заполнены!'; 
            header('Location: ../register.php'); 
            exit();
        } else {
            if (preg_match('/^(?=.*[a-zA-Z])[a-zA-Z0-9]+$/i', $login)) {
                if (strlen($password) < 5 || strlen($password) > 30) {
                    $_SESSION['err_message'] = 'Пароль не может быть короче 5 символов или длиннее 30'; 
                    header('Location: ../register.php'); 
                    exit();
                } else { 
                    // Хэшируем пароль
                    $hashed_password = password_hash($password, PASSWORD_DEFAULT);

                    // Вставляем нового пользователя
                    $query = $connect->prepare("INSERT INTO `users` (`name`, `surname`, `username`, `password`) VALUES (:name, :surname, :login, :password)");
                    $query->bindParam(':name', $name);
                    $query->bindParam(':surname', $surname);
                    $query->bindParam(':login', $login);
                    $query->bindParam(':password', $hashed_password);
                    $query->execute();

                    // Перенаправляем на страницу успеха или логина
                    header('Location: ../success.php'); 
                    exit();
                }
            } else {
                $_SESSION['err_message'] = 'Логин может содержать только буквы и цифры.'; 
                header('Location: ../register.php'); 
                exit();
            }
        }
    }
}
?>
```

### Объяснение внесенных изменений:

1. **Удалены кавычки** вокруг параметров в SQL-запросах, чтобы обеспечить корректное использование параметризованных запросов.
2. **Использование `fetch()`** для проверки, существует ли пользователь с таким логином.
3. **Добавлено хэширование пароля** с помощью `password_hash`, что делает хранение паролей безопаснее.
4. **Добавлены вызовы `exit()`** после `header()`, чтобы предотвратить выполнение последующего кода.

Эти изменения помогут улучшить безопасность вашего кода регистрации и защитят вашу базу данных от SQL-инъекций.
Похожие вопросы