¿Cómo evitar que las ID incrementales se expongan en una API?

7

Mirando publicaciones como esto en StackOverflow el consenso Parece ser que debería ocultar las IDs incrementales de las API externas para la seguridad.

Sin embargo, tengo problemas para encontrar una buena implementación.

No quiero usar Guids como ID, porque como se indica en aquí , conduce a la fragmentación de la página y cuando lo hice antes, la base de datos tenía problemas de rendimiento (en parte debido a los identificadores).

Se me ocurrió la siguiente estructura de clase. Tiene un int ID, luego un Guid para la identificación externa. El problema con esto es que ahora significa que hay demasiadas llamadas a la base de datos para inserciones y actualizaciones.

Modelos:

public class Blog
{
    public int BlogId { get; set; }
    public Guid BlogGuid { get; set; } = Guid.NewGuid();
    public string Url { get; set; }
    public List<Post> Posts { get; set; }
}

public class Post
{
    public int PostId { get; set; }
    public Guid PostGuid { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }

    public int BlogId { get; set; }
    public Blog Blog { get; set; }
}

DTO:

public class BlogDto
{
    // No int id on dto
    public string Url { get; set; }
    public Guid BlogGuid { get; set; }
    public List<PostDto> Posts { get; set; }
}

public class PostDto
{
    // No int id on dto
    public Guid PostGuid { get; set; }  
    public string Title { get; set; }
    public string Content { get; set; }

    public BlogDto Blog { get; set; }
}

Obtener los datos está bien. Como antes, solo obtenemos y convertimos al DTO.

Al querer hacer una actualización o inserción, los datos regresan con solo los ID de Guid en todos los objetos. No puedo devolver las entidades, como lo hacen en los tutoriales, como esto .

Ahora necesito obtener los datos originales (por Guid, con incluye), luego necesito obtener los datos relacionados (por Guid) y averiguar qué hacer (algo podría haber sido insertado, eliminado o simplemente modificado) . Todo se siente un poco desordenado e innecesariamente conversador con la base de datos.

¿Esto es solo un caso de más seguro = más lento, o es este diseño (como sospecho) de alguna manera ineficiente?

    
pregunta HockeyJ 05.12.2016 - 18:11

3 respuestas

19

El consejo en la publicación que vinculó sobre el uso de GUID para las claves primarias agrupadas es Siete años de edad y casi sin duda un mal consejo hoy. El artículo al que hace referencia hace referencia a SQL Server 7.

Usamos GUID para cada clave principal en nuestra base de datos y exponemos esos GUID en las URL que llegan a nuestros servicios JSON. Podemos hacer esto porque no exponemos nuestras bases de datos internas al mundo exterior; A falta de esta información, también podría estar exponiendo números al azar. No tenemos ninguno de los problemas de rendimiento que se prevén en esa publicación.

Los GUID tienen algunas propiedades únicas que los hacen muy útiles como claves primarias y externas. Debido a que son únicos a nivel mundial, puede usar un solo JOIN sin preocuparse de a qué tabla se está uniendo. A diferencia de los ID secuenciales, adivinar un GUID vecino es casi imposible, por las mismas razones que hacen que los GUID sean los identificadores ideales en primer lugar.

¿La forma ideal de evitar la exposición de ID incrementales? Utilice GUID como claves primarias en su lugar. Si bien los GUID no son una característica de seguridad mágica, tampoco es una ofuscación. Asegúrese de que el resto de su seguridad (SSL, inicios de sesión, seguridad basada en roles, fortalecimiento de las falsificaciones de solicitud de X-site, etc.) sea sólido primero, y exponga los GUID para representar lo que están diseñados para representar de todos modos (es decir, recursos únicos) será el menor de tus problemas.

    
respondido por el Robert Harvey 05.12.2016 - 20:12
10
  

Al ver publicaciones como esta en StackOverflow, el consenso parece ser que debería ocultar las ID de incremento de las API externas para la seguridad.

Cuando esté hablando de seguridad, su primera pregunta debería ser: "¿De qué amenaza estoy protegiendo?" Así que echemos un vistazo a las amenazas descritas en la pregunta que vincula.

  1. Las ID secuenciales permiten que un atacante ingrese una ID que no les pertenece en algún lugar. Si los datos no tienen la autorización adecuada a su alrededor, pueden acceder a los datos que no deberían.
  2. Facilitan la búsqueda de datos en un ataque de inyección SQL.
  3. Puede exponer cierta información sobre la cantidad de uso que está obteniendo su sitio.
  4. Es posible que puedan adivinar un ID de sesión (si fueran secuenciales) y tomar el control de la sesión de otra persona.

Para resumir, el tema central es que el atacante podría tener alguna idea de qué ID están en su sistema. Pero esta información es en su mayoría inútil por sí misma . Un ID debe combinarse con otra vulnerabilidad que permita que el atacante pueda utilizar el ID. Específicamente,

  1. Requiere una vulnerabilidad que permite el acceso no autorizado a través de ID.
  2. Requiere una vulnerabilidad de inyección SQL.
  3. Esto es cierto en términos generales, pero ¿te importa?
  4. Requiere falta de verificación para evitar el secuestro de la sesión. (Esto normalmente implica algún tipo de técnica de encriptación, por lo que las identificaciones secuenciales en realidad se deben descartar aquí. Sin embargo, un GUID de texto sin formato sería igualmente vulnerable una vez que lo haya obtenido un atacante).

Aparte de las estadísticas de uso del sitio, todas estas son vulnerabilidades mucho más peligrosas que simplemente filtrar sus ID. Asegurarse de que su sistema esté libre de estos otros vacíos de seguridad debe ser una prioridad mucho más importante para usted que preocuparse por el tipo de identificación que debe usar, y conectarlos hará que su identificación sea una pieza de información inútil.

Ahora pensemos un poco en cómo el uso de GUID puede que no ayude aquí. Los atacantes podrían obtener acceso incluso a ID de GUID usando

  1. Ingeniería social : el usuario suele ser el enlace más débil en seguridad.
  2. Inyección de SQL : si su aplicación es vulnerable a la inyección de SQL, es muy posible que un atacante pueda usar esta vulnerabilidad para obtener los ID de todos modos. (Depende de los detalles exactos de cómo introdujo la vulnerabilidad, pero definitivamente es una posibilidad que debería preocuparle).
  3. Volcado de base de datos robada : si un atacante infringe su servidor y obtiene una copia completa de la base de datos, tiene todos los ID (y toda la contraseña o los datos del token que almacenó y cualquier otra información en la base de datos). ).

Los GUID están bien, pero la seguridad no es su propósito principal , y no debe pensar por un momento que el uso ciego de GUID es una medida de seguridad. Están en mejor una forma de seguridad a través de la oscuridad, y la oscuridad no es algo en lo que su sistema deba confiar si la información que contiene debe mantenerse en privado. Concéntrese en evitar las vulnerabilidades que hacen que sea útil tener ID.

Los

GUID son principalmente útiles como una identificación única a nivel mundial, especialmente cuando necesita almacenar datos en dos lugares diferentes y luego combinarlos más tarde. Si no necesita esto, entonces probablemente esté bien sin GUID. StackOverflow no los usa para usuarios, publicaciones o cualquier otra cosa después de todo, y esto no los expone automáticamente a vulnerabilidades. Si necesita usarlos para ocultar la cantidad de uso que recibe su sitio, eso es razonable. Pero mantener esa información en secreto sería un requisito comercial que debe evaluar con quien establezca los requisitos para su aplicación, y el uso de GUID probablemente no sea el único componente para resolver ese problema de todos modos. Debería decidir si usar GUID según los requisitos de su aplicación, no por una vaga noción de ser "más seguro".

    
respondido por el jpmc26 06.12.2016 - 01:17
0
  1. Continúa y usa los GUID
  2. No utilice un índice agrupado.
  3. Si debe usar un índice agrupado, nuevo NEWSEQUENTIALID () para generarlos.

No estoy de acuerdo con la afirmación de Robert Harvey de que el consejo contra el uso de GUID tiene fecha. Hay publicaciones más recientes que hablan sobre GUID en índices agrupados , incluida la documentación de SQL Server 2012 , que sugiere usar NewSequentialID () Si debe usar GUIDs en un índice agrupado. Ese consejo sigue siendo relevante hoy.

    
respondido por el Moby Disk 05.12.2016 - 23:23

Lea otras preguntas en las etiquetas