【问题标题】:Customize web form script generation自定义 Web 表单脚本生成
【发布时间】:2020-07-03 21:26:15
【问题描述】:

好的,是的,现在是 2020 年,但不要笑。我正在尝试更新一些 ASP.NET Web 表单。我的目标是锁定它们,通过应用更严格的内容安全策略 (CSP) 使它们更安全。为此,我使用随机数,而不是允许 unsafe-inline 进行脚本编写。

对于“简单”的网络表单,它运行良好。但是,每当有一个导致回发的 ASP 控件时,我都会遇到问题。当我查看页面源代码时,我看到如下内容:

<script type="text/javascript">
//<![CDATA[
var theForm = document.forms['form1'];
if (!theForm) {
    theForm = document.form1;
}
function __doPostBack(eventTarget, eventArgument) {
    if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
        theForm.__EVENTTARGET.value = eventTarget;
        theForm.__EVENTARGUMENT.value = eventArgument;
        theForm.submit();
    }
}

<script type="text/javascript">
    function previewFile() {
        var preview = document.querySelector('#Body_Main_LogoImage');
        var file = document.querySelector('#Body_Main_logoUpload').files[0];
        var reader = new FileReader();

        reader.onloadend = function () {
            preview.src = reader.result;
        }

        if (file) {
            reader.readAsDataURL(file);
        } else {
            preview.src = "";
        }
    }
</script>

我相信此代码是由一些 MS Web 表单代码生成的。问题是这些脚本元素都没有我想提供的随机数,所以它违反了我的 CSP(不包括unsafe-inline)。有什么我可以覆盖来自定义此行为的吗?

【问题讨论】:

    标签: webforms content-security-policy


    【解决方案1】:

    一些违规代码是在 Page 类内的私有方法(例如 RenderPostBackScript)中定义的,而该类又由内部方法调用。因此,除非我替换大量代码,否则不能以正常方式覆盖它。作为替代方案,我在我的页面中覆盖了CreateHtmlTextWriter

    protected override System.Web.UI.HtmlTextWriter CreateHtmlTextWriter(TextWriter tw)
    {
        return new HtmlTextWriter(tw, this);
    }
    

    然后在我的HtmlWriter 课程中,我这样做:

    public override void Write(string s)
    {
        if (s != null && s.IndexOf("<script") > -1 && s.IndexOf("nonce") == -1 && s.IndexOf("src") == -1)
        {
            s = s.Replace("<script", "<script nonce=\"" + this._page.GetNonce() + "\"");
        }
        base.Write(s);
    }
    

    我在HtmlTextWriter 中为AddAttribute 使用了类似的方法,以避免在href 内内联javascript:,这需要unsafe-inline 用于script-src(并排除使用随机数)。

    public override void AddAttribute(HtmlTextWriterAttribute key, string value)
    {
        if (key == HtmlTextWriterAttribute.Href && value != null && value.IndexOf("javascript:") > -1)
        {
            base.AddAttribute(key, "#");
            var newScript = value.Replace("javascript:", "");
            newScript += "; return false;";
            base.AddAttribute(HtmlTextWriterAttribute.Onclick, newScript);
        }
        else
        {
            base.AddAttribute(key, value);
        }
    }
    

    【讨论】:

    • 如何/在哪里将 nonce 添加回 Web 表单页面的请求标头?您是否也遇到过需要 unsafe-eval 的 WebResource.axd 文件问题?
    【解决方案2】:

    您可以覆盖 __DoPostBack 并改用您自己的函数。

    var __original= __doPostBack;
    __doPostBack = myFunction();
    

    这里还有一些想法: How to intercept any postback in a page? - ASP.NET

    【讨论】:

    • 感谢您的建议和链接。 RegisterOnSubmitStatement 的想法看起来很有趣。但我想出了另一个解决方案,我将作为答案分享
    【解决方案3】:

    如果您在 Chrome 中打开开发工具,您可能会看到类似 Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self'. Either the 'unsafe-inline' keyword, a hash ('sha256-2NqnatcPqy5jjBXalTpZyJMO/0fUaYUb3ePlviUP4II='), or a nonce ('nonce-...') is required to enable inline execution. 的消息

    如果您仔细查看该消息,它会告诉您哈希是什么:sha256-2NqnatcPqy5jjBXalTpZyJMO/0fUaYUb3ePlviUP4II=

    所以如果你不想走nonce路线,你可以改为走hash路线并添加

    Content-Security-Policy: script-src 'self' 'sha256-2NqnatcPqy5jjBXalTpZyJMO/0fUaYUb3ePlviUP4II=' 'unsafe-eval';
    

    在某些情况下,您可能还必须添加 unsafe-eval 才能使其正常工作。

    【讨论】:

      猜你喜欢
      • 2012-02-18
      • 2017-02-26
      • 2011-12-29
      • 1970-01-01
      • 2017-04-02
      • 2019-02-18
      • 2017-01-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多