在编写 PHP 代码时,牢记以下安全漏洞非常重要,以避免编写不安全的代码。
这些是您在编写 PHP 代码时会遇到的常见漏洞。我们将在下面更深入地讨论一些。
现在让我们更详细地了解一些常见的漏洞。
会话劫持是由攻击者获得对用户会话标识符的访问权并能够使用另一个用户的帐户来冒充他们而导致的漏洞。这通常用于访问管理用户的帐户。
要防御会话劫持攻击,您需要根据存储的会话信息检查当前用户的浏览器和位置信息。下面是一个示例实现,可以帮助减轻会话劫持攻击的影响。它会检查 IP 地址、用户代理以及会话是否已过期,在会话恢复之前删除会话。
- session_start();
-
- // Does IP Address match?
- if ($_SERVER['REMOTE_ADDR'] != $_SESSION['ipaddress'])
- {
- session_unset();
- session_destroy();
- }
-
- // Does user agent match?
- if ($_SERVER['HTTP_USER_AGENT'] != $_SESSION['useragent'])
- {
- session_unset();
- session_destroy();
- }
-
- // Is the last access over an hour ago?
- if (time() > ($_SESSION['lastaccess'] + 3600))
- {
- session_unset();
- session_destroy();
- }
- else
- {
- $_SESSION['lastaccess'] = time();
- }
Cross Site Scripting 是 Web 应用程序中的一种漏洞,由程序员在将输入输出到 Web 浏览器(例如博客上的评论)之前没有清理输入而导致。它通常用于在 Web 浏览器中运行恶意 javascript 来进行攻击,例如窃取会话 cookie 等恶意行为,以在 Web 应用程序中获得更高级别的权限。
博客允许用户使用 HTML 标签设置他们的评论样式,但是支持博客的脚本不会去除标签,允许任何用户在页面上运行 javascript。攻击者可以利用这一点在浏览器中运行恶意 javascript。他们可以用恶意软件感染用户、窃取会话 cookie 等等。
- alert('Cross Site Scripting!');
在 PHP 中有两个主要功能,htmlspecialchars()和strip_tags(),内置以保护自己免受跨站点脚本攻击。
该htmlspecialchars($string)函数将阻止 HTML 字符串呈现为 HTML,并将其作为纯文本显示给 Web 浏览器。htmlspecialchars() 代码示例
- $usercomment = "
alert('Cross Site Scripting!');" ; - echo htmlspecialchars($usercomment);
另一种方法是strip_tags($string, $allowedtags)删除除您列入白名单的 HTML 标记之外的所有 HTML 标记的函数。请务必注意,使用该strip_tags()功能时您必须更加小心,此功能不会阻止用户将 javascript 作为链接包含在内,您必须自行对其进行清理。
strip_tags() 代码示例
- $usercomment = "
alert('Cross Site Scripting!');" ; - $allowedtags = ";
- echo strip_tags($usercomment, $allowedtags);
设置 X-XSS-Protection 标头:
在 PHP 中,您可以发送X-XSS-ProtectionHeader,它会告诉浏览器检查反射的跨站点脚本攻击并阻止页面加载。这并不能阻止所有的跨站点脚本攻击,只是反射攻击,应该与其他方法结合使用。
- header("X-XSS-Protection: 1; mode=block");
编写自己的清理函数如果您想更好地控制清理工作的方式,另一种选择是编写自己的 HTML 清理函数,不建议 PHP 初学者这样做,因为错误会使您的网站易受攻击。
防止跨站点脚本攻击(可能需要对 Web 应用程序的设计和代码库进行大量调整)的有效方法是使用内容安全策略。
将内容安全策略设置为 HTTP 标头
设置内容安全策略的最常见方法是直接在 HTTP 标头中设置。这可以由 Web 服务器通过编辑其配置或通过 PHP 发送来完成。
HTTP 标头中设置的内容安全策略示例
- header("content-security-policy: default-src 'self'; img-src https://*; child-src 'none';");
将内容安全策略设置为元标记
您可以在页面的 HTML 中包含您的内容安全策略,并逐页设置。此方法要求您在每个页面上进行设置,否则您将失去该策略的好处。
HTML 元标记中设置的内容安全策略示例
- "Content-Security-Policy" content="default-src 'self'; img-src https://*; child-s
SQL 注入是应用程序中的一个漏洞,它是由于程序员在将输入包含到数据库的查询中之前没有对其进行清理而导致的。这导致攻击者拥有对数据库的完全读取权限,并且往往没有写入权限。通过这种类型的访问,攻击者可以做非常糟糕的事情。
下面的 PHP 脚本运行一个 SQL 语句以通过 ID 获取用户的电子邮件。但是输入没有经过过滤,使其容易受到 SQL 注入的影响
- $input = $_GET['id'];
- $dbserver = "localhost";
- $dbuser = "camper";
- $dbpass = "supersecretcampsitepassword";
- $dbname = "freecodecamp";
-
- $conn = new mysqli($dbserver, $dbuser, $dbpass, $dbname);
-
- if ($conn->connect_error) {
- die("Connection failed: " . $conn->connect_error);
- }
-
- $sql = "SELECT email FROM users WHERE id =" . $input;
-
- $result = $conn->query($sql);
-
- if ($result->num_rows > 0) {
- while($row = $result->fetch_assoc()) {
- echo $row["email"];
- }
- } else {
- echo "no results";
- }
-
- $conn->close();
SELECT email FROM users WHERE id = `$input`;
因此,上面的输入不是类型转换的(即用 (int) 转换输入,所以只允许一个数字)也不是转义允许某人执行 SQL 注入攻击 - 例如,URLgetemailbyuserid.php?id=1'; My Query Here-- -将允许您运行任意 SQL 查询一点点努力。
有几种方法可以保护您的网站免受 SQL 注入攻击。这些方法是白名单、类型转换和字符转义
白名单:白名单方法用于只需要少量输入的情况。您可以在 PHP Switch 中列出每个预期的输入,然后为无效输入设置默认值。您不必担心类型转换问题或字符转义绕过,但允许的输入非常有限。它仍然是一个选项,请参见下面的示例。
- switch ($input) {
- case "1":
- //db query 1
- break;
- case "2":
- //db query 2
- break;
- default:
- // invalid input return error
- }
类型转换:类型转换方法通常用于使用数字输入的应用程序。只需将输入转换为,(int) $input并且只允许使用数字值。
字符转义:字符转义方法将对用户提供的引号和斜杠等字符进行转义,以防止攻击。如果您使用 MySQL 服务器和 MySQLi 库来访问您的数据库,该mysqli_real_escape_string($conn, $string)函数将采用两个参数,即 MySQLi 连接和字符串,并将正确地转义用户的输入以阻止 sql 注入攻击。您使用的确切功能取决于您使用的数据库类型和 php 库,请查看 php 库的文档以获取有关转义用户输入的更多信息。