ユーザーが私のWebアプリケーションのページに<
または>
を含む何かを投稿するたびに、この例外がスローされます。
誰かがテキストボックスに文字を入力したために例外をスローしたりWebアプリケーション全体をクラッシュさせたりすることの賢さに関する議論には入りたくありませんが、これを処理するためのエレガントな方法を探しています。
例外をトラップして表示する
エラーが発生しました。戻ってフォーム全体をもう一度入力してください。ただし、今回は<使用しないでください。
私にとってプロとしては十分ではないようです。
事後検証(validateRequest="false"
)を無効にすると、このエラーは確実に回避されますが、ページが多くの攻撃に対して脆弱になります。
理想的には:HTMLで制限された文字を含むポストバックが発生すると、Formコレクション内のそのポストされた値は自動的にHTMLエンコードされます。だから私のテキストボックスの.Text
プロパティはsomething & lt; html & gt;
になります
私はハンドラからこれを行うことができる方法はありますか?
投稿されたデータをすべてエンコードしようとすることで、間違った角度からそれを攻撃していると思います。
"<
"は、データベースフィールド、設定、ファイル、フィードなど、他の外部のソースからも取得できることに注意してください。
さらに、 "<
"は本質的に危険ではありません。 (XSSのために)HTML出力にエンコードされていない文字列を書くとき、それは特定の状況においてのみ危険です。
他のコンテキストでは、さまざまなサブストリングが危険です。たとえば、ユーザー提供のURLをリンクに書き込む場合、サブストリング "javascript:
"が危険になる可能性があります。一方、一重引用符はSQLクエリで文字列を補間する場合は危険ですが、フォームから送信された名前やデータベースフィールドから読み取られた名前の一部である場合は完全に安全です。
肝心なのは、ランダムな入力に対して危険な文字をフィルタ処理することはできない、というのは正しい状況下ではどんな文字でも危険なのだから。特定の文字が危険になる可能性があるところでエンコードする必要があります。それらは特別な意味を持つ別のサブ言語に交差するためです。 HTMLに文字列を書き込むときは、Server.HtmlEncodeを使用して、HTMLで特別な意味を持つ文字をエンコードする必要があります。動的SQL文に文字列を渡す場合は、異なる文字をエンコードする必要があります(または、準備済みの文などを使用してフレームワークに代わって処理させてください)。
の場合は、文字列をHTMLに渡す場所に必ずHTMLエンコードしてから、validateRequest="false"
ファイルの<%@ Page ... %>
ディレクティブに.aspx
を設定してください。
.NET 4では、もう少し作業が必要になるかもしれません。時々web.configに<httpRuntime requestValidationMode="2.0" />
を追加する必要があります( reference )。
ASP.NET MVCを使用している場合、このエラーに対する別の解決策があります。
C#のサンプル:
[HttpPost, ValidateInput(false)]
public ActionResult Edit(FormCollection collection)
{
// ...
}
Visual Basicのサンプル:
<AcceptVerbs(HttpVerbs.Post), ValidateInput(False)> _
Function Edit(ByVal collection As FormCollection) As ActionResult
...
End Function
ASP.NET MVC(バージョン3以降)では、モデルのプロパティに AllowHtml
属性を追加できます。
プロパティの要求検証をスキップすることで、モデルバインディング中に要求にHTMLマークアップを含めることができます。
[AllowHtml]
public string Description { get; set; }
.NET 4.0をお使いの場合は、これを<system.web>
タグ内の web.config ファイルに追加してください。
<httpRuntime requestValidationMode="2.0" />
.NET 2.0では、要求の検証はaspx
要求にのみ適用されました。 .NET 4.0では、これは all リクエストを含むように拡張されました。次のように指定すると、.aspx
を処理するときに only に戻りXSS検証を実行できます。
requestValidationMode="2.0"
次のように指定することでrequest validate fully を無効にすることができます。
validateRequest="false"
ASP.NET 4.0では、すべてを<location>
要素に入れることで、サイト全体ではなく特定のページへの入力としてマークアップを許可できます。これにより、他のすべてのページが安全であることを確認できます。あなたの.aspxページにValidateRequest="false"
を入れる必要はありません。
<configuration>
...
<location path="MyFolder/.aspx">
<system.web>
<pages validateRequest="false" />
<httpRuntime requestValidationMode="2.0" />
</system.web>
</location>
...
</configuration>
どのページが入力としてマークアップを許可するかをサイトレベルで見ることができるので、あなたのweb.configの中でこれを制御するほうが安全です。
リクエストの検証が無効になっているページでは、プログラムで入力を検証する必要があります。
これまでの答えは素晴らしいですが、HTML/JavaScriptインジェクションの検証から単一のフィールドを除外する方法は誰も述べていません。以前のバージョンについてはわかりませんが、MVC3 Betaではこれが可能です。
[HttpPost, ValidateInput(true, Exclude = "YourFieldName")]
public virtual ActionResult Edit(int id, FormCollection collection)
{
...
}
これはまだ除外されたものを除くすべてのフィールドを検証します。これについてのいいところは、あなたの検証属性がまだフィールドを検証しているということですが、あなたは「潜在的に危険なRequest.Form値がクライアントから検出された」という例外を受けないということです。
これを正規表現の検証に使用しました。正規表現が有効かどうかを確認するために独自のValidationAttributeを作成しました。正規表現には上記のコードを適用したスクリプトのようなものを含めることができます。正規表現は有効かどうかはまだチェックされますが、スクリプトやHTMLが含まれている場合はチェックされません。
ASP.NET MVCでは、web.configでrequestValidationMode = "2.0"とvalidateRequest = "false"を設定し、ValidateInput属性をコントローラのアクションに適用する必要があります。
<httpRuntime requestValidationMode="2.0"/>
<configuration>
<system.web>
<pages validateRequest="false" />
</system.web>
</configuration>
そして
[Post, ValidateInput(false)]
public ActionResult Edit(string message) {
...
}
HTMLエンコード テキストボックスのコンテンツを作成できますが、残念ながら例外が発生するのを防ぐことはできません。私の経験では回避策はありません、そしてページ検証を無効にする必要があります。それをすることによって、あなたは言っています:「私は慎重になります、私は約束します」。
MVCの場合は、追加して入力検証を無視します。
[ValidateInput(false)]
コントローラ内の各アクションの上。
Global.asaxでそのエラーをキャッチすることができます。まだ検証したいのですが、適切なメッセージを表示します。下記のブログでは、このようなサンプルが利用可能でした。
void Application_Error(object sender, EventArgs e)
{
Exception ex = Server.GetLastError();
if (ex is HttpRequestValidationException)
{
Response.Clear();
Response.StatusCode = 200;
Response.Write(@"[html]");
Response.End();
}
}
別のページにリダイレクトすることも例外に対する合理的な対応のように思えます。
http://www.romsteady.net/blog/2007/06/how-to-catch-httprequestvalidationexcep.html
いくつかの.NETコントロールは自動的に出力をHTMLエンコードすることに注意してください。たとえば、TextBoxコントロールの.Textプロパティを設定すると、自動的にエンコードされます。つまり、<
を<
に、>
を>
に、そして&
を&
に変換するということです。だからこれをすることには用心してください...
myTextBox.Text = Server.HtmlEncode(myStringFromDatabase); // Pseudo code
ただし、HyperLink、Literal、およびLabelの.TextプロパティはHTMLエンコードされないため、Server.HtmlEncode()をラップします。 <script> window.location = "http://www.google.com"; </script>
があなたのページに出力され、その後実行されるのを防ぎたいのなら、これらのプロパティに設定されているものすべてを回避することが必須です。
何がエンコードされ、何がエンコードされないのかを確認するために、少し実験を行います。
この質問に対する答えは簡単です。
var varname = Request.Unvalidated["parameter_name"];
これにより、特定のリクエストに対する検証が無効になります。
Web.configファイルのタグ内に、属性requestValidationMode = "2.0"のhttpRuntime要素を挿入します。 pages要素にvalidateRequest = "false"属性も追加します。
例:
<configuration>
<system.web>
<httpRuntime requestValidationMode="2.0" />
</system.web>
<pages validateRequest="false">
</pages>
</configuration>
ValidateRequestを無効にしたくない場合は、例外を回避するためにJavaScript関数を実装する必要があります。これは最良の選択肢ではありませんが、うまくいきます。
function AlphanumericValidation(evt)
{
var charCode = (evt.charCode) ? evt.charCode : ((evt.keyCode) ? evt.keyCode :
((evt.which) ? evt.which : 0));
// User type Enter key
if (charCode == 13)
{
// Do something, set controls focus or do anything
return false;
}
// User can not type non alphanumeric characters
if ( (charCode < 48) ||
(charCode > 122) ||
((charCode > 57) && (charCode < 65)) ||
((charCode > 90) && (charCode < 97))
)
{
// Show a message or do something
return false;
}
}
次に、コードビハインドのPageLoadイベントで、次のコードを使用してコントロールに属性を追加します。
Me.TextBox1.Attributes.Add("OnKeyPress", "return AlphanumericValidation(event);")
まだ誰も以下のことを述べていないようですが、私にとっては問題は解決しています。そして誰かが言う前にそうだ、それはVisual Basic ...やあ。
<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="Example.aspx.vb" Inherits="Example.Example" **ValidateRequest="false"** %>
欠点があるかどうかはわかりませんが、私にとってはこれは驚くほどうまくいきました。
別の解決策は:
protected void Application_Start()
{
...
RequestValidator.Current = new MyRequestValidator();
}
public class MyRequestValidator: RequestValidator
{
protected override bool IsValidRequestString(HttpContext context, string value, RequestValidationSource requestValidationSource, string collectionKey, out int validationFailureIndex)
{
bool result = base.IsValidRequestString(context, value, requestValidationSource, collectionKey, out validationFailureIndex);
if (!result)
{
// Write your validation here
if (requestValidationSource == RequestValidationSource.Form ||
requestValidationSource == RequestValidationSource.QueryString)
return true; // Suppress error message
}
return result;
}
}
フレームワーク4.0を使用している場合は、web.configのエントリ(<pages validateRequest = "false" />)
<configuration>
<system.web>
<pages validateRequest="false" />
</system.web>
</configuration>
フレームワーク4.5を使用している場合は、web.configのエントリ(requestValidationMode = "2.0")
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" requestValidationMode="2.0"/>
</system.web>
あなたが1ページだけをしたい場合は、あなたのaspxファイルでは、このように最初の行を入れてください:
<%@ Page EnableEventValidation="false" %>
すでに<%@ Pageのようなものがある場合は、rest => EnableEventValidation="false"
%>を追加する
しないことをお勧めします。
ASP.NETでは、例外をキャッチして、わかりやすいメッセージを表示したり、別のページにリダイレクトしたりすることなど、何かを行うことができます。
わかりやすいメッセージを表示します。
protected override void OnError(EventArgs e)
{
base.OnError(e);
var ex = Server.GetLastError().GetBaseException();
if (ex is System.Web.HttpRequestValidationException)
{
Response.Clear();
Response.Write("Invalid characters."); // Response.Write(HttpUtility.HtmlEncode(ex.Message));
Response.StatusCode = 200;
Response.End();
}
}
モジュールでそれができると思います。しかし、それはいくつかの疑問を残したままにします。あなたがデータベースに入力を保存したい場合はどうなりますか?突然、エンコードされたデータをデータベースに保存しているので、そこからの入力を信頼することになります。これはおそらく悪い考えです。理想的には、未エンコードの生データをデータベースに保存し、その都度エンコードします。
ページ単位レベルで保護を無効にしてから毎回エンコードすることをお勧めします。
Server.HtmlEncodeを使用するのではなく、Microsoft ACEチームによる、より新しくより完全な Anti-XSS library を参照してください。
ここで他の解決策はいいです、しかし、あなたがまともなサイズのサイトで100以上のモデルを持っているなら特に、すべての個々のModelプロパティに[AllowHtml]を適用しなければならないことは後部の少し王立の苦痛です。
私と同じように、この(私見では無意味な)機能をサイト全体でオフにしたい場合は、ベースコントローラのExecute()メソッドをオーバーライドすることができます(まだベースコントローラを持っていない場合は作成できます)。一般的な機能を適用するのに非常に便利です。
protected override void Execute(RequestContext requestContext)
{
// Disable requestion validation (security) across the whole site
ValidateRequest = false;
base.Execute(requestContext);
}
ユーザー入力からのビューに表示されるすべてのものをHTMLエンコードしていることを確認してください(何らかの理由でHtml.Raw()を使用しない限り、Razorを使用したASP.NET MVC 3のデフォルトの動作です)。この機能を必要としないでください。
本当に>
、、<
などの特殊文字が必要な場合は、ページ検証を無効にします。次に、ユーザー入力が表示されるときにデータがHTMLエンコードされるようにします。
ページ検証にはセキュリティ上の脆弱性があるため、回避することができます。また、ページの検証だけに頼るべきではありません。
原因
デフォルトでASP.NETは、 クロスサイトスクリプティング (XSS)および SQLインジェクション につながる可能性がある危険性のあるコンテンツについてすべての入力コントロールを検証します。そのため、上記の例外をスローしてそのようなコンテンツを許可しません。デフォルトでは、このチェックがポストバックごとに行われるようにすることをお勧めします。
解決策
多くの場合、リッチテキストボックスまたはリッチテキストエディタを介してHTMLコンテンツをページに送信する必要があります。その場合、@Page
ディレクティブのValidateRequestタグをfalseに設定することでこの例外を回避できます。
<%@ Page Language="C#" AutoEventWireup="true" ValidateRequest = "false" %>
これにより、ValidateRequestフラグをfalseに設定したページに対するリクエストの検証が無効になります。これを無効にしたい場合は、Webアプリケーション全体をチェックしてください。 web.config <system.web>セクションでfalseに設定する必要があります。
<pages validateRequest ="false" />
.NET 4.0以降のフレームワークでは、上記を機能させるために<system.web>セクションに次の行も追加する必要があります。
<httpRuntime requestValidationMode = "2.0" />
それでおしまい。これが上記の問題を解決するのに役立つことを願っています。
私はJavaScriptを使用してデータをエンコードするソリューションを見つけました。それは.NETでデコードされます(そしてjQueryを必要としません)。
以下のJavaScript関数をヘッダーに追加してください。
function boo(){ targetText = document.getElementById( "HiddenField1"); sourceText = document.getElementById( "userbox") targetText.value = escape(sourceText.innerText); }テキスト領域に、boo()を呼び出すonchangeを含めます。
<textarea id="userbox" onchange="boo();"></textarea>
最後に、.NETでは
string val = Server.UrlDecode(HiddenField1.Value);
私はこれが一方向であることを承知しています - 双方向が必要な場合はクリエイティブになる必要がありますが、これはweb.configを編集できない場合の解決策になります。
これが私(MC9000)が思い付いたjQuery経由の使用例です。
$(document).ready(function () {
$("#txtHTML").change(function () {
var currentText = $("#txtHTML").text();
currentText = escape(currentText); // Escapes the HTML including quotations, etc
$("#hidHTML").val(currentText); // Set the hidden field
});
// Intercept the postback
$("#btnMyPostbackButton").click(function () {
$("#txtHTML").val(""); // Clear the textarea before POSTing
// If you don't clear it, it will give you
// the error due to the HTML in the textarea.
return true; // Post back
});
});
そしてマークアップ:
<asp:HiddenField ID="hidHTML" runat="server" />
<textarea id="txtHTML"></textarea>
<asp:Button ID="btnMyPostbackButton" runat="server" Text="Post Form" />
これはとてもうまくいきます。ハッカーがJavaScriptをバイパスして投稿しようとすると、彼らはただエラーを見るでしょう。データベースにエンコードされたこのデータすべてを保存してから(サーバー側で)アンエスケープし、他の場所に表示する前に解析して攻撃をチェックすることもできます。
私もこのエラーを受けていました。
私の場合は、ユーザーがロール名にアクセント記号付きの文字á
を入力しました(ASP.NETメンバーシッププロバイダに関して)。
ユーザーにそのロールを付与するメソッドにロール名を渡し、$.ajax
投稿要求が失敗しました...
私は問題を解決するためにこれをしました:
の代わりに
data: { roleName: '@Model.RoleName', users: users }
これを行う
data: { roleName: '@Html.Raw(@Model.RoleName)', users: users }
@Html.Raw
がうまくいった。
ロール名をHTML値roleName="Cadastro bás"
として取得していました。 HTMLエンティティá
を持つこの値は、ASP.NET MVCによってブロックされていました。これで、roleName
パラメータの値が正しい方法で取得されました。roleName="Cadastro Básico"
とASP.NET MVCエンジンは、要求をブロックしなくなりました。
JavaScriptの escape(string) 関数を使って特殊文字を置き換えることもできます。それからサーバサイドはServer. URLDecode(string) を使ってそれを元に戻します。
こうすれば、入力検証を無効にする必要がなくなり、文字列にHTMLコンテンツが含まれる可能性があることが他のプログラマには明らかになります。
ポストバックの前にJavaScriptを使用して、不要な文字をチェックしました。
<asp:Button runat="server" ID="saveButton" Text="Save" CssClass="saveButton" OnClientClick="return checkFields()" />
function checkFields() {
var tbs = new Array();
tbs = document.getElementsByTagName("input");
var isValid = true;
for (i=0; i<tbs.length; i++) {
if (tbs(i).type == 'text') {
if (tbs(i).value.indexOf('<') != -1 || tbs(i).value.indexOf('>') != -1) {
alert('<> symbols not allowed.');
isValid = false;
}
}
}
return isValid;
}
確かに私のページはデータ入力であり、ポストバックをする要素は非常に少ないですが、少なくともそれらのデータは保持されます。
これらが only "<"と ">"(そして二重引用符自体ではない)の文字であり、<input value = " this " />のように使用している場合安全です(<textarea> これ </textarea>の間はもちろん脆弱です)。それはあなたの状況を単純化するかもしれません、しかし 何でも もっと他の投稿された解決策のうちの1つを使用してください。
ユーザーに<と>は使用しないことを伝えたいだけであれば、フォーム全体を処理したりポストバックしたり(およびすべての入力を失ったり)しないでください。それらの(そしておそらく他の潜在的に危険な)文字をスクリーニングするためにフィールドの周りのバリデータ?
次のようなものを使うことができます。
var nvc = Request.Unvalidated().Form;
後で、nvc["yourKey"]
が機能するはずです。
提案のどれも私のために働きませんでした。 99%の時間が私のユーザーがWebフォームにHTMLを配置したくないので私はとにかく私はとにかくウェブサイト全体のためにこの機能をオフにしたくありませんでした。私はこの特定のアプリケーションを使用しているのは私だけなので、私は私自身の方法で自分自身の回避策を作成しました。コードビハインドで入力をHTMLに変換してデータベースに挿入します。
カスタムモデルバインダーのフィールドを自動的にHTMLエンコードできます。私の解決策は多少異なります、私はModelStateにエラーを入れて、フィールドの近くにエラーメッセージを表示します。自動的にエンコードするためにこのコードを修正するのは簡単です
public class AppModelBinder : DefaultModelBinder
{
protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
{
try
{
return base.CreateModel(controllerContext, bindingContext, modelType);
}
catch (HttpRequestValidationException e)
{
HandleHttpRequestValidationException(bindingContext, e);
return null; // Encode here
}
}
protected override object GetPropertyValue(ControllerContext controllerContext, ModelBindingContext bindingContext,
PropertyDescriptor propertyDescriptor, IModelBinder propertyBinder)
{
try
{
return base.GetPropertyValue(controllerContext, bindingContext, propertyDescriptor, propertyBinder);
}
catch (HttpRequestValidationException e)
{
HandleHttpRequestValidationException(bindingContext, e);
return null; // Encode here
}
}
protected void HandleHttpRequestValidationException(ModelBindingContext bindingContext, HttpRequestValidationException ex)
{
var valueProviderCollection = bindingContext.ValueProvider as ValueProviderCollection;
if (valueProviderCollection != null)
{
ValueProviderResult valueProviderResult = valueProviderCollection.GetValue(bindingContext.ModelName, skipValidation: true);
bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);
}
string errorMessage = string.Format(CultureInfo.CurrentCulture, "{0} contains invalid symbols: <, &",
bindingContext.ModelMetadata.DisplayName);
bindingContext.ModelState.AddModelError(bindingContext.ModelName, errorMessage);
}
}
Application_Startの場合:
ModelBinders.Binders.DefaultBinder = new AppModelBinder();
フォームフィールドでのみ機能することに注意してください。危険な値はコントローラーモデルに渡されませんが、ModelStateに格納され、エラーメッセージ付きでフォームに再表示できます。
URL内の危険な文字は次のように処理されます。
private void Application_Error(object sender, EventArgs e)
{
Exception exception = Server.GetLastError();
HttpContext httpContext = HttpContext.Current;
HttpException httpException = exception as HttpException;
if (httpException != null)
{
RouteData routeData = new RouteData();
routeData.Values.Add("controller", "Error");
var httpCode = httpException.GetHttpCode();
switch (httpCode)
{
case (int)HttpStatusCode.BadRequest /* 400 */:
if (httpException.Message.Contains("Request.Path"))
{
httpContext.Response.Clear();
RequestContext requestContext = new RequestContext(new HttpContextWrapper(Context), routeData);
requestContext.RouteData.Values["action"] ="InvalidUrl";
requestContext.RouteData.Values["controller"] ="Error";
IControllerFactory factory = ControllerBuilder.Current.GetControllerFactory();
IController controller = factory.CreateController(requestContext, "Error");
controller.Execute(requestContext);
httpContext.Server.ClearError();
Response.StatusCode = (int)HttpStatusCode.BadRequest /* 400 */;
}
break;
}
}
}
ErrorController:
public class ErrorController : Controller
{
public ActionResult InvalidUrl()
{
return View();
}
}
あなたのサイトを危険な入力から守るためにServer.HtmlEncodeメソッドを使うべきです。
Sel's answer への私のコメントに示されているように、これはカスタムリクエストバリデータへの拡張です。
public class SkippableRequestValidator : RequestValidator
{
protected override bool IsValidRequestString(HttpContext context, string value, RequestValidationSource requestValidationSource, string collectionKey, out int validationFailureIndex)
{
if (collectionKey != null && collectionKey.EndsWith("_NoValidation"))
{
validationFailureIndex = 0;
return true;
}
return base.IsValidRequestString(context, value, requestValidationSource, collectionKey, out validationFailureIndex);
}
}
モデルバインディングを使用していない人、Request.Formから各パラメータを抽出している人、入力テキストが害を及ぼさないことを確信している人にとっては、別の方法があります。素晴らしい解決策ではありませんが、それは仕事をします。
クライアント側から、それをURIとしてエンコードして送信します。
例えば:
encodeURIComponent($("#MsgBody").val());
サーバー側から、それを受け入れてURIとしてデコードします。
例えば:
string temp = !string.IsNullOrEmpty(HttpContext.Current.Request.Form["MsgBody"]) ?
System.Web.HttpUtility.UrlDecode(HttpContext.Current.Request.Form["MsgBody"]) :
null;
または
string temp = !string.IsNullOrEmpty(HttpContext.Current.Request.Form["MsgBody"]) ?
System.Uri.UnescapeDataString(HttpContext.Current.Request.Form["MsgBody"]) :
null;
UrlDecode
とUnescapeDataString
の違いを探してください
大事なことを言い忘れましたが、ASP.NETデータバインディングはデータバインディング中に自動的に encode の値を制御します。これはItemTemplate
に含まれるすべてのASP.NETコントロール(TextBox、Labelなど)のデフォルトの動作を変更します。次のサンプルはそのことを示しています(ValidateRequest
はfalseに設定されています)。
aspx
<%@ Page Language="C#" ValidateRequest="false" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication17._Default" %> <html> <body>
<form runat="server">
<asp:FormView ID="FormView1" runat="server" ItemType="WebApplication17.S" SelectMethod="FormView1_GetItem">
<ItemTemplate>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />
<asp:Label ID="Label1" runat="server" Text="<%#: Item.Text %>"></asp:Label>
<asp:TextBox ID="TextBox2" runat="server" Text="<%#: Item.Text %>"></asp:TextBox>
</ItemTemplate>
</asp:FormView>
</form>
コードビハインド
public partial class _Default : Page
{
S s = new S();
protected void Button1_Click(object sender, EventArgs e)
{
s.Text = ((TextBox)FormView1.FindControl("TextBox1")).Text;
FormView1.DataBind();
}
public S FormView1_GetItem(int? id)
{
return s;
}
}
public class S
{
public string Text { get; set; }
}
'
Label1.Text
値:'
TextBox2.Text
値:&#39;
<script>alert('attack!');</script>
Label1.Text
値:<script>alert('attack!');</script>
TextBox2.Text
値:<script>alert('attack!');</script>
私たちのうちの1人はまだWebフォームを使い続けているので、1つのフィールドでのみ検証を無効にできる次の解決策を見つけました。 (私はページ全体でそれを無効にするのは嫌だと思います。)
VB.NET:
Public Class UnvalidatedTextBox
Inherits TextBox
Protected Overrides Function LoadPostData(postDataKey As String, postCollection As NameValueCollection) As Boolean
Return MyBase.LoadPostData(postDataKey, System.Web.HttpContext.Current.Request.Unvalidated.Form)
End Function
End Class
C#:
public class UnvalidatedTextBox : TextBox
{
protected override bool LoadPostData(string postDataKey, NameValueCollection postCollection)
{
return base.LoadPostData(postDataKey, System.Web.HttpContext.Current.Request.Unvalidated.Form);
}
}
<prefix:UnvalidatedTextBox id="test" runat="server" />
の代わりに<asp:TextBox
を使用するだけで、すべての文字を使用できます(これはパスワードフィールドに最適です)
私はこの質問がフォームの投稿に関することを知っていますが、私は他の状況でこのエラーを受けた人々のためにいくつかの詳細を加えたいと思います。 Webサービスの実装に使用されるハンドラでも発生する可能性があります。
Webクライアントがajaxを使用してPOSTまたはPUTリクエストを送信し、jsonまたはxmlのテキストまたは生データ(ファイルコンテンツ)をWebサービスに送信するとします。 WebサービスはContent-Typeヘッダーから情報を取得する必要がないため、JavaScriptコードはこのヘッダーをajaxリクエストに設定しませんでした。しかし、POST/PUT ajaxリクエストにこのヘッダを設定しない場合、Safariはこのヘッダを追加する可能性があります: "Content-Type:application/x-www-form-urlencoded"。私はiPhone上のSafari 6でそれを観察しました、しかし他のSafariバージョン/ OSまたはChromeは同じことをするかもしれません。したがって、このContent-Typeヘッダーを受け取るとき、.NET Frameworkの一部は、要求本文のデータ構造がHTMLフォームの投稿に対応していると見なし、HttpRequestValidationException例外を発生させません。最初にやるべきことは、POST/PUT ajaxリクエストでContent-Typeヘッダーを常にフォームのMIMEタイプ以外に設定することです。
私もこの詳細を発見しました:
これらの状況で、コードがHttpRequest.Paramsコレクションにアクセスしようとすると、HttpRequestValidationException例外が発生します。しかし、驚くべきことに、この例外はHttpRequest.ServerVariablesコレクションにアクセスしても上昇しません。これは、これら2つのコレクションはほぼ同じように見えますが、一方はセキュリティチェックを通じて要求データにアクセスし、もう一方はそうではないことを示しています。
通常のケースである.Net 4.0以降では、system.webに次の設定を入れます。
<system.web>
<httpRuntime requestValidationMode="2.0" />
私の場合は、validateRequest="false"
の全ページを設定する代わりにasp:Textboxコントロール(Asp.net 4.5)を使用します。
<asp:TextBox runat="server" ID="mainTextBox"
ValidateRequestMode="Disabled"
></asp:TextBox>
例外を引き起こしたTextboxで。
解決策
投稿の検証を無効にしたくありません(validateRequest = "false")。一方、罪のないユーザーが偶然<x
などとタイプしたからといって、アプリケーションがクラッシュすることは許容できません。
そこで私は予備的なチェックを行うクライアントサイドのJavaScript関数(xssCheckValidates)を書きました。この関数は、次のようにフォームデータを投稿しようとしたときに呼び出されます。
<form id="form1" runat="server" onsubmit="return xssCheckValidates();">
機能は非常に単純で改善することができますが、それはその仕事をしています。
この目的はシステムをハッキングから保護することではなく、ユーザーを悪い経験から保護することを目的としていることに注意してください。サーバーで行われた要求検証はまだオンになっています、そしてそれは(それがすることができる範囲で)システムの保護(の一部)です。
ここで「の一部」と言うのは、組み込みの要求検証では不十分な場合があると聞いたためです。完全な保護を得るには他の補足的な手段が必要になるかもしれません。しかし、繰り返しますが、ここで紹介するJavaScript関数には 何もない がシステムの保護に関係しています。 only は、ユーザーが悪い経験をしないようにするためのものです。
ここで試してみることができます。
function xssCheckValidates() {
var valid = true;
var inp = document.querySelectorAll(
"input:not(:disabled):not([readonly]):not([type=hidden])" +
",textarea:not(:disabled):not([readonly])");
for (var i = 0; i < inp.length; i++) {
if (!inp[i].readOnly) {
if (inp[i].value.indexOf('<') > -1) {
valid = false;
break;
}
if (inp[i].value.indexOf('&#') > -1) {
valid = false;
break;
}
}
}
if (valid) {
return true;
} else {
alert('In one or more of the text fields, you have typed\r\nthe character "<" or the character sequence "&#".\r\n\r\nThis is unfortunately not allowed since\r\nit can be used in hacking attempts.\r\n\r\nPlease edit the field and try again.');
return false;
}
}
<form onsubmit="return xssCheckValidates();" >
Try to type < or &# <br/>
<input type="text" /><br/>
<textarea></textarea>
<input type="submit" value="Send" />
</form>
Server.HtmlEncode("yourtext");
を使う
私はこれについて多くのことが書かれているのを見ます…そして私はこれが言及されるのを見ませんでした。
コントロールの ValidateRequestMode 設定は素晴らしいオプションです。 web.configを変更する必要はありません。
protected void Page_Load(object sender, EventArgs e)
{
txtMachKey.ValidateRequestMode = ValidateRequestMode.Disabled;
}