web-dev-qa-db-ja.com

jquery post callからasp.netページにhtmlマークアップを送信すると、潜在的に危険なRequest.QueryString値がクライアントから検出されました。

JQueryを使用して、Ajaxサーバーページとして機能するASP.NETページへのajax呼び出しを行って、クエリ文字列で送信するデータを保存しています。 ASP.NETページでクエリ文字列を読み取ろうとすると、次のエラーが表示されます。

A potentially dangerous Request.QueryString value was detected from the client...

ページにValidateRequest="false"を設定しました。すべてのページに設定する必要はありません。したがって、設定レベルではなくページレベルで行いました。

  var content = "<h3>Sample header</h3><p>sample para</p>"
  content = encodeURIComponent(content);
  var url = "../Lib/ajaxhandler.aspx?mode=savecontent&page=home&ltxt=" + content;

     $.post(url, function (data) { 
       //check return value and do something
   });

と私のasp.netページで:

 <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="ajaxhandler.aspx.cs" ValidateRequest="false" Inherits="MyProject.Lib.ajaxhandler" %>

しかし、htmlマークアップの代わりにプレーンテキストを送信する場合、正常に機能します。

40
Shyju

これがASP.NET 4の場合、 breaking change with ValidateRequestがありました。 requestValidationModeの詳細については、 このStackOverflowの質問 を参照してください。

36

特定のASP.NETページまたはページ全体にValidateRequest="false"を設定せずに1つ以上のクエリ文字列パラメーターにカスタム検証ロジックを追加する場合、次の「ハッキング」ソリューションが役立ちます。

public partial class MyPage : System.Web.UI.Page
{
    private string SomeUnvalidatedValue { get; set; }

    public override void ProcessRequest(HttpContext context)
    {
        var queryString = context.Request.QueryString;

        var readOnly = queryString.GetType().GetProperty("IsReadOnly",
            System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);

        readOnly.SetValue(queryString, false);

        var unvalidatedValue = context.Request.Unvalidated.QueryString["SomeKey"];
        // for RequestValidationMode="2.0"
        //var unvalidatedValue = context.Request.QueryString["SomeKey"];

        // custom logic goes here

        // you could store unvalidated value here and then remove it from the query string
        SomeUnvalidatedValue = unvalidatedValue;
        queryString["SomeKey"] = string.Empty;
        // or just remove all "potentially dangerous" symbols, for example
        if (!string.IsNullOrEmpty(unvalidatedValue))
        {
            queryString["SomeKey"] = Regex.Replace(unvalidatedValue,
                "(\\<+[a-z!/\\?])|(&\\#)", new MatchEvaluator((m) =>
                {
                    return m.Value.Replace("<", string.Empty).Replace("&#", string.Empty);
                }), RegexOptions.IgnoreCase);
        }

        readOnly.SetValue(queryString, true);

        // keep other request validation logic as is
        base.ProcessRequest(context);
    }
}

このASP.NETメソッドの分析の結果として作成された正規表現: CrossSiteScriptingValidation.IsDangerousString

.NET 4.5.2でテストされたコードIIS統合モード、RequestValidationMode="2.0"ありとなし)。

2
VAV

VAVの答え に基づいて、いくつかの再利用可能なメソッドを作成しました

   public static string ExtractUnvalidatedValue(HttpRequest request, string key)
        {
            var unvalidatedValue =  HttpUtility.UrlDecode(request.Unvalidated.QueryString[key]);
            // for RequestValidationMode="2.0"
            //var unvalidatedValue = context.Request.QueryString["SomeKey"];

          // remove all "potentially dangerous" symbols
            return ReplacePotentiallyDangerousSymbols(unvalidatedValue, string.Empty);
        }

    public static string ReplacePotentiallyDangerousSymbols(string unvalidatedValue, string valueToReplace="")
        {
            if (!string.IsNullOrEmpty(unvalidatedValue))
            {
                //The regular expression made as result of this ASP.NET method analyzing: CrossSiteScriptingValidation.IsDangerousString http://referencesource.Microsoft.com/#System.Web/CrossSiteScriptingValidation.cs,3c599cea73c5293b
                unvalidatedValue = Regex.Replace(unvalidatedValue,
                    "(\\<+[a-z!/\\?])|(&\\#)",
                    new MatchEvaluator((m) => { return m.Value.Replace("<", valueToReplace).Replace("&#", valueToReplace); }), RegexOptions.IgnoreCase);
            }
            return unvalidatedValue;
        }
1