保护 PHP 应用程序免受 SQL 注入攻击

保护 php 应用程序免受 sql 注入攻击

阻止 sql 注入攻击对于维护 php 应用程序的安全至关重要。 sql 注入是一个漏洞,允许攻击者在您的数据库上执行任意 sql 代码,可能导致数据泄露或丢失。这是防止 php sql 注入攻击的分步指南,配有实践示例和说明。

1.了解 sql 注入

当用户输入未正确清理并合并到 sql 查询中时,就会发生 sql 注入。例如,如果用户输入恶意 sql 代码,它可能会操纵您的查询来执行意外操作。

sql 注入示例:

// vulnerable code
$user_id = $_get['user_id'];
$query = "select * from users where id = $user_id";
$result = mysqli_query($conn, $query);

如果 user_id 设置为 1 or 1=1,则查询变为:

select * from users where id = 1 or 1=1

此查询将返回 users 表中的所有行,因为 1=1 始终为 true。

2.使用准备好的语句

准备好的语句是防御 sql 注入的关键。它们将 sql 逻辑与数据分开,并确保用户输入被视为数据而不是可执行代码。

mysqli 与准备好的语句结合使用:

  1. 连接到数据库
   $conn = new mysqli("localhost", "username", "password", "database");

   if ($conn->connect_error) {
       die("connection failed: " . $conn->connect_error);
   }
  1. 准备sql语句
   $stmt = $conn->prepare("select * from users where id = ?");
  1. 绑定参数
   $stmt->bind_param("i", $user_id); // "i" indicates the type is integer
  1. 执行语句
   $user_id = $_get['user_id'];
   $stmt->execute();
  1. 获取结果
   $result = $stmt->get_result();
   while ($row = $result->fetch_assoc()) {
       // process results
   }
  1. 关闭语句和连接
   $stmt->close();
   $conn->close();

完整示例

<?php // database connection
$conn = new mysqli("localhost", "username", "password", "database");

if ($conn->connect_error) {
    die("connection failed: " . $conn->connect_error);
}

// prepare statement
$stmt = $conn->prepare("select * from users where id = ?");
if ($stmt === false) {
    die("prepare failed: " . $conn->error);
}

// bind parameters
$user_id = $_get['user_id'];
$stmt->bind_param("i", $user_id);

// execute statement
$stmt->execute();

// get results
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
    echo "user id: " . $row['id'] . "<br>";
    echo "user name: " . $row['name'] . "<br>";
}

// close statement and connection
$stmt->close();
$conn->close();
?>

3.将 pdo 与准备好的语句结合使用

php 数据对象 (pdo) 提供类似的针对 sql 注入的保护并支持多个数据库系统。

pdo 与准备好的语句结合使用:

  1. 连接到数据库
   try {
       $pdo = new pdo("mysql:host=localhost;dbname=database", "username", "password");
       $pdo->setattribute(pdo::attr_errmode, pdo::errmode_exception);
   } catch (pdoexception $e) {
       die("connection failed: " . $e->getmessage());
   }
  1. 准备sql语句
   $stmt = $pdo->prepare("select * from users where id = :id");
  1. 绑定参数并执行
   $stmt->bindparam(':id', $user_id, pdo::param_int);
   $user_id = $_get['user_id'];
   $stmt->execute();
  1. 获取结果
   $results = $stmt->fetchall(pdo::fetch_assoc);
   foreach ($results as $row) {
       echo "user id: " . $row['id'] . "<br>";
       echo "user name: " . $row['name'] . "<br>";
   }

完整示例

<?php try {
    // Database connection
    $pdo = new PDO("mysql:host=localhost;dbname=database", "username", "password");
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    // Prepare statement
    $stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id");

    // Bind parameters
    $user_id = $_GET['user_id'];
    $stmt->bindParam(':id', $user_id, PDO::PARAM_INT);

    // Execute statement
    $stmt->execute();

    // Fetch results
    $results = $stmt->fetchAll(PDO::FETCH_ASSOC);
    foreach ($results as $row) {
        echo "User ID: " . $row['id'] . "<br>";
        echo "User Name: " . $row['name'] . "<br>";
    }

} catch (PDOException $e) {
    die("Error: " . $e->getMessage());
}
?>

4.其他安全实践

  • 清理输入:始终清理和验证用户输入,以确保它们采用预期的格式。
  • 使用 orm:像 eloquent (laravel) 这样的对象关系映射器在内部处理 sql 注入保护。
  • 限制数据库权限:对数据库用户帐户使用最小权限原则。

5.结论

阻止 sql 注入攻击对于保护 php 应用程序至关重要。通过将准备好的语句与 mysqli pdo 一起使用,您可以确保用户输入得到安全处理,而不是作为 sql 查询的一部分执行。遵循这些最佳实践将有助于保护您的应用程序免受最常见的 web 漏洞之一的影响。

以上就是保护 PHP 应用程序免受 SQL 注入攻击的详细内容,更多请关注其它相关文章!