在 PHP 中清理用户定义的 CSS

Posted

技术标签:

【中文标题】在 PHP 中清理用户定义的 CSS【英文标题】:Sanitize user defined CSS in PHP 【发布时间】:2011-03-15 13:44:09 【问题描述】:

我想允许用户在我的论坛上为他们的个人资料使用他们自己的样式表,但我担心可能存在安全漏洞。有人对清理 CSS 有什么建议吗?

基本流程:用户在表单中输入 CSS -> 保存到数据库 -> 输出为内联 CSS

【问题讨论】:

除了 IE 允许的非标准 behavior 属性和 expressions (两者都启动 javascript),我看不出 css 是如何导致任何“安全漏洞”的。因此,如果您过滤掉(或不允许输入)这些内容,我认为您会没事的。 moz 绑定。 javascript: 接受 url() 的所有内容中的 URL。布局黑客将其他内容放置在登录表单的顶部,@import 以引入未经检查的外部文件,作者稍后可能会破坏该文件。 CSS 并不是那么安全。 感谢 bobince,我不知道其中的一些危险。 来自sk89q.com/2009/08/definitive-php-security-checklist * 请注意,某些 CSS 属性(例如“位置”)可能会被恶意使用(覆盖登录表单的元素等)。 * CSS 还可以在字符串内部和外部包含转义序列 (\34)。 * CSS 文件可以包含 JavaScript。这表现为“CSS 表达式”和“行为”(Internet Explorer 功能)或 Gecko“绑定”的形式。 您的问题解决了吗? 【参考方案1】:

htmlPurifier 和 CSSTidy 可以满足您的需求。

HTMLPurifier 主要用于清理 HTML,但也可以选择使用 CSSTidy 提取样式块。

HTMLPurifier 文档中有一个示例(但是,我已经用完了每个帖子的两个链接。)

这是另一个:

require_once './htmlpurifier/library/HTMLPurifier.auto.php';
require_once './csstidy/class.csstidy.php';

// define some css
$input_css = "
    body 
        margin: 0px;
        padding: 0px;
        /* JS injection */
        background-image: url(javascript:alert('Injected'));
    
    a 
        color: #ccc;
        text-decoration: none;
        /* dangerous proprietary IE attribute */
        behavior:url(hilite.htc);
        /* dangerous proprietary FF attribute */
        -moz-binding: url('http://virus.com/htmlBindings.xml');
    
    .banner 
        /* absolute position can be used for phishing */
        position: absolute;
        top: 0px;
        left: 0px;
    
";

// Create a new configuration object
$config = HTMLPurifier_Config::createDefault();
$config->set('Filter.ExtractStyleBlocks', TRUE);

// Create a new purifier instance
$purifier = new HTMLPurifier($config);

// Turn off strict warnings (CSSTidy throws some warnings on PHP 5.2+)
$level = error_reporting(E_ALL & ~E_STRICT);

// Wrap our CSS in style tags and pass to purifier. 
// we're not actually interested in the html response though
$html = $purifier->purify('<style>'.$input_css.'</style>');

// Revert error reporting
error_reporting($level);

// The "style" blocks are stored seperately
$output_css = $purifier->context->get('StyleBlocks');

// Get the first style block
echo $output_css[0];

输出是:

body 
    margin:0;
    padding:0;


a 
    color:#ccc;
    text-decoration:none;


.banner 

【讨论】:

谢谢;希望我的网站上没有人被我微不足道的 RegEx 替换的 CSRF 击中。 这是一个绝妙的答案,极大地帮助了我正在做的事情。非常感谢。 这很好用!只有一个绊脚石:如何在 HTMLpurifier 的上下文中配置 CSS tidy,使用如上所示的 PHP 运行时代码?与此处相同的问题(基本上):***.com/questions/10843600/… 不使用 HTMLPurifier 和 CSSTidy 的任何方法 有人可以帮我解决我的问题吗:***.com/questions/52677988/…【参考方案2】:

自己定义类,并制作一个 GUI 来为每个类应用颜色和其他属性,使用与 twitter 相同的方法。

alt text http://grab.by/grabs/3217158e9c48538eb127fb1678dab6ae.png

当然,这只有在您的布局是由管理员而不是用户固定和定义的情况下才有效。

【讨论】:

我希望通过使用黑名单而不是白名单来为用户提供更多的灵活性。 黑名单需要不断更新,因为浏览器会添加新功能,而浏览器中的错误会让事情从裂缝中溜走。白名单是针对安全问题过滤数据的唯一明智方法。 图片链接已损坏。【参考方案3】:

我看不出这怎么可能造成安全漏洞,除非与其他用户共享配置文件。

如果它们被共享,可能会出现 CSRF 漏洞(因为 CSS 可以生成包含图像、字体、其他样式表等的 GET 请求)。他们还可以使用content 诱骗用户点击某些地方、隐藏重要功能等。当然,您必须转义&lt;&gt;,可能还有&amp; 以防止XSS(如果CSS 嵌入在 HTML 中)。

至于图书馆做卫生,我不知道任何(也许整洁)。

【讨论】:

它们与其他用户共享。【参考方案4】:

这可能无法修复所有类型的 hack,但至少可能是大多数自动化的 hack:

$css = strip_tags($css);
$css = htmlspecialchars($css, ENT_HTML5 | ENT_NOQUOTES | ENT_SUBSTITUTE, 'utf-8');

取决于允许多少用户使用此功能以及由此造成的威胁有多大..

【讨论】:

以上是关于在 PHP 中清理用户定义的 CSS的主要内容,如果未能解决你的问题,请参考以下文章

清理用户提交内容的最佳方法? [复制]

如何在邮件发送前清理 PHP 中的用户输入?

PHP PDO 清理用户输入

使用 PHP GET 清理字符串以在 href 中使用

PHP 清理 SQL DDL 语句的用户输入的方式是啥?

清理和验证 PHP 表单的最常见的“最佳”方式?