如何在 PHP 中防止 XSS

如何在 PHP 中防止 XSS

XSS 漏洞是网络上最流行的安全问题之一。不幸的是,即使新的开发技术已经尽力消除这个漏洞,它仍然存在于所有新旧应用程序中。为防止任何开发技术中的 XSS 漏洞,用户的输入应在显示在 Web 应用程序中之前进行过滤。

在本文中,我将详细解释在 PHP 代码中防止此特定漏洞的正确方法。我将为您提供实际示例,说明如何在每个流行的 PHP 开发框架中执行此操作。以下是这些框架的列表:

  • PHP
    • Laravel
    • Symfony
    • CodeIgniter
    • CakePHP
    • FuelPHP
    • Zend

在我们开始深入研究如何修复和防止此漏洞之前,我想提供一些我相信大多数人不了解 XSS 漏洞影响的信息。

如果您熟悉此漏洞并且只想了解如何在您正在使用的技术中修复它,那么请忽略以下段落并直接转到您想要的技术。但是,相信我,我强烈建议您继续阅读我很确定您不了解以下信息。

XSS 是一个漏洞,包括将恶意 Javascript 代码注入到合法网页中。当代码在将用户输入显示在合法页面上之前未过滤用户输入时,就会出现此漏洞。

XSS 漏洞可分为三种类型:

  • XSS 存储
  • XSS 反映
  • 基于 XSS DOM

这三种类型的最大区别在于,在存储的 XSS 中,用户数据保存在数据库中,这与反射和基于 DOM 的 XSS 漏洞相反。现在,对于反射的 XSS 和基于 DOM 的 XSS 漏洞,尊重与数据流有关。

在基于 DOM 的 XSS 中,浏览器处理从源到接收器的整个污染数据流,这与反射型 XSS 相反。

现在,当我问我的大多数客户和学生,这个漏洞的影响是什么时,他们不断地告诉我,比如窃取用户信息、控制应用程序等等,仅此而已。不幸的是,这并不是这个漏洞所能做的全部。在某些情况下,影响可能与控制服务器或客户端计算机一样严重。

这不容易接受,但相信我,这是真的。如果您想要一些关于这方面的真实示例,那么我强烈建议您查看我的博客文章,了解OWASP TOP 10 漏洞的真正影响。

现在您已经了解了此漏洞的严重程度,让我们看看如何修复它。

如何在 PHP 中防止 XSS 攻击

在讨论如何在 PHP 框架中修复此漏洞之前,让我们先看看如何在纯 PHP 源代码中修复它。

要修复 PHP 源代码中的 XSS 漏洞,您需要使用 htmlspecialchars 过滤用户输入,参数为 ENT_QUOTES 和 'UTF-8'。

以下是易受攻击的代码示例:

<?php echo $_GET[‘name’];?>

为了修复这个漏洞,大多数人编写以下代码:

<?php echo htmlspecialchars($_GET[‘name’]);?>

不幸的是,这不是修复此漏洞的正确方法。使用没有正确参数的 htmlspecialchars 可以通过一些高级技术绕过,这意味着漏洞将保留在应用程序中。

要修复此代码,您需要做的就是使用带有以下参数的 htmlspecialchars 过滤用户输入:

<?php echo htmlspecialchars($_GET[‘name’],ENT_QUOTES,’UTF-8’);?>

甚至以下示例也存在漏洞,需要 htmlspecialchars 函数:

<?=$_GET[‘name’]?>

以下是解决方法:

<?=htmlspecialchars($_GET[‘name’],ENT_QUOTES,’UTF-8’)?>

使用带有所需参数的 htmlspecialchars 并不总能保护您的 php 代码,您需要将其与其他功能结合使用。

这是这种情况的一个例子:

<a href=”<?php echo htmlspecialchars($_GET[‘userURL’]);?>”>Click here</a >

为了防止这种情况下的 XSS 漏洞,您需要将 htmlspecialchars 与 urlencode() 函数结合使用。以下是此类使用的示例:

<a href=”<?php echo urlencode(htmlspecialchars($_GET[‘userURL’]));?>”>Click here</a >

如何在 Laravel 中防止 XSS 攻击

Laravel 是最流行的 PHP 框架之一,我使用过的大多数客户端都使用它来制作 Web 应用程序。因此,我能够找到多种可能发生 XSS 漏洞的情况,即使该框架已经保护了应用程序免受此类攻击。

实际上,显示用户输入的 {{ $data }} 方式并不总是安全的,即使这种技术过滤了 HTML 标签。

以下是 laravel 代码易受攻击的一些情况:

  • 创建动态 URL 时

当您创建动态 URL 并将其注入“a”标签的“href”属性时,使用如下用户输入:

<a href="{{$userData}}" >Click here</a>

在这种情况下,即使 {{ }} 保护过滤了 $userData 变量,攻击者仍然有可能注入不包含任何 html 标签的恶意 Javascript 代码来利用该漏洞。我不会给出这种利用的例子,因为这不是本文的目的。

以下是修复此代码的方法:

<a href="{{ urlencode($userData) }}" >Click here</a>
  • 使用 {!!$data !!} 声明

Laravel 提供了这个声明,让开发人员可以在内部显示带有 HTML 标签的数据。但是,如果使用此语句显示用户输入,那么他将能够注入恶意 javascript 代码。

永远不要让用户发送 HTML 标记并显示它们。如果您想要这样的可能的文本格式或……,然后创建您自己的虚拟标签,然后在过滤这些标签之间的用户数据时转换它们。

  • 使用自定义指令时

Laravel 还提供了创建自己的指令的可能性,如下所示:

public function boot()
{
Blade::directive('testDirective', function ($userInput) {
return "<?php echo $userInput;?>";
});
}

此代码易受 XSS 攻击,因为用户数据未经任何过滤直接显示。要解决此问题,您需要将 htmlspecialchars() 与所需参数一起使用,如果您在 URL 中使用用户数据,则将其与 urlencode() 函数结合使用。

这是一个例子:

public function boot()
{
Blade::directive('testDirective', function ($userInput) {
return "<?php echo htmlspecialchars($userInput,ENT_QUOTES,’UTF-8’);?>";
});
}
  • 使用事件属性时

正如您在 a.href 属性中看到的那样,XSS 漏洞仍然存在。在更一般的情况下,如果您使用一些用户输入而不过滤事件属性,如下例所示:

<p onclick="{{$userData}}" >paragraph</p>

即使您使用显示用户输入的 {{ }} 技术,代码仍将易受攻击。为了防止这种情况下的 XSS 漏洞,您需要在使用前过滤用户输入。

但是,这种情况很难修复,而且在代码中也很少见。我强烈建议不要让用户直接将他的输入注入到上一个示例中的偶数属性中。

如何在 Symfony 中防止 XSS 攻击

为了防止基于 Symfony 的应用程序中的 XSS 漏洞,用户输入需要在显示在合法网页上之前进行转义。这个框架提供了许多技术来防止像 laravel 这样的 XSS 漏洞,我们将在接下来的段落中看到这一点。

为了生成一个 html 页面,Symfony 提供了两种类型的模板:

  • 树枝模板

第一个也是最推荐的一个是 Twig。在 Twig 模板中,默认情况下,输出会在注入 HTML 页面之前进行过滤。这可以保护源代码免受任何可能的 XSS 漏洞的影响。但是,如果开发人员已经信任输出,该框架提供了一种禁用此过滤的方法 。这是一个例子:

{{ article.body|raw }}

为了能够使用此技术,您需要 100% 确定 article.body 变量中的内容已被过滤。

  • PHP 模板

不幸的是,默认情况下 PHP 模板中未启用此转义选项。所以编写以下代码:

My name is : <?=$name ?>

使应用程序易受 XSS 攻击。

要修复此漏洞,您需要在显示 $name 变量之前使用 escape() 函数对其进行转义。这是一个例子:

Hello <?= $view->escape($name) ?>

默认情况下,转义函数假定您在 HTML 上下文中显示此数据。如果您查看 PHP 或 Laravel 讨论的 XSS 漏洞,您会注意到即使使用 htmlspecialchars(),如果数据用于某些类型的属性,源代码仍然容易受到攻击。因此,为了在这种情况下保护您的源代码,您需要根据数据的上下文更改函数参数。

以下是在 Javascript 代码中使用用户数据的示例:

var name = '<?= $view->escape($name, 'js') ?>';

如何在 CodeIgniter 中防止 XSS 攻击

CodeIgniter 是一个强大、轻量且流行的 PHP 框架,占用空间小。它是为需要基本而优雅的工具包来构建功能齐全的 Web 应用程序的开发人员创建的。为了防止 Codeigniter Web 应用程序中的 XSS 攻击,需要在检索所有用户输入时添加第二个参数“True”。

但是,在大多数情况下,开发人员不知道或忘记了第二个参数,这使应用程序容易受到 XSS 漏洞的攻击。

以下是易受攻击的源代码示例:

echo $this->input->post('name');

直接向用户显示 post 变量“name”,使该代码容易受到 XSS 漏洞的攻击。实际上,在 Codeigniter 中解决这个问题真的很容易。您需要做的就是添加前面提到的第二个参数。

以下是如何修复此代码的示例:

echo $this->input->post('name',TRUE);

添加 TRUE 参数,要求 Codeigniter 在将用户输入注入 HTML 网页之前对其进行过滤。此外,Codeigniter 提供了一种更简单(但不推荐)的数据过滤方式。实际上,输入类提供了通过将变量 global_xss_filtering 设置为 true 来直接在所有 Web 应用程序中自动进行过滤的可能性。

为此,您需要做的就是修改路径中的文件:

应用程序/config/config.php

通过将 global_xss_filtering 变量的值更改为 TRUE,如下所示:

$config['global_xss_filtering'] = TRUE;

实际上,您可能会注意到,在 Codeigniter 部分中,我没有讨论属性问题,我已经在其他框架中讨论过。这背后的原因是,Codeigniter 的工作方式以及其功能的开发方式使其即使在这些情况下也非常安全。

我对 Codeigniter 源代码进行了小型逆向工程,这就是我的发现。

通过执行 get()、post() 和其他用户的输入函数,我注意到它们调用了 xss_clean() 函数。此函数是名为 Security 的类的一部分。

如何在 PHP 中防止 XSS

通过分析这个类和这个函数,我发现这个函数不像其他框架的过滤函数那样工作。在这里,该函数对用户输入执行一些精确的操作,以仅过滤危险数据。因此,此功能将保护您的应用免受此类攻击技术的侵害

这个类实际上为其他漏洞提供了其他保护,我将在下一篇文章中解释,值得分析。

如何在 CakePHP 中防止 XSS 攻击

CakePHP 是业内优秀的 PHP 框架之一,我真的很幸运能与一些优秀的开发人员一起工作。其中一些开发人员告诉我,该框架实际上会自动过滤用户输入,因此我们不需要执行该操作。

老实说,我不知道 CakePHP 是如何执行此操作的,我可能会对框架进行逆向工程以找到对我的问题的详细回答,但现在,让我们坚持我所确定的。

下面是一个易受攻击的 CakePHP 源代码示例:

<?=$username ?>

现在,要保护此源代码,您需要做的就是调用 h() 函数。该函数负责过滤用户输入并使其安全。

以下是如何解决此问题的示例:

<?=h($username) ?>

但是,该函数使用 htmlspecialchars() 过滤数据,正如我们在前面部分中讨论的那样,仍然容易受到属性注入的攻击。所以不要犹豫,根据情况添加更多功能来过滤这些数据。

FuelPHP中如何防止XSS攻击

Fuel PHP 框架是最快和最简单的 PHP 框架之一,它诞生于以前框架的最佳概念。这意味着该框架的开发人员也确实关心生成的源代码的安全性。为了防止对 FuelPHP 框架的 XSS 攻击,在显示用户输入时应使用函数 xss_clean()。

事实上,您甚至可以通过将以下路径中存在的参数“security”更改为:app/config/config.php 来自动化这个过程

'security' => array(
'input_filter' => array(‘Security::xss_clean’),
)

默认情况下不启用输入自动过滤选项

但是,并不真正推荐这种自动化技术,因为您的 Web 应用程序的性能会下降。我实际上建议我的客户使用 xss_clean 函数,只过滤将在某处显示的用户数据。

FuelPHP 中的易受攻击代码如下所示:

 echo Input::param('username');

这段代码容易受到 XSS 攻击,因为用户输入直接显示,没有任何过滤。

要修复此代码,您只需调用 xss_clean() 函数,如下例所示:

 echo Security::xss_clean(Input::param('username'));

xss_clean 函数实际上和 Codeigniter xss_clean 函数做的工作是一样的,也就是说这里也不存在属性问题。

Zend中如何防止XSS攻击

Zend 也是一个著名的 PHP 框架,可作为一个开源项目使用。Zend 引入了基于同行评审规则的上下文转义,允许开发人员转义输出并防御 XSS 和其他漏洞。

为了防止 Zend 中的 XSS 攻击,用户输入需要根据上下文通过以下函数之一进行转义:

  • 转义HTML
  • escapeHtmlAttr
  • 逃逸
  • 转义CSS
  • 转义网址

这些函数是名为Zend\Escaper\Escaper的转义类的一部分。根据用户数据的显示位置,您应该使用正确的函数。以下是一些如何使用它的示例:

  • 易受攻击的代码
span {
color: <?php echo $val['userFontColor']; ?>
}
  • 正确使用函数
span {
color: <?php echo $this->escapeCss($val['userFontColor']); ?>
}
  • 易受攻击的代码
<input type=”text” value=”<?php echo $val['user']; ?>” >
  • 正确使用函数
<input type=”text” value=”<?php echo $this->escapeHtmlAttr($val['user']); ?>” >

就个人而言,我真的很喜欢 Zend 团队处理这个问题的方式。将过滤分成多种情况不会对源代码执行产生明显影响。此外,专注于可能使用的利用技术实际上并不是一个好主意,因为没有人知道将来是否会出现新技术。

我并不是说其他​​框架提出的解决方案不起作用,但对我来说,Zend 解决方案是最好的。

我真的尽我所能涵盖所有最流行的 PHP 框架,以帮助人们保护他们的应用程序。但是,如果您发现我可能会遗漏一些其他 PHP 框架,请在下方留言,我将非常乐意添加此框架

                       

点击阅读全文

上一篇 2023年 6月 5日 am10:52
下一篇 2023年 6月 5日 am10:54