soosyze/kses

一个用 PHP 编写的 HTML/XHTML 过滤器。检查属性值。可以用来防止跨站脚本攻击(XSS)、缓冲区溢出和拒绝服务攻击等。

3.2.0 2022-12-08 18:40 UTC

This package is auto-updated.

Last update: 2024-09-10 20:51:45 UTC


README

Build Status Coverage Status GitHub Packagist PHP from Packagist

简介

欢迎来到 kses - 一个用 PHP 编写的 HTML/XHTML 过滤器。它会删除所有不需要的 HTML 元素和属性,无论你给出的 HTML 输入有多么不规范。检查属性值。可以用来防止跨站脚本攻击(XSS)、缓冲区溢出和拒绝服务攻击等。

通过 OWASP® 基金会提出的防止 XSS 攻击保护测试。

特性

kes 的当前特性包括

  • 它只允许它被明确告知允许的 HTML 元素和属性,
  • 元素和属性名称不区分大小写(a hrefA HREF),
  • 它能够正确理解和处理空白字符,
  • 属性值可以由引号、撇号或无引号包围,
  • 它可以接受只有名称没有值的属性(例如 selected),
  • 它可以接受 XHTML 的关闭标记 /
  • 无引号包围的属性值将得到引号以避免生成不符合 W3C 标准的 HTML,
    • 例如: <a href=http://foo.com> 可以工作,但不是有效的 HTML。
  • 它通过尽可能好地解释现有代码并从中重建新代码来处理大量的不规范 HTML 类型。这比尝试处理现有代码更好,因为你很可能会忘记某些奇怪的特殊情况。它优雅地处理问题,如无限循环引号和标签,
  • 它会删除人们可能试图偷偷放入的额外的 <> 字符,
  • 它支持检查属性值的最小/最大长度和最小/最大值,以保护客户端和服务器免受缓冲区溢出和拒绝服务攻击。例如,你可以阻止 <iframe src= width= height=> 宽度和高度的值过高,
  • 它有一个允许列表的 URL 协议系统。你可以指定属性值只能以 http:https:ftp:gopher: 开头,但不能有其他 URL 协议(例如 javascript:java:about:telnet: 等)。执行此操作的功能处理空白、大小写、HTML 实体(jav&#97;script:)和重复条目(javascript:javascript:alert(57)),
  • 它还可以作为副作用规范化 HTML 实体,
  • 它删除了 Netscape 4 的 JavaScript 实体 &{alert(57)};
  • 它处理 NULL 字节和 Opera 的 chr(173) 空白字符,
  • 提供标签和协议的允许列表。

要求

PHP 版本

安装

Composer

要通过 Composer 安装 Kses,您必须安装安装程序或二进制文件 Composer

转到您的项目目录,打开命令提示符并运行以下命令

composer require soosyze/kses --no-dev

或者,如果您使用二进制文件,

php composer.phar require soosyze/kses --no-dev

使用方法

在您的 PHP 网络应用程序中使用 kses 非常简单!基本用法如下

<?php

require __DIR__ . '/vendor/autoload.php';

use Soosyze\Kses\Xss;

$allowedTags = [
    'a'  => [
        'href'  => 1,
        'title' => 1
    ],
    'b'  => [],
    'br' => [],
    'i'  => [],
    'p'  => [
        'align' => 1
    ]
];

$allowedProtocols = [ 'http', 'https' ];

$xss = new Xss($allowed, $allowedProtocols);

$xss->filter('
    <h1>Lorem ipsum</h1>
    <p>Quisque sed ligula pulvinar, tempor dolor sit amet, placerat nisl.</p>
');

// Lorem ipsum
// <p>Quisque sed ligula pulvinar, tempor dolor sit amet, placerat nisl.</p>

这个$allowed的定义意味着只有biapbr元素(以及它们的结束标签/b/i/a/p/br)被允许。其中bibr不能有任何属性。a属性只能有hreftitle,而p属性只能有align。你可以以任意大小写混合形式在数组中列出元素和属性。kses也会识别使用大小写混合的HTML代码。

选择正确的允许属性非常重要,以免不小心打开XSS漏洞。一些不允许的重要属性包括但不限于:

  • 样式
  • 所有内嵌事件属性(如onMouseOver及其它onon*)。

还需要注意的是,kses的HTML输入必须清除所有来自魔法引号的斜杠。如果你的代码需要这些斜杠,可以在调用kses后通过简单的addslashes()调用再次添加它们。

与允许列表一起使用

标签和协议的授权列表可用

<?php

require __DIR__ . '/vendor/autoload.php';

use Soosyze\Kses\Xss;
use Soosyze\Kses\AllowedList;

$xss = new Xss();
/**
 * Similar to :
 * $xss = new Xss(AllowedList::getTags(), AllowedList::getProtocols());
 */

$xss->filter('<SCRIPT SRC=http://xss.rocks/xss.js></SCRIPT>');
// Result : ''

$xss->filter('<IMG SRC="javascript:alert(\'XSS\');">');
// Result : '<IMG src="alert(\'XSS\');">'

$xss->filter('\<a onmouseover=alert(document.cookie)\>xxs link\</a\>');
// Result : '\<a>xxs link\</a>'

kses属性值检查

正如你可能已经在README文件中看到的,$allowed_html数组通常如下所示

$allowed = [
    'a'  => [
        'href'  => 1,
        'title' => 1
    ],
    'b'  => [],
    'br' => [],
    'i'  => [],
    'p'  => [
        'align' => 1
    ]
];

这设置了允许哪些元素和属性。

从kses 0.2.0版本开始,你也可以对属性值执行一些检查。你可以这样操作

$allowed = [
    'a'    => [
        'href'  => [
            'maxlen' => 100
        ],
        'title' => 1
    ],
    'b'    => [],
    'br'   => [],
    'i'    => [],
    'p'    => [
        'align' => 1
    ],
    'font' => [
        'size' => [
            'maxval' => 20
        ]
    ]
];

这意味着kses应该在<a href=>值上执行maxlen检查,其值为100,以及在<font size=>值上执行maxval检查,其值为20。

目前实现的检查(还有更多)包括maxlenmaxvalminlenminvalvalueless

maxlen

'maxlen'检查属性值的长度是否不大于给定的值。这有助于防止WWW客户端和各种服务器上的缓冲区溢出。在我的例子中,这意味着不会接受<a href='ftp://ftp.v1ct1m.com/AAAA..thousands_of_A's...'>

当然,如果你把这个长URL放在<frame>标签中,这个问题会更糟,因为WWW客户端会自动获取它,而无需用户点击。

maxval

maxval检查属性值是否为大于或等于零的整数,它没有不合理的零或空格数量(以避免缓冲区溢出),并且它不大于给定的值。在我的例子中,这意味着接受<font size='20'>但不接受<font size='21'>。这项检查有助于防止针对WWW客户端的拒绝服务攻击。

这种DoS问题的一个例子是<iframe src="http://some.web.server/" width="20000" height="2000">,它会导致某些客户端机器完全过载。

minlen和minval

minlenminvalmaxlenmaxval的工作方式相同,只是它们检查最小长度和值而不是最大长度和值。

valueless

valueless 检查属性是否有值(例如 <a href="blah">)或者没有(例如 <option selected>)。如果给定的值是 "y" 或 "Y",则属性必须没有值才能被接受。如果给定的值是 "n" 或 "N",则属性必须有值。注意,<a href=""> 被认为是具有值的,因此无值属性与长度为零的属性值之间存在差异。

您可以通过在内部数组中将一个检查放在另一个之后来组合多个检查。

允许列出的URL协议

默认情况下,Kses 使用自己的协议列表加载

  • ftp, http, https, irc, news, nntp, rtsp, sftp, ssh, tel, telnet, webcal。

相当合理,但任何想更改它的人只需调用 setAllowedProtocols()addAlloweProtocol() 函数,并带上第三个参数,如下所示

$xss = new Xss();

$xss->setAllowedProtocols(['http', 'https']);

$xss->addAlloweProtocol('news');

注意,在 http 或其他协议名称之后不应包含任何冒号。

错误报告

似乎不再有人维护 Kses 的代码。由 WordPress 和 Drupal 使用,我们将密切关注它们的实现。

如果您在 kses 中发现了任何安全问题(尤其是 XSS,当然是),请在 Discord、Mastodon 或论坛上私下联系 Soosyze CMS 团队,以便他在您或其他人向公众透露之前纠正它。

(不,如果使用 kses 的某个程序允许一个坏的属性,这不是 kses 中的安全问题,愚蠢。如果 kses 被告知接受具有 style 和 onLoad 属性的元素 body,它将接受它们,即使从安全的角度来看这真的不是一个好主意。)

Kses 的第一作者

感谢

  • Peter Valach,代码审查和功能建议
  • Simon Cornelius P. Umacob,测试
  • Dirk Haun,功能建议
  • Hendy Irawan,错误报告和文档建议
  • dude21,功能建议
  • Christian Bolstad,文档建议
  • SourceForge,项目托管

也要感谢许多在 Bugtraq 和邮件列表上发布有关 XSS 或 HTML 过滤器的帖子的人。他们为我们提供了一些有价值的见解。

许可证

该程序根据 GNU 通用公共许可证的条款发布。在使用 kses 之前,您应该了解一下这意味着什么。您可以在 文件 LICENSE 中找到许可证的全文。