Come evitare l'incremento degli ID esposti in un'API?

7

Guardando post come questo su StackOverflow , il consenso sembra che tu debba nascondere gli ID incrementali dalle API esterne per sicurezza.

Tuttavia, sto riscontrando problemi nell'elaborazione di una buona implementazione.

Non voglio usare Guids come ID, perché come indicato qui , porta alla frammentazione della pagina e quando l'ho fatto prima, il DB aveva problemi di prestazioni (in parte a causa dell'Id).

Mi è venuta in mente la seguente struttura di classe. Ha un int ID, quindi un Guid per l'identificazione esterna. Il problema con questo è che ora significa che ci sono chiamate eccessive al db per inserimenti e aggiornamenti.

Modelli:

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; }
}

Ottenere i dati va bene. Come prima, otteniamo e convertiamo in DTO.

Quando si desidera eseguire un aggiornamento o inserire, i dati tornano con solo gli ID guida su tutti gli oggetti. Non posso semplicemente inviare le entità indietro, come fanno nei tutorial come questo .

Ora ho bisogno di ottenere i dati originali (da Guid, con include), quindi ho bisogno di ottenere i dati relativi (da Guid) e capire cosa fare (qualcosa potrebbe essere stato inserito, cancellato o semplicemente modificato) . Sembra tutto un po 'disordinato e inutilmente loquace con il database.

Questo è solo un caso di più sicuro = più lento, o questo disegno (come sospetto) è in qualche modo inefficiente?

    
posta HockeyJ 05.12.2016 - 18:11
fonte

3 risposte

19

Il consiglio su il post che hai collegato sull'utilizzo dei GUID per le chiavi primarie in cluster è sette anni e quasi certamente un cattivo consiglio oggi. articolo a cui fa riferimento riferimenti SQL Server 7.

Utilizziamo i GUID per ogni chiave primaria nel nostro database ed esponiamo tali GUID negli URL che colpiscono i nostri servizi JSON. Possiamo farlo perché non esponiamo i nostri interni di database al mondo esterno; in assenza di queste informazioni, potresti anche esporre numeri casuali. Non abbiamo nessuno dei problemi di prestazioni previsti in quel post.

I GUID hanno alcune proprietà uniche che li rendono molto utili come chiavi primarie e esterne. Poiché sono globalmente unici, puoi utilizzare un singolo JOIN senza preoccuparti della tabella a cui stai partecipando. A differenza degli ID sequenziali, l'ipotesi di un GUID adiacente è quasi impossibile, per gli stessi motivi che rendono i GUID identificatori ideali in primo luogo.

Il modo ideale per evitare di esporre gli ID incrementali? Utilizza invece i GUID come chiavi primarie. Sebbene i GUID non siano una funzione di sicurezza magica, nessuno dei due è offuscato. Assicurati che il resto della tua sicurezza (SSL, accessi, sicurezza basata sui ruoli, indurimento dalle falsificazioni delle richieste di X-site, ecc. Ecc.) Sia solido per prima e esponendo i GUID per rappresentare ciò che sono progettati per rappresentare comunque (ovvero risorse uniche) sarà l'ultimo dei tuoi problemi.

    
risposta data 05.12.2016 - 20:12
fonte
10

Looking at posts such as this on StackOverflow, the consensus seems to be that you should hide incrementing ID's from external API's for security.

Ogni volta che parli di sicurezza, la tua prima domanda dovrebbe essere: "Da quale minaccia sto proteggendo?" Diamo quindi un'occhiata alle minacce descritte nella domanda che colleghi.

  1. Gli ID sequenziali consentono a un utente malintenzionato di immettere un ID che non appartiene a loro da qualche parte. Se i dati non dispongono di un'autorizzazione appropriata, possono accedere ai dati che non dovrebbero.
  2. Rendono più facile la ricerca dei dati in un attacco di SQL injection.
  3. Potresti esporre alcune informazioni sull'utilizzo del tuo sito.
  4. Potrebbero essere in grado di indovinare l'ID di una sessione (se sono sequenziali) e assumere la sessione di qualcun altro.

Per riassumere, il tema centrale è che l'autore dell'attacco potrebbe avere un'idea di quali siano gli ID nel tuo sistema. Ma questa informazione è per lo più inutile da sola . Un ID deve essere combinato con un'altra vulnerabilità che rende l'ID utilizzabile dall'attaccante. In particolare,

  1. Richiede una vulnerabilità che consenta l'accesso non autorizzato tramite ID.
  2. Richiede una vulnerabilità di SQL injection.
  3. Questo è vero in generale, ma ti interessa?
  4. Richiede la mancanza di verifiche per prevenire il dirottamento di sessione. (Normalmente questo implica un qualche tipo di tecnica di crittografia, quindi gli ID sequenziali dovrebbero essere buttati qui, ma un GUID in testo semplice sarebbe ugualmente vulnerabile una volta ottenuto da un utente malintenzionato.)

Oltre alle statistiche sull'utilizzo del sito, tutte queste vulnerabilità sono molto più pericolose rispetto alla semplice perdita degli ID. Assicurarti che il tuo sistema sia libero da questi buchi di sicurezza spalancati dovrebbe essere una molto priorità per te più che preoccuparti di quale tipo di ID usare e il loro inserimento renderà il tuo ID un'informazione inutile.

Ora pensiamo un po 'su come l'utilizzo dei GUID potrebbe non essere d'aiuto nemmeno qui. Gli aggressori potrebbero ottenere l'accesso anche agli ID GUID utilizzando

  1. Ingegneria sociale : l'utente è spesso il link più debole in sicurezza.
  2. Iniezione SQL : se la tua app è vulnerabile all'iniezione SQL, è molto probabile che un utente malintenzionato possa sfruttare questa vulnerabilità per ottenere comunque gli ID. (Dipende dai dettagli esatti di come hai introdotto la vulnerabilità, ma è sicuramente una possibilità con cui dovresti preoccuparti.)
  3. Dump del database rubato : se un utente malintenzionato viola il server e ottiene una copia completa del DB, ha tutti gli ID (e tutti i dati relativi a password o token memorizzati e qualsiasi altra informazione nel DB ).

I GUID vanno bene, ma la sicurezza non è il loro scopo principale , e non dovresti pensare per un momento che usare GUID ciecamente sia una misura di sicurezza. Sono migliori una forma di sicurezza attraverso l'oscurità, e l'oscurità non è qualcosa su cui il tuo sistema dovrebbe fare affidamento se le informazioni in essa contenute devono essere mantenute private. Concentrati sull'eliminazione delle vulnerabilità che rendono utile l'utilizzo degli ID.

I GUID sono principalmente utili come ID univoco a livello globale, in particolare quando è necessario memorizzare i dati in due posizioni diverse e combinarli in un secondo momento. Se non ne hai bisogno, probabilmente stai bene senza GUID. StackOverflow non li usa per utenti, post o qualsiasi altra cosa, e questo non li espone automaticamente alle vulnerabilità. Se è necessario usarli per nascondere l'utilizzo del sito, è ragionevole. Ma mantenere tali informazioni segrete sarebbe un requisito aziendale che dovresti valutare con chiunque stabilisca i requisiti per la tua applicazione, e l'utilizzo dei GUID probabilmente non sarà l'unico componente per risolvere comunque il problema. Dovresti decidere se utilizzare i GUID in base ai requisiti dell'applicazione, non per una vaga idea di essere "più sicuro".

    
risposta data 06.12.2016 - 01:17
fonte
0
  1. Vai avanti e utilizza i GUID
  2. Non utilizzare un indice cluster.
  3. Se è necessario utilizzare un indice cluster, new NEWSEQUENTIALID () per generarli.

Non sono d'accordo con la dichiarazione di Robert Harvey secondo cui il consiglio di usare GUID è datato. Ci sono post più recenti che parlano di GUID negli indici cluster , include la documentazione di SQL Server 2012 , che suggerisce l'utilizzo di NewSequentialID () se è necessario utilizzare GUID in un indice cluster. Quel consiglio è ancora attuale oggi.

    
risposta data 05.12.2016 - 23:23
fonte

Leggi altre domande sui tag