PHP安全:如何保护网站免受SQL注入和XSS攻击

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

您的PHP代码处于瞄准镜下:为什么沉默不是金

\n\n

想象一下:您上线了一个网站,一切运行顺畅,客户满意。而与此同时,在互联网的某个阴暗角落,一个脚本小子在您的搜索表单中输入了神奇的字符串 ' OR 1=1 --。数据库就像听话的仆人一样,将所有用户密码都交给了他。熟悉的故事吗?不幸的是,对于许多初级开发者来说,答案是肯定的。

\n\n

PHP安全不是枯燥的官僚主义,而是对您的时间、金钱和声誉的真正保护。今天我们来分析Web应用程序的两个主要敌人:SQL注入和跨站脚本攻击(XSS)。您将学习如何识别它们、消除它们,并确保它们永远不会再出现在您的代码中。

\n\n

SQL注入:当用户变成黑客

\n\n

SQL注入是一种攻击,攻击者通过输入字段“注入”恶意SQL代码。如果您只是简单地将用户数据插入查询中,那就等于您自己为窃贼打开了大门。

\n\n

易受攻击的代码长什么样

\n\n

这是一个经典的例子,至今仍出现在旧教材和实际运行的网站中:

\n\n
<?php\n// 危险!永远不要这样做\n$username = $_POST['username'];\n$password = $_POST['password'];\n\n$query = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";\n$result = mysqli_query($conn, $query);\n?>
\n\n

如果在username字段中输入 admin' -- 会发生什么?查询将变成:

\n\n
SELECT * FROM users WHERE username = 'admin' --' AND password = ''
\n\n

双破折号 -- 注释掉了查询的其余部分。瞧——攻击者无需密码就以管理员身份登录。如果输入 '; DROP TABLE users; -- 呢?再见,用户表。

\n\n

救生圈:预处理语句(Prepared Statements)

\n\n

防范SQL注入的最佳方法是使用预处理语句,通过PDO或MySQLi实现。它们将查询逻辑与数据分开,因此恶意代码永远不会被执行。

\n\n

以下是使用PDO的安全代码示例:

\n\n
<?php\n// 安全!使用预处理语句\n$username = $_POST['username'];\n$password = $_POST['password'];\n\n$stmt = $pdo->prepare("SELECT * FROM users WHERE username = :username AND password = :password");\n$stmt->execute(['username' => $username, 'password' => $password]);\n$user = $stmt->fetch();\n?>
\n\n

现在,即使攻击者传递 admin' OR 1=1 --,PDO也会将其视为普通字符串,而不是SQL命令的一部分。数据库会说:“正在查找具有这个奇怪用户名的用户。” 然后找不到。

\n\n

为什么选择PDO而不是mysql_*?

\n\n
    \n
  • 默认安全: PDO自动转义数据。
  • \n
  • 灵活性: 支持不同的数据库管理系统(MySQL, PostgreSQL, SQLite)。
  • \n
  • 命名占位符: 代码变得可读且可维护。
  • \n
  • 面向对象方法: 现代编程风格。
  • \n
\n\n

mysql_* 函数已在PHP 7.0中被移除,这是件好事。如果您仍然在使用 mysqli_real_escape_string —— 这总比没有好,但PDO仍然更可靠。

\n\n

XSS攻击:当代码隐藏在评论中

\n\n

跨站脚本攻击(XSS)是通过用户输入将JavaScript代码注入到页面中。想象一下:用户留下一条评论,但写的不是文字,而是:

\n\n
<script>alert('您的网站被黑了!');</script>
\n\n

如果您未经处理就直接输出,每个访问者都会看到一个弹出窗口。如果 alert 被替换成窃取Cookie或重定向到钓鱼网站的代码呢?

\n\n

XSS攻击的类型

\n\n
    \n
  • 反射型(Reflected): 恶意代

博客

书籍推荐