提问者:小点点

将“不安全内联”代码从元素移除到单独脚本的最佳实践


所以,背景是我是一个相当大的CMS的开发人员。数十万行代码。

因此,在实现内容安全策略时,我被迫对style-src和script-src指令使用“unsafe-inline”,因为CMS在元素中输出了大量内联CSS以及用于脚本编写的大量onclick-attributes。

为了提取内联样式,我更新了创建实际HTML的代码,以生成内联样式的crc32散列,将一个类应用于元素,然后在具有nonce-attribute的style标记中单独打印所有CSS。最终结果看起来是这样的:

对于内联脚本,或者更确切地说是onclick属性,我做了类似的事情,创建命令的crc32,将其作为元素的内联类添加,然后将其添加到脚本标记中。问题是,我使用jQuery将这些事件附加到元素,而旧的live()函数不推荐使用,所以我将它作为click事件附加到body元素上,这样隐藏的元素仍然会被激发。最终结果看起来是这样的:

所以,所有这些都是以前的或类似的东西。我想知道这个修复的最佳实践是什么。

并且在您建议这些实例中的每一个都应该将它们的动作附加得更符合逻辑或者用某种形式的内部逻辑来代替,以使它们触发正确的命令之前--我同意!但这是一大堆代码!我的第一步是做一个修复,然后开始对每个实例进行寻址,以做一个更漂亮的修复。

那么有没有更好的方法来处理这件事呢?


共1个答案

匿名用户

好吧,所以我可能找到了变通办法。如果我的系统要打印此代码:

<a onclick="dialog('/url.php')">Do stuff</a>

我的代码现在输出如下:

<a data-cmd="dialog" data-arg="/url.php">Do stuff</a>

然后我有一个全局代码:

$("body").on("click", "[data-cmd]", function(){
    switch ($(this).attr("data-cmd")){
        case "dialog" : dialog($(this).attr("data-arg")); break;
        case "bbe" : bbe($(this).attr("data-arg")); break;
        case "visa" : visa($(this).attr("data-arg")); break;
        case "svisa" : svisa($(this).attr("data-arg")); break;
        case "pop" : pop($(this).attr("data-arg")); break;
        case "dialog" : dialog($(this).attr("data-arg")); break;
        default: return false;
    }
    return false;
})

因此,使用它,我就可以拥有一个可以出现在data-cmd中的各种命令的安全列表,而且我不必eval()任何东西,这违反了内容安全策略。

我确信我会发现很多这不起作用的异常值(我可以想象onclick=“hide('EL1');show('EL2')”失败了,但是我可以回退到我以前的修复程序中,并用nonce将它们放入单独的脚本块中。“hide('EL1');show('EL2')”不起作用(我可以想象onclick=“hide('EL1');show('EL2')”失败了。