Joven hacker sonriendo

Hackeamos su software

cero falsos positivos

Inteligencia experta + automatización eficaz

Comprobar Identidad de Llamadas en Servlets

Nuestros ethical hackers explican cómo evitar vulnerabilidades de seguridad mediante la programación segura en Java al comprobar la identidad de llamadas mediante Servlets. La autenticación de identidad es fundamental en cualquier aplicación web para evitar el acceso de usuarios sin privilegios.

Necesidad

Comprobación de la identidad de llamadas mediante programación en Servlets (Java)

Contexto

A continuación se describen las circunstancias bajo las cuales la siguiente solución tiene sentido:

  1. Se dispone de un servidor de aplicaciones o contenedor de Servlets conforme con las especificaciones empresariales de Java que soporte la especificación 3.0 o superior.

Solución

  1. Inicialmente se configuran los usuarios que tendrán acceso a la aplicación. Este paso dependerá del contenedor de servlets que se esté usando y de la fuente de donde se extraen los datos.

  2. En general, la administración de la seguridad debería ser ejercida por el contenedor de tal modo que sea transparente para el servlet.

  3. El API descrita en esta solución, debe ser usada en aquellos casos poco frecuentes en los cuales los métodos del servlet requieren acceso a la información del contexto de seguridad.

  4. La especificación de Servlet 3.0 admite los siguientes métodos para acceder a la información de seguridad de quien está solicitando acceder al mismo:

    • getRemoteUser, determina el nombre de usuario con el cual el cliente se ha autenticado. Este método retorna null en caso de que no se haya autenticado.

    • isUserInRole, determina si un usuario remoto se encuentra en un rol de seguridad específico pasado como argumento, correspondiente al campo role-name del descriptor de despliegue. Si el usuario no se ha autenticado, este método retorna false.

    • getUserPrincipal, determina el nombre principal principal name del usuario actual retornando un objeto de la clase java.security.Principal, el cual posee el método getName que retorna el nombre del usuario. Si el usuario no se ha autenticado, se retorna null.

  5. A continuación se muestra un ejemplo de como usar los métodos. La estructura de carpetas que debe tener la aplicación es:

    estrucutura.bash
    1
    2
    3
    % ls -R *
    src/test:
    TestRemoteUserData.java
    
  6. Se crea el servlet TestRemoteUserData.java, configurando mediante anotaciones cuales serán los roles permitidos.

  7. Primero se especifica que pertenece al paquete test y se importan las clases necesarias para trabajar con servlets HTTP.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    package test;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
  8. Se especifica que el servlet se llamará TestRemoteUserData y que la URL que mapea a este será /TestRemoteUserData.

    1
    @WebServlet("/TestRemoteUserData")
    
  9. Se crea un servlet típico.

    1
    2
    3
    4
    5
    6
    7
    8
    public class TestRemoteUserData extends HttpServlet {
      public TestRemoteUserData() {
        super();
      }
      protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
          response.setContentType("text/html;charset=UTF-8");
          PrintWriter out = response.getWriter();
    
  10. Se crean variables que se utilizarán para almacenar la información del usuario remoto.

    1
    2
    java.security.Principal principal = null;
    String remoteUser = null;
    
  11. Se escribe como parte de la respuesta el resultado de invocar request.isUserInRole para el rol1, request.getRemoteUser y request.getUserPrincipal.getName y request.getAuthType.

  12. Los tres primeros métodos ya han sido explicados anteriormente. getAuthType retorna el mecanismo de autenticación especificado en el descriptor de despliegue.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    try {
      out.println("<h2>Antes de hacer login:</h2>");
      out.println("IsUserInRole rol1: " + request.isUserInRole("rol1") + "<br>");
      out.println("getRemoteUser: " + request.getRemoteUser() + "<br>");
      principal = request.getUserPrincipal();
      if( principal != null )
        remoteUser = principal.getName();
        out.println("getUserPrincipal.getName: " + remoteUser + "<br>");
        out.println("getAuthType: " + request.getAuthType() + "<br><br>");NONE.
    
  13. Se intenta autenticarse usando las credenciales del usuario1 y se muestra de nuevo el resultado de llamar los métodos de request.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    try {
      request.login("usuario1", "clave1"); //manda cookie
      }
      catch(ServletException ex) {
        out.println("No se completó el login. <br>");
        return;
      }
      out.println("<h2>Despues de hacer <strong>login</strong>:</h2>");
      out.println("IsUserInRole rol1: " + request.isUserInRole("rol1") + "<br>");
      out.println("getRemoteUser: " + request.getRemoteUser() + "<br>");
      principal = request.getUserPrincipal();
      remoteUser = null;
      if( principal != null )
        remoteUser = principal.getName();
      out.println("getUserPrincipal.getName: " + remoteUser + "<br>");
      out.println("getAuthType: " + request.getAuthType() + "<br><br>");
    
  14. Se eliminan los datos de autenticación del cliente y se muestra de nuevo el resultado de llamar los métodos de request.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
        request.logout();
        out.println("<h2>Despues de hacer <strong>logout</strong>:</h2>");
        out.println("IsUserInRole rol1: " + request.isUserInRole("rol1") + "<br>");
        out.println("getRemoteUser: " + request.getRemoteUser() + "<br>");
        principal = request.getUserPrincipal();
        remoteUser = null;
        if( principal != null )
          remoteUser = principal.getName();
        out.println("getUserPrincipal.getName: " + remoteUser + "<br>");
        out.println("getAuthType: " + request.getAuthType() + "<br><br>");
       }
       finally {
         out.close();
       }
     }
    }
    
  15. Para probar la aplicación, luego de hacer el despliegue, basta con acceder a la dirección del servlet.

  16. El resultado se muestra a continuación:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    Antes de hacer login:
    IsUserInRole rol1: false
    getRemoteUser: null
    getUserPrincipal.getName: null
    getAuthType: null
    
    Despues de hacer login:
    IsUserInRole rol1: true
    getRemoteUser: usuario1
    getUserPrincipal.getName: usuario1
    getAuthType: NONE
    
    Despues de hacer logout:
    IsUserInRole rol1: false
    getRemoteUser: null
    getUserPrincipal.getName: null
    getAuthType: null
    
  17. Nótese como solo hay información luego de hacer la autenticación y antes de eliminar la información de ésta.

Descargas

Puedes descargar el código fuente pulsando en el siguiente enlace:

TestRemoteUserData.java Servlet que implementa la comprobación de identidad.




Haz un comentario

Estado de los servicios - Términos de Uso