这是世界上最不安全的代码。
要点:
对 PHP 的一个常见批评是其安全性不足。令人遗憾的是,我们无法反驳这一点。这种批评过于宽泛,几乎可以套用到所有编程语言上,因为大多数语言都存在泄露机密信息的途径。现代 PHP 和现代编码实践旨在缓解这个问题。但今天,我们将探讨一个非常基本的安全漏洞示例,以及一种缓解方法。如果我们不运行 Web 服务器,但仍然将 PHP 文件公开,就会出现这种情况。
假设我们有一个index.php位于公共文件夹中的文件。该文件用于保护秘密圣诞老人的身份,直到圣诞节当天。它看起来像这样:
<?php
define('SECRET_SANTA', "Olaf ⛄");
?>
<!DOCTYPE html>
<html lang="en">
<body>
<h1>The Secret Santa is a secret!</h1>
<p>You have to wait until Christmas Day to know who it is.</p>
<?php
$today = new DateTime("now");
$christmas = new DateTime("2021-12-25");
if ($today >= $christmas) {
echo "<p>The Secret Santa is " . SECRET_SANTA . "!</p>";
} else {
echo "<p>The Secret Santa is still a secret.</p>";
}
?>
</body>
</html>
只要我们有运行中的 Web 服务器服务(例如 Apache),这段代码就能被正确解析,并输出以下结果:
但如果服务宕机,而网站又有访客访问怎么办?我们不会解析 PHP 文件并渲染正确的输出,而是会把文件作为纯文本提供。所有代码都会暴露出来,任何人都能看出这是 Olaf!😱
那么我们该如何防止这种情况发生呢?我们可以将密钥从公共文件夹(或网站根目录)移到一个访客无法访问的文件夹中。假设我们有以下文件夹结构:
/
|-- public-folder
| |-- index.php
|
|-- private-folder
|-- SecretSanta.php
我们的访客将无法看到文件的内容SecretSanta.php,但他们可以看到这个index.php文件。以下是实现方法
。SecretSanta.php
<?php
class SecretSanta
{
private const SECRET_SANTA = 'Olaf ⛄';
public static function getSecretSanta(): bool|string
{
if ((new DateTime("now")) >= new DateTime("2021-12-25")) {
return self::SECRET_SANTA;
} else {
return false;
}
}
}
这个类声明了一个常量,用于存储秘密圣诞老人的身份信息。它是私有的,因此其他文件无法访问它。我们必须使用静态函数getSecretSanta()来访问秘密圣诞老人。如果当天是圣诞节当天或之后,此函数将返回秘密圣诞老人的身份信息;否则,它将返回空值false。
回到index.php文件,我们现在可以通过调用类上的静态函数来获取秘密圣诞老人SecretSanta::getSecretSanta():
<?php
require('../private/SecretSanta.php');
?>
<!DOCTYPE html>
<html lang="en">
<body>
<h1>The Secret Santa is a secret!</h1>
<p>You have to wait until Christmas Day to know who it is.</p>
<?php
if (SecretSanta::getSecretSanta()) {
echo "<p>The Secret Santa is " . SecretSanta::getSecretSanta() . "!</p>";
} else {
echo "<p>The Secret Santa is still a secret.</p>";
}
?>
</body>
</html>
当 Web 服务器服务运行时,我们仍然会得到与之前相同的输出,但现在我们可以看到,如果服务宕机,秘密圣诞老人活动将对公众不可见。这只是一个例子,说明将应用程序逻辑和密钥放在公共文件夹之外可能是一个好主意。
安全方面需要考虑的因素太多了,本文仅触及了冰山一角。而且,许多问题并非 PHP 特有,例如跨域资源伪造 (CSRF) 攻击、SQL 注入、跨站脚本攻击 (XSS) 等等。
你呢?
或许您对 PHP 生态系统中的安全实践有一些独到的见解,欢迎分享!您是否遇到过安全措施不完善的项目?对于正在构建最初几个 PHP 项目的 Web 开发人员,您有哪些最佳的安全建议?请在下方留言,分享您的想法✍
延伸阅读
- PHP 安全手册:https://www.php.net/manual/en/security.php
- Zend 谈如何处理安全风险:https://www.zend.com/blog/managing-security-risks-php-engine-and-web-applications