Ogni volta che un utente pubblica qualcosa che contiene <
o >
in una pagina della mia applicazione web, ottengo questa eccezione generata.
Non voglio entrare nella discussione sull'abilità di lanciare un'eccezione o di bloccare un'intera applicazione web perché qualcuno ha inserito un personaggio in una casella di testo, ma sto cercando un modo elegante per gestirlo.
Intrappolare l'eccezione e mostrare
Si è verificato un errore, torna indietro e digita nuovamente l'intero modulo, ma questa volta non utilizzare <
non mi sembra abbastanza professionale.
La disabilitazione della convalida post (validateRequest="false"
) eviterà sicuramente questo errore, ma lascerà la pagina vulnerabile a un numero di attacchi.
Idealmente: quando si verifica un postback contenente caratteri HTML limitati, il valore inserito nella raccolta Form verrà automaticamente codificato in HTML . Quindi la proprietà .Text
della mia casella di testo sarà something & lt; html & gt;
C'è un modo per farlo da un conduttore?
Penso che tu stia attaccando da un angolo sbagliato cercando di codificare tutti i dati inviati.
Si noti che un "<
" potrebbe anche provenire da altre fonti esterne, come un campo di database, una configurazione, un file, un feed e così via.
Inoltre, "<
" non è intrinsecamente pericoloso. È pericoloso solo in un contesto specifico: quando si scrivono stringhe che non sono state codificate in output HTML (a causa dell'XSS).
In altri contesti, diverse sottostringhe sono pericolose, ad esempio, se si scrive un URL fornito dall'utente in un collegamento, la sottostringa "javascript:
" potrebbe essere pericolosa. D'altra parte, il carattere di virgoletta singola è pericoloso quando si interpolano stringhe nelle query SQL, ma perfettamente sicuro se fa parte di un nome inviato da un modulo o letto da un campo di database.
La linea di fondo è: non puoi filtrare input casuali per personaggi pericolosi, perché qualsiasi personaggio può essere pericoloso nelle giuste circostanze. Dovresti codificare nel punto in cui alcuni personaggi specifici possono diventare pericolosi perché attraversano una sotto-lingua diversa in cui hanno un significato speciale. Quando scrivi una stringa in HTML, dovresti codificare i caratteri che hanno un significato speciale in HTML, usando Server.HtmlEncode. Se passi una stringa ad un'istruzione SQL dinamica, dovresti codificare caratteri diversi (o meglio, lasciare che il framework faccia per te usando istruzioni preparate o simili) ..
Quando sei sicuro di codificare HTML ovunque passi le stringhe in HTML, quindi imposta validateRequest="false"
nella direttiva <%@ Page ... %>
nei tuoi file .aspx
.
In .NET 4 potrebbe essere necessario fare un po 'di più. A volte è necessario aggiungere anche <httpRuntime requestValidationMode="2.0" />
a web.config ( reference ).
Esiste una soluzione diversa a questo errore se si utilizza ASP.NET MVC:
Campione C #:
[HttpPost, ValidateInput(false)]
public ActionResult Edit(FormCollection collection)
{
// ...
}
Esempio di Visual Basic:
<AcceptVerbs(HttpVerbs.Post), ValidateInput(False)> _
Function Edit(ByVal collection As FormCollection) As ActionResult
...
End Function
In ASP.NET MVC (a partire dalla versione 3), è possibile aggiungere l'attributo AllowHtml
a una proprietà sul modello.
Consente a una richiesta di includere il markup HTML durante l'associazione del modello ignorando la convalida della richiesta per la proprietà.
[AllowHtml]
public string Description { get; set; }
Se sei su .NET 4.0 assicurati di aggiungerlo nel tuo file web.config all'interno dei tag <system.web>
:
<httpRuntime requestValidationMode="2.0" />
In .NET 2.0, la convalida della richiesta si applicava solo alle richieste aspx
. In .NET 4.0 questo è stato ampliato per includere tutte richieste. È possibile ripristinare only eseguendo la convalida XSS durante l'elaborazione di .aspx
specificando:
requestValidationMode="2.0"
Puoi disabilitare la richiesta validate interamente specificando:
validateRequest="false"
Per ASP.NET 4.0, è possibile consentire il markup come input per pagine specifiche anziché l'intero sito inserendo tutto in un elemento <location>
. Questo assicurerà che tutte le altre pagine siano al sicuro. NON è necessario inserire ValidateRequest="false"
nella tua pagina .aspx.
<configuration>
...
<location path="MyFolder/.aspx">
<system.web>
<pages validateRequest="false" />
<httpRuntime requestValidationMode="2.0" />
</system.web>
</location>
...
</configuration>
È più sicuro controllarlo all'interno di web.config, perché è possibile vedere a livello di sito quali pagine consentono il markup come input.
È ancora necessario convalidare in modo programmato l'input nelle pagine in cui la convalida della richiesta è disabilitata.
Le risposte precedenti sono grandiose, ma nessuno ha detto come escludere un singolo campo dall'essere validato per le iniezioni HTML/JavaScript. Non conosco le versioni precedenti, ma in MVC3 Beta puoi farlo:
[HttpPost, ValidateInput(true, Exclude = "YourFieldName")]
public virtual ActionResult Edit(int id, FormCollection collection)
{
...
}
Ciò convalida ancora tutti i campi eccetto quello escluso. La cosa bella di questo è che i tuoi attributi di convalida continuano a validare il campo, ma non ottieni il messaggio "Un valore potenzialmente pericoloso Request.Form è stato rilevato dal client" eccezioni.
L'ho usato per convalidare un'espressione regolare. Ho creato il mio ValidationAttribute per vedere se l'espressione regolare è valida o meno. Poiché le espressioni regolari possono contenere qualcosa che assomiglia a uno script, ho applicato il codice precedente: l'espressione regolare viene ancora controllata se è valida o meno, ma non se contiene script o HTML.
In ASP.NET MVC è necessario impostare requestValidationMode = "2.0" e validateRequest = "false" in web.config e applicare un attributo ValidateInput all'azione del controller:
<httpRuntime requestValidationMode="2.0"/>
<configuration>
<system.web>
<pages validateRequest="false" />
</system.web>
</configuration>
e
[Post, ValidateInput(false)]
public ActionResult Edit(string message) {
...
}
Puoi codificare HTML contenuto della casella di testo, ma sfortunatamente ciò non impedirà l'esecuzione dell'eccezione. Nella mia esperienza non c'è modo, e devi disabilitare la convalida della pagina. In questo modo stai dicendo: "Starò attento, lo prometto".
Per MVC, ignorare la convalida dell'input aggiungendo
[ValidateInput (false)]
sopra ogni azione nel controller.
È possibile rilevare l'errore in Global.asax. Voglio ancora convalidare, ma mostrare un messaggio appropriato. Nel blog elencato di seguito, è disponibile un esempio simile.
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();
}
}
Il reindirizzamento a un'altra pagina sembra anche una risposta ragionevole all'eccezione.
http://www.romsteady.net/blog/2007/06/how-to-catch-httprequestvalidationexcep.html
Tieni presente che alcuni controlli .NET codificheranno automaticamente l'output in HTML. Ad esempio, l'impostazione della proprietà .Text su un controllo TextBox verrà automaticamente codificata. Ciò significa in particolare convertire <
in <
, >
in >
e &
in &
. Quindi diffidare di fare questo ...
myTextBox.Text = Server.HtmlEncode(myStringFromDatabase); // Pseudo code
Tuttavia, la proprietà .Text per HyperLink, Literal e Label non codificherà HTML, quindi avvolgerà Server.HtmlEncode (); tutto ciò che viene impostato su queste proprietà è indispensabile se si desidera impedire che <script> window.location = "http://www.google.com"; </script>
venga emesso nella pagina e successivamente eseguito.
Fai qualche esperimento per vedere cosa viene codificato e cosa no.
La risposta a questa domanda è semplice:
var varname = Request.Unvalidated["parameter_name"];
Ciò disabilita la convalida per la richiesta particolare.
Nel file web.config, all'interno dei tag, inserire l'elemento httpRuntime con l'attributo requestValidationMode = "2.0". Aggiungi anche l'attributo validateRequest = "false" nell'elemento pages.
Esempio:
<configuration>
<system.web>
<httpRuntime requestValidationMode="2.0" />
</system.web>
<pages validateRequest="false">
</pages>
</configuration>
Se non si desidera disabilitare ValidateRequest è necessario implementare una funzione JavaScript per evitare l'eccezione. Non è l'opzione migliore, ma funziona.
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;
}
}
Quindi, nel codice sottostante, nell'evento PageLoad, aggiungi l'attributo al tuo controllo con il codice successivo:
Me.TextBox1.Attributes.Add("OnKeyPress", "return AlphanumericValidation(event);")
Sembra che nessuno abbia ancora menzionato il sotto, ma risolve il problema per me. E prima che qualcuno dica sì, è Visual Basic ... schifo.
<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="Example.aspx.vb" Inherits="Example.Example" **ValidateRequest="false"** %>
Non so se ci sono degli svantaggi, ma per me questo ha funzionato in modo sorprendente.
Un'altra soluzione è:
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;
}
}
Se stai usando framework 4.0, allora la voce nel web.config (<pages validateRequest = "false" />)
<configuration>
<system.web>
<pages validateRequest="false" />
</system.web>
</configuration>
Se stai utilizzando framework 4.5, la voce in web.config (requestValidationMode = "2.0")
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" requestValidationMode="2.0"/>
</system.web>
Se vuoi una sola pagina allora, nel tuo file aspx dovresti mettere la prima riga come questa:
<%@ Page EnableEventValidation="false" %>
se hai già qualcosa come <% @ Page quindi aggiungi il resto => EnableEventValidation="false"
%>
Raccomando di non farlo.
In ASP.NET, puoi prendere l'eccezione e fare qualcosa al riguardo, come visualizzare un messaggio amichevole o reindirizzare ad un'altra pagina ... Inoltre c'è la possibilità che tu possa gestire la validazione da solo ...
Visualizza messaggio amichevole:
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();
}
}
Immagino che potresti farlo in un modulo; ma questo lascia aperte alcune domande; cosa succede se si desidera salvare l'input in un database? All'improvviso, poiché stai salvando i dati codificati nel database, finisci per fidarti dell'input che è probabilmente una cattiva idea. Idealmente si memorizzano i dati non codificati grezzi nel database e la codifica ogni volta.
Disabilitare la protezione a livello di pagina e quindi codificare ogni volta è un'opzione migliore.
Anziché utilizzare Server.HtmlEncode, è necessario consultare la più recente/più completa libreria Anti-XSS del team Microsoft ACE.
Le altre soluzioni qui sono belle, tuttavia è un po 'un dolore reale nella parte posteriore di dover applicare [AllowHtml] a ogni singola proprietà del modello, soprattutto se si dispone di oltre 100 modelli su un sito di dimensioni decenti.
Se come me, vuoi trasformare questa funzione (IMHO piuttosto inutile) fuori dal sito, puoi sovrascrivere il metodo Execute () nel tuo controller di base (se non hai già un controller di base ti consiglio di crearne uno, possono essere abbastanza utile per l'applicazione di funzionalità comuni).
protected override void Execute(RequestContext requestContext)
{
// Disable requestion validation (security) across the whole site
ValidateRequest = false;
base.Execute(requestContext);
}
Assicurati di essere in grado di codificare in HTML tutto ciò che viene pompato nelle viste che provengono dall'input dell'utente (è comunque il comportamento predefinito in ASP.NET MVC 3 con Razor, quindi a meno che per qualche strana ragione tu stia usando Html.Raw () tu non dovrebbe richiedere questa funzione.
Disattiva la convalida della pagina se hai veramente bisogno dei caratteri speciali come, >
, <
, ecc. Quindi assicurati che quando l'input dell'utente viene visualizzato, i dati siano codificati in HTML.
Esiste una vulnerabilità di sicurezza con la convalida della pagina, quindi può essere aggirata. Inoltre, la convalida della pagina non deve essere esclusivamente basata.
Causa
ASP.NET per impostazione predefinita convalida tutti i controlli di input per contenuti potenzialmente non sicuri che possono portare a cross-site scripting (XSS) e Iniezioni SQL . In questo modo non consente tale contenuto lanciando l'eccezione di cui sopra. Per impostazione predefinita si consiglia di consentire che questo controllo si verifichi su ogni postback.
Soluzione
In molte occasioni è necessario inviare contenuto HTML alla tua pagina tramite Rich TextBoxes o Rich Text Editors. In tal caso puoi evitare questa eccezione impostando il tag ValidateRequest nella direttiva @Page
su false.
<%@ Page Language="C#" AutoEventWireup="true" ValidateRequest = "false" %>
Ciò disabiliterà la convalida delle richieste per la pagina che hai impostato il flag ValidateRequest su false. Se vuoi disabilitarlo, controlla tutta la tua applicazione web; dovrai impostarlo su false nella sezione web.config <system.web>
<pages validateRequest ="false" />
Per i framework .NET 4.0 o versioni successive è necessario aggiungere anche la seguente riga nella sezione <system.web> per eseguire il lavoro sopra.
<httpRuntime requestValidationMode = "2.0" />
Questo è tutto. Spero che questo ti aiuti a liberarti di questo problema.
Riferimento da: Errore ASP.Net: è stato rilevato un valore Request.Form potenzialmente pericoloso dal client
Ho trovato una soluzione che utilizza JavaScript per codificare i dati, che viene decodificato in .NET (e non richiede jQuery).
Aggiungi la seguente funzione JavaScript alla tua intestazione.
function boo () { targetText = document.getElementById ("HiddenField1"); sourceText = document.getElementById ("userbox"); targetText.value = escape (sourceText.innerText); }Nella tua textarea, includi un onchange che chiama boo ():
<textarea id="userbox" onchange="boo();"></textarea>
Infine, in. NET, usa
string val = Server.UrlDecode(HiddenField1.Value);
Sono consapevole che questo è a senso unico: se hai bisogno di un doppio senso devi essere creativo, ma questo fornisce una soluzione se non puoi modificare il web.config
Ecco un esempio I (MC9000) fornito con 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
});
});
E il markup:
<asp:HiddenField ID="hidHTML" runat="server" />
<textarea id="txtHTML"></textarea>
<asp:Button ID="btnMyPostbackButton" runat="server" Text="Post Form" />
Funziona alla grande Se un hacker tenta di postare bypassando JavaScript, vedrà semplicemente l'errore. È possibile salvare tutti i dati codificati in un database, quindi decifrarli (sul lato server) e analizzare e controllare gli attacchi prima di visualizzarli altrove.
Stavo ottenendo anche questo errore.
Nel mio caso, un utente ha inserito un carattere accentato á
in un nome ruolo (relativo al provider di appartenenze ASP.NET).
Ho passato il nome del ruolo a un metodo per concedere gli utenti a quel ruolo e la richiesta del post $.ajax
stava fallendo miseramente ...
L'ho fatto per risolvere il problema:
Invece di
data: { roleName: '@Model.RoleName', users: users }
Fai questo
data: { roleName: '@Html.Raw(@Model.RoleName)', users: users }
@Html.Raw
ha fatto il trucco.
Stavo ottenendo il nome del ruolo come valore HTML roleName="Cadastro bás"
. Questo valore con entità HTML á
era bloccato da ASP.NET MVC. Ora ottengo il valore del parametro roleName
nel modo in cui dovrebbe essere: roleName="Cadastro Básico"
e il motore ASP.NET MVC non bloccherà più la richiesta.
Puoi anche usare la funzione JavaScript escape (stringa) per sostituire i caratteri speciali. Quindi lato server utilizzare Server. URLDecode (stringa) per tornare indietro.
In questo modo non è necessario disattivare la convalida dell'input e sarà più chiaro agli altri programmatori che la stringa potrebbe avere contenuto HTML.
Ho finito per usare JavaScript prima di ogni postback per verificare i caratteri che non volevi, come ad esempio:
<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;
}
A mio parere, la mia pagina è per lo più data entry e ci sono pochissimi elementi che fanno postback, ma almeno i loro dati vengono mantenuti.
Finché questi sono solo "<" e ">" (e non la doppia citazione stessa) e li stai usando in un contesto come <input value = "this" />, tu sei sicuro (mentre per <textarea> this one </ textarea> saresti ovviamente vulnerabile). Ciò potrebbe semplificare la tua situazione, ma per qualsiasi cosa più usare una delle altre soluzioni pubblicate.
Se stai solo cercando di dire ai tuoi utenti che <and> non devono essere usati MA, non vuoi che l'intero modulo sia processato/postato (e perdi tutto l'input) prima non potresti semplicemente inserire un validatore in tutto il campo per lo screening di quelli (e forse di altri personaggi potenzialmente pericolosi)?
Puoi usare qualcosa come:
var nvc = Request.Unvalidated().Form;
Più tardi, nvc["yourKey"]
dovrebbe funzionare.
Nessuno dei suggerimenti ha funzionato per me. Non volevo disattivare comunque questa funzionalità per l'intero sito Web perché il 99% del tempo non desidera che i miei utenti inseriscano l'HTML nei moduli Web. Ho appena creato il mio lavoro attorno al metodo dato che sono l'unico a usare questa particolare applicazione. Converto l'input in HTML nel codice sottostante e lo inserisco nel mio database.
È possibile automaticamente il campo di codifica HTML in Raccoglitore modello personalizzato. La mia soluzione è diversa, ho inserito un errore in ModelState e ho visualizzato un messaggio di errore vicino al campo. È facile modificare questo codice per la codifica automatica
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);
}
}
In Application_Start:
ModelBinders.Binders.DefaultBinder = new AppModelBinder();
Si noti che funziona solo per i campi modulo. Valore pericoloso non passato al modello del controllore, ma memorizzato in ModelState e può essere nuovamente visualizzato sul modulo con un messaggio di errore.
I caratteri pericolosi nell'URL possono essere gestiti in questo modo:
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();
}
}
È necessario utilizzare il metodo Server.HtmlEncode per proteggere il sito da input pericolosi.
Come indicato nel mio commento a Risposta di Sel , questa è la nostra estensione a un validatore di richieste personalizzate.
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);
}
}
Per coloro che non utilizzano l'associazione modello, che stanno estraendo ogni parametro dal Request.Form, che sono sicuri che il testo di input non causerà danni, c'è un altro modo. Non è una grande soluzione, ma farà il lavoro.
Dal lato client, codificalo come uri e poi invialo.
per esempio:
encodeURIComponent($("#MsgBody").val());
Dal lato server, accettalo e decodificalo come uri.
per esempio:
string temp = !string.IsNullOrEmpty(HttpContext.Current.Request.Form["MsgBody"]) ?
System.Web.HttpUtility.UrlDecode(HttpContext.Current.Request.Form["MsgBody"]) :
null;
o
string temp = !string.IsNullOrEmpty(HttpContext.Current.Request.Form["MsgBody"]) ?
System.Uri.UnescapeDataString(HttpContext.Current.Request.Form["MsgBody"]) :
null;
per favore cerca le differenze tra UrlDecode
e UnescapeDataString
Ultimo ma non meno importante, si prega di notare che i binding di dati di ASP.NET controllano automaticamente codificare i valori durante l'associazione dei dati. Ciò modifica il comportamento predefinito di tutti i controlli ASP.NET (TextBox, Label ecc.) Contenuti in ItemTemplate
. Il seguente esempio dimostra (ValidateRequest
è impostato su 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>
code behind
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
valore: '
TextBox2.Text
valore: &#39;
<script>alert('attack!');</script>
Label1.Text
valore: <script>alert('attack!');</script>
TextBox2.Text
valore: <script>alert('attack!');</script>
Per quelli di noi ancora bloccati su webforms ho trovato la seguente soluzione che ti permette di disabilitare solo la convalida su un campo! (Mi dispiacerebbe disabilitarla per l'intera pagina).
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);
}
}
Ora usa solo <prefix:UnvalidatedTextBox id="test" runat="server" />
invece di <asp:TextBox
, e dovrebbe consentire tutti i caratteri (questo è perfetto per i campi password!)
So che questa domanda riguarda la pubblicazione di moduli, ma vorrei aggiungere alcuni dettagli per le persone che hanno ricevuto questo errore in altre circostanze. Potrebbe anche verificarsi su un gestore utilizzato per implementare un servizio Web.
Supponiamo che il tuo client web mandi POST o PUT richieste usando ajax e mandi json o xml text o raw (un file contenuto) al tuo servizio web. Poiché il tuo servizio web non ha bisogno di ottenere informazioni da un'intestazione Content-Type, il tuo codice JavaScript non ha impostato questa intestazione sulla tua richiesta Ajax. Ma se non si imposta questa intestazione su una richiesta ajax POST/PUT, Safari può aggiungere questa intestazione: "Content-Type: application/x-www-form-urlencoded". Ho osservato che su Safari 6 su iPhone, ma altre versioni di Safari/OS o Chrome potrebbero fare lo stesso. Pertanto, quando si riceve questa intestazione Content-Type parte di .NET Framework presuppone che la struttura dei dati del corpo della richiesta corrisponda a una registrazione in formato html mentre non lo fa e aumenta un'eccezione HttpRequestValidationException. La prima cosa da fare è ovviamente impostare sempre l'intestazione Content-Type su qualsiasi tipo tranne un tipo MIME su una richiesta ajax POST/PUT, anche se è inutile per il tuo servizio web.
Ho anche scoperto questo dettaglio:
In queste circostanze, l'eccezione HttpRequestValidationException viene aumentata quando il codice tenta di accedere alla raccolta HttpRequest.Params. Sorprendentemente, questa eccezione non viene aumentata quando accede alla raccolta HttpRequest.ServerVariables. Questo dimostra che mentre queste due raccolte sembrano essere quasi identiche, si accede ai dati delle richieste attraverso i controlli di sicurezza e l'altro no.
In .Net 4.0 e versioni successive, che è il solito caso, inserire le seguenti impostazioni in system.web
<system.web>
<httpRuntime requestValidationMode="2.0" />
nel mio caso, usando asp: controllo Textbox (Asp.net 4.5), invece di impostare la pagina per validateRequest="false"
che ho usato
<asp:TextBox runat="server" ID="mainTextBox"
ValidateRequestMode="Disabled"
></asp:TextBox>
sulla casella di testo che ha causato l'eccezione.
Una soluzione
Non mi piace disattivare la convalida dei post (validateRequest = "false"). D'altra parte non è accettabile che l'applicazione si blocchi solo perché un utente innocente digita <x
o qualcosa del genere.
Pertanto ho scritto una funzione javascript lato client (xssCheckValidates) che effettua un controllo preliminare. Questa funzione è chiamata quando c'è un tentativo di inviare i dati del modulo, come questo:
<form id="form1" runat="server" onsubmit="return xssCheckValidates();">
La funzione è abbastanza semplice e potrebbe essere migliorata, ma sta facendo il suo lavoro.
Si prega di notare che lo scopo di questo non è quello di proteggere il sistema dall'hacking, ma è pensato per proteggere gli utenti da una brutta esperienza. La convalida della richiesta eseguita sul server è ancora attiva e questa è (parte della) protezione del sistema (nella misura in cui è in grado di farlo).
La ragione per cui dico "parte di" qui è perché ho sentito che la convalida della richiesta integrata potrebbe non essere sufficiente, quindi altri mezzi complementari potrebbero essere necessari per avere una protezione completa. Ma, ancora, la funzione javascript che presento qui ha nothing a che fare con la protezione del sistema. È only pensato per assicurarsi che gli utenti non abbiano una brutta esperienza.
Puoi provarlo qui:
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>
Usa il Server.HtmlEncode("yourtext");
Vedo che c'è molto scritto su questo ... e non ho visto questo menzionato . Questo è disponibile da. NET Framework 4.5
L'opzione ValidateRequestMode per un controllo è una grande opzione . In questo modo gli altri controlli sulla pagina sono ancora protetti. Nessuna modifica web.config necessaria.
protected void Page_Load(object sender, EventArgs e)
{
txtMachKey.ValidateRequestMode = ValidateRequestMode.Disabled;
}