Modello di sicurezza di Windows per sviluppatori di driver

Il modello di sicurezza di Windows si basa su oggetti a protezione diretta. Ogni componente del sistema operativo deve garantire la sicurezza degli oggetti per i quali è responsabile. I driver, pertanto, devono proteggere la sicurezza dei dispositivi e degli oggetti del dispositivo.

Questo argomento riepiloga il modo in cui il modello di sicurezza di Windows si applica ai driver in modalità kernel.

Modello di sicurezza di Windows

Il modello di sicurezza di Windows si basa principalmente sui diritti per oggetto, con un numero ridotto di privilegi a livello di sistema. Gli oggetti che possono essere protetti includono, ma non sono limitati a, processi, thread, eventi e altri oggetti di sincronizzazione, nonché file, directory e dispositivi.

Per ogni tipo di oggetto, la lettura generica, la scrittura e il mapping dei diritti di esecuzione in diritti specifici dell'oggetto dettagliati. Ad esempio, per i file e le directory, i diritti possibili includono il diritto di leggere o scrivere il file o la directory, il diritto di leggere o scrivere attributi di file estesi, il diritto di attraversare una directory e il diritto di scrivere il descrittore di sicurezza di un oggetto.

Il modello di sicurezza prevede i concetti seguenti:

  • Identificatori di sicurezza (SID)
  • Token di accesso
  • Descrittori di sicurezza
  • Elenchi di controllo di accesso (ACL)
  • Privilegi

Identificatori di sicurezza (SID)

Un identificatore di sicurezza (SID, denominato anche entità) identifica un utente, un gruppo o una sessione di accesso. Ogni utente ha un SID univoco, recuperato dal sistema operativo all'accesso.

I SID vengono emessi da un'autorità, ad esempio il sistema operativo o un server di dominio. Alcuni SID sono noti e hanno nomi e identificatori. Ad esempio, il SID S-1-1-0 identifica Tutti (o Mondo).

Token di accesso

Ogni processo ha un token di accesso. Il token di accesso descrive il contesto di sicurezza completo del processo. Contiene il SID dell'utente, il SID dei gruppi a cui appartiene l'utente e il SID della sessione di accesso, nonché un elenco dei privilegi a livello di sistema concessi all'utente.

Per impostazione predefinita, il sistema usa il token di accesso primario per un processo ogni volta che un thread del processo interagisce con un oggetto a protezione diretta. Tuttavia, un thread può rappresentare un account client. Quando un thread rappresenta, ha un token di rappresentazione oltre al proprio token primario. Il token di rappresentazione descrive il contesto di sicurezza dell'account utente che il thread rappresenta. La rappresentazione è particolarmente comune nella gestione di Remote Procedure Call (RPC).

Un token di accesso che descrive un contesto di sicurezza limitato per un thread o un processo viene chiamato token con restrizioni. I SID in un token con restrizioni possono essere impostati solo per negare l'accesso, non consentire l'accesso, agli oggetti a protezione diretta. Inoltre, il token può descrivere un set limitato di privilegi a livello di sistema. Il SID e l'identità dell'utente rimangono invariati, ma i diritti di accesso dell'utente sono limitati mentre il processo usa il token con restrizioni. La funzione CreateRestrictedToken crea un token limitato.

Descrittori di sicurezza

Ogni oggetto Windows denominato ha un descrittore di sicurezza; alcuni oggetti senza nome fanno anche. Il descrittore di sicurezza descrive i SID del proprietario e del gruppo per l'oggetto insieme ai relativi elenchi di controllo di accesso.

Il descrittore di sicurezza di un oggetto viene in genere creato dalla funzione che crea l'oggetto. Quando un driver chiama la routine IoCreateDevice o IoCreateDeviceSecure per creare un oggetto dispositivo, il sistema applica un descrittore di sicurezza all'oggetto dispositivo creato e imposta gli ACL per l'oggetto . Per la maggior parte dei dispositivi, gli ACL vengono specificati nel file INF (Device Information).

Per altre informazioni Sui descrittori di sicurezza nella documentazione del driver del kernel.

Elenchi di controllo di accesso

Controllo di accesso Elenchi (ACL) abilitano il controllo con granularità fine sull'accesso agli oggetti. Un ACL fa parte del descrittore di sicurezza per ogni oggetto.

Ogni ACL contiene zero o più voci Controllo di accesso (ACE). Ogni ACE, a sua volta, contiene un singolo SID che identifica un utente, un gruppo o un computer e un elenco di diritti negati o consentiti per tale SID.

ACL per gli oggetti dispositivo

L'elenco di controllo di accesso per un oggetto dispositivo può essere impostato in uno qualsiasi dei tre modi seguenti:

  • Impostare nel descrittore di sicurezza predefinito per il tipo di dispositivo.
  • Creato a livello di codice dalla funzione RtlCreateSecurityDescriptor e impostato dalla funzione RtlSetDaclSecurityDescriptor .
  • Specificato in Security Descriptor Definition Language (SDDL) nel file INF del dispositivo o in una chiamata alla routine IoCreateDeviceSecure .

Tutti i driver devono usare SDDL nel file INF per specificare gli elenchi di controllo di accesso per gli oggetti del dispositivo.

SDDL è un linguaggio di descrizione estendibile che consente ai componenti di creare elenchi di controllo di accesso in un formato stringa. SDDL viene usato sia dal codice in modalità utente che dal codice in modalità kernel. Nella figura seguente viene illustrato il formato delle stringhe SDDL per gli oggetti dispositivo.

Diagramma che mostra il formato delle stringhe SDDL per gli oggetti dispositivo.

Il valore Access specifica il tipo di accesso consentito. Il valore SID specifica un identificatore di sicurezza che determina a chi si applica il valore di Access, ad esempio un utente o un gruppo.

Ad esempio, la stringa SDDL seguente consente l'accesso a tutto e consente a tutti gli altri (WD) l'accesso in sola lettura:

“D:P(A;;GA;;;SY)(A;;GR;;;WD)”

Il file di intestazione wdmsec.h include anche un set di stringhe SDDL predefinite adatte agli oggetti dispositivo. Ad esempio, il file di intestazione definisce SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_RWX_RES_RWX come indicato di seguito:

"D:P(A;;GA;;;SY)(A;;GRGWGX;;;BA)(A;;GRGWGX;;;WD)(A;;GRGWGX;;;RC)"

Il primo segmento di questa stringa consente il controllo completo del kernel e del sistema operativo (SY) sul dispositivo. Il secondo segmento consente a chiunque del gruppo Administrators predefinito (BA) di accedere all'intero dispositivo, ma non di modificare l'elenco di controllo di accesso. Il terzo segmento consente a tutti (WD) di leggere o scrivere nel dispositivo e il quarto segmento concede gli stessi diritti al codice non attendibile (RC). I driver possono usare le stringhe predefinite come è o come modelli per stringhe specifiche dell'oggetto dispositivo.

Tutti gli oggetti dispositivo in uno stack devono avere gli stessi elenchi di controllo di accesso. La modifica degli elenchi di controllo di accesso in un oggetto dispositivo nello stack modifica gli elenchi di controllo di accesso nell'intero stack di dispositivi.

Tuttavia, l'aggiunta di un nuovo oggetto dispositivo allo stack non modifica gli elenchi di controllo di accesso, quelli del nuovo oggetto dispositivo (se contiene elenchi di controllo di accesso) o quelli di qualsiasi oggetto dispositivo esistente nello stack. Quando un driver crea un nuovo oggetto dispositivo e lo collega all'inizio dello stack, il driver deve copiare gli elenchi di controllo di accesso per lo stack nel nuovo oggetto dispositivo copiando il campo DeviceObject.Characteristics dal driver inferiore successivo.

La routine IoCreateDeviceSecure supporta un subset di stringhe SDDL che usano SID predefiniti, ad esempio WD e SY. Le API in modalità utente e i file INF supportano la sintassi SDDL completa.

Controlli di sicurezza tramite elenchi di controllo di accesso

Quando un processo richiede l'accesso a un oggetto, i controlli di sicurezza confrontano gli ACL per l'oggetto rispetto ai SID nel token di accesso del chiamante.

Il sistema confronta gli ACL in un ordine superiore rigoroso e si arresta sulla prima corrispondenza pertinente. Pertanto, quando si crea un ACL, è consigliabile inserire sempre gli ACL di rifiuto sopra gli ACL di concessione corrispondenti. Gli esempi seguenti illustrano come procede il confronto.

Esempio 1: Confronto di un elenco di controllo di accesso a un token di accesso

Nell'esempio 1 viene illustrato come il sistema confronta un elenco di controllo di accesso al token di accesso per il processo del chiamante. Si supponga che il chiamante voglia aprire un file con ACL visualizzato nella tabella seguente.

ACL di file di esempio

Autorizzazione SID Access
Allow Contabilità Scrittura, eliminazione
Allow Sales Accoda
Nega Legale Accodamento, scrittura, eliminazione
Allow Tutti Lettura

Questo ACL include quattro ACL, che si applicano in particolare ai gruppi Accounting, Sales, Legal e Everyone.

Si supponga quindi che il token di accesso per il processo di richiesta contenga i SID per un utente e tre gruppi, nell'ordine seguente:

Utente Jim (S-1-5-21...)

Contabilità gruppo (S-1-5-22...)

Legale gruppo (S-1-5-23...)

Raggruppa tutti (S-1-1-0)

Quando si confronta un ACL di file con un token di accesso, il sistema cerca innanzitutto un ace per l'utente Jim nell'ACL del file. None viene visualizzato, quindi successivamente cerca un ACE per il gruppo Accounting. Come illustrato nella tabella precedente, un ACE per il gruppo Accounting viene visualizzato come prima voce nell'ACL del file, quindi al processo di Jim viene concesso il diritto di scrivere o eliminare il file e il confronto si arresta. Se l'ACE per il gruppo Legale precede invece l'ACE per il gruppo Accounting nell'elenco di controllo di accesso, il processo verrà negato la scrittura, l'aggiunta e l'eliminazione dell'accesso al file.

Esempio 2: Confronto di un ACL con un token con restrizioni

Il sistema confronta un ACL con un token con restrizioni nello stesso modo in cui confronta quelli in un token che non è limitato. Tuttavia, un SID denial in un token con restrizioni può corrispondere solo a deny ACE in un ACL.

L'esempio 2 mostra come il sistema confronta l'ACL di un file con un token con restrizioni. Si supponga che il file abbia lo stesso ACL illustrato nella tabella precedente. In questo esempio, tuttavia, il processo ha un token con restrizioni che contiene i SID seguenti:

Utente Jim (S-1-5-21...) Negare

Contabilità gruppo (S-1-5-22...) Negare

Legale gruppo (S-1-5-23...) Negare

Raggruppa tutti (S-1-1-0)

L'ACL del file non elenca il SID di Jim, quindi il sistema procede al SID del gruppo Accounting. Anche se l'ACL del file ha un ace per il gruppo Accounting, questo ACE consente l'accesso; pertanto, non corrisponde al SID nel token con restrizioni del processo, che nega l'accesso. Di conseguenza, il sistema procede al SID del gruppo legale. L'ACL per il file contiene un ace per il gruppo Legal che nega l'accesso, pertanto il processo non può scrivere, aggiungere o eliminare il file.

Privilegi

Un privilegio è il diritto per un utente di eseguire un'operazione correlata al sistema nel computer locale, ad esempio il caricamento di un driver, la modifica dell'ora o l'arresto del sistema.

I privilegi sono diversi dai diritti di accesso perché si applicano alle attività e alle risorse correlate al sistema anziché agli oggetti e perché vengono assegnati a un utente o a un gruppo da un amministratore di sistema, anziché dal sistema operativo.

Il token di accesso per ogni processo contiene un elenco dei privilegi concessi al processo. I privilegi devono essere abilitati in modo specifico prima dell'uso. Per altre informazioni sui privilegi, vedere Privilegi nella documentazione del driver kernel.

Scenario del modello di sicurezza di Windows: Creazione di un file

Il sistema usa i costrutti di sicurezza descritti nel modello di sicurezza di Windows ogni volta che un processo crea un handle in un file o oggetto.

Il diagramma seguente mostra le azioni correlate alla sicurezza attivate quando un processo in modalità utente tenta di creare un file.

Diagramma di flusso che illustra le azioni correlate alla sicurezza quando un processo in modalità utente tenta di creare un file.

Il diagramma precedente mostra come il sistema risponde quando un'applicazione in modalità utente chiama la funzione CreateFile . Le note seguenti fanno riferimento ai numeri cerchiati nella figura:

  1. Un'applicazione in modalità utente chiama la funzione CreateFile , passando un nome di file Microsoft Win32 valido.
  2. La modalità utente Kernel32.dll passa la richiesta a Ntdll.dll, che converte il nome Win32 in un nome file di Microsoft Windows NT.
  3. Ntdll.dll chiama la funzione NtCreateFile con il nome file di Windows. All'interno di Ntoskrnl.exe, Gestione I/O gestisce NtCreateFile.
  4. Gestione I/O ripacchetto la richiesta in una chiamata di Gestione oggetti.
  5. Gestione oggetti risolve i collegamenti simbolici e garantisce che l'utente disponga dei diritti di attraversamento per il percorso in cui verrà creato il file. Per altre informazioni, vedere Controlli di sicurezza in Gestione oggetti.
  6. Gestione oggetti chiama il componente di sistema proprietario del tipo di oggetto sottostante associato alla richiesta. Per una richiesta di creazione di file, questo componente è gestione I/O, proprietario di oggetti dispositivo.
  7. Gestione I/O controlla il descrittore di sicurezza per l'oggetto dispositivo rispetto al token di accesso per il processo dell'utente per assicurarsi che l'utente abbia l'accesso necessario al dispositivo. Per altre informazioni, vedere Controlli di sicurezza in Gestione I/O.
  8. Se il processo utente ha l'accesso necessario, Gestione I/O crea un handle e invia una richiesta di IRP_MJ_CREATE al driver per il dispositivo o il file system.
  9. Il driver esegue controlli di sicurezza aggiuntivi in base alle esigenze. Ad esempio, se la richiesta specifica un oggetto nello spazio dei nomi del dispositivo, il driver deve assicurarsi che il chiamante disponga dei diritti di accesso necessari. Per altre informazioni, vedere Controlli di sicurezza nel driver.

Controlli di sicurezza in Gestione oggetti

La responsabilità di controllare i diritti di accesso appartiene al componente di livello più alto in grado di eseguire tali controlli. Se Gestione oggetti può verificare i diritti di accesso del chiamante, lo fa. In caso contrario, Gestione oggetti passa la richiesta al componente responsabile del tipo di oggetto sottostante. Tale componente, a sua volta, verifica l'accesso, se possibile; se non può, passa la richiesta a un componente ancora inferiore, ad esempio un driver.

Gestione oggetti controlla gli elenchi di controllo di accesso per i tipi di oggetto semplici, ad esempio eventi e blocchi mutex. Per gli oggetti con uno spazio dei nomi, il proprietario del tipo esegue controlli di sicurezza. Ad esempio, Gestione I/O viene considerato il proprietario del tipo per oggetti dispositivo e oggetti file. Se Gestione oggetti trova il nome di un oggetto dispositivo o di un oggetto file durante l'analisi di un nome, passa il nome a I/O Manager, come nello scenario di creazione di file illustrato in precedenza. Gestione I/O controlla quindi i diritti di accesso, se possibile. Se il nome specifica un oggetto all'interno di uno spazio dei nomi del dispositivo, Gestione I/O in disattiva il nome al driver del dispositivo (o del file system) e tale driver è responsabile della convalida dell'accesso richiesto.

Controlli di sicurezza in I/O Manager

Quando gestione I/O crea un handle, controlla i diritti dell'oggetto rispetto al token di accesso del processo e quindi archivia i diritti concessi all'utente insieme all'handle. Quando arrivano richieste di I/O successive, Gestione I/O controlla i diritti associati all'handle per assicurarsi che il processo abbia il diritto di eseguire l'operazione di I/O richiesta. Ad esempio, se il processo richiede in seguito un'operazione di scrittura, Gestione I/O controlla i diritti associati all'handle per assicurarsi che il chiamante abbia accesso in scrittura all'oggetto.

Se l'handle è duplicato, i diritti possono essere rimossi dalla copia, ma non aggiunti.

Quando gestione I/O crea un oggetto, converte le modalità di accesso Win32 generiche in diritti specifici dell'oggetto. Ad esempio, i diritti seguenti si applicano a file e directory:

Modalità di accesso Win32 Diritti specifici dell'oggetto
GENERIC_READ ReadData
GENERIC_WRITE WriteData
GENERIC_EXECUTE ReadAttributes
GENERIC_ALL Tutti

Per creare un file, un processo deve avere diritti di attraversamento per le directory padre nel percorso di destinazione. Ad esempio, per creare \Device\CDROM0\Directory\File.txt, un processo deve avere il diritto di attraversare \Device, \Device\CDROM0 e \Device\CDROM0\Directory. I/O Manager controlla solo i diritti di attraversamento per queste directory.

Gestione I/O controlla i diritti di attraversamento quando analizza il nome del file. Se il nome del file è un collegamento simbolico, Gestione I/O lo risolve in un percorso completo e quindi controlla i diritti di attraversamento, a partire dalla radice. Si supponga, ad esempio, che il collegamento simbolico \DosDevices\D sia mappato al nome del dispositivo Windows NT \Device\CDROM0. Il processo deve avere diritti di attraversamento per la directory \Device.

Per altre informazioni, vedere Handle di oggetti e sicurezza degli oggetti.

Controlli di sicurezza nel driver

Il kernel del sistema operativo considera ogni driver, in effetti, come file system con il proprio spazio dei nomi. Di conseguenza, quando un chiamante tenta di creare un oggetto nello spazio dei nomi del dispositivo, I/O Manager verifica che il processo abbia diritti di attraversamento per le directory nel percorso.

Con i driver WDM, Gestione I/O non esegue controlli di sicurezza sullo spazio dei nomi, a meno che l'oggetto dispositivo non sia stato creato specificando FILE_DEVICE_SECURE_OPEN. Quando FILE_DEVICE_SECURE_OPEN non è impostato, il driver è responsabile di garantire la sicurezza dello spazio dei nomi. Per altre informazioni, vedere Controllo dell'accesso dello spazio dei nomi dei dispositivi e Protezione degli oggetti dispositivo.

Per i driver WDF, il flag FILE_DEVICE_SECURE_OPEN viene sempre impostato, in modo che sia presente un controllo del descrittore di sicurezza del dispositivo prima di consentire a un'applicazione di accedere a qualsiasi nome all'interno dello spazio dei nomi del dispositivo. Per altre informazioni, vedere Controllo dell'accesso ai dispositivi nei driver KMDF.

Limiti di sicurezza di Windows

I driver che comunicano tra loro e con i chiamanti in modalità utente di diversi livelli di privilegi possono essere considerati che superano un limite di attendibilità. Un limite di attendibilità è qualsiasi percorso di esecuzione del codice che attraversa un processo con privilegi inferiore in un processo con privilegi più elevati.

Maggiore è la disparità nei livelli di privilegio, più interessante è il limite per gli utenti malintenzionati che vogliono eseguire attacchi come un attacco di escalation dei privilegi contro il driver o il processo di destinazione.

Parte del processo di creazione di un modello di minaccia consiste nell'esaminare i limiti di sicurezza e cercare percorsi imprevisti. Per altre informazioni, vedere Modellazione delle minacce per i driver.

Tutti i dati che superano un limite di attendibilità non sono attendibili e devono essere convalidati.

Questo diagramma mostra tre driver del kernel e due app, una in un contenitore di app e un'app che viene eseguita con diritti di amministratore. Le righe rosse indicano limiti di attendibilità di esempio.

Diagramma che illustra la superficie di attacco del driver con tre driver kernel, un'app in un contenitore di app e un'app con diritti di amministratore.

Poiché il contenitore dell'app può fornire vincoli aggiuntivi e non è in esecuzione a livello di amministratore, il percorso (1) è un percorso di rischio più elevato per un attacco di escalation poiché il limite di attendibilità è compreso tra un contenitore di app ( un processo con privilegi molto basso) e un driver del kernel.

Path (2) è un percorso di rischio inferiore, poiché l'app è in esecuzione con diritti di amministratore e chiama direttamente nel driver del kernel. Amministrazione è già un privilegio abbastanza elevato sul sistema, quindi la superficie di attacco dall'amministratore al kernel è meno di una destinazione interessante agli utenti malintenzionati, ma ancora un limite di attendibilità notevole.

Percorso (3) è un esempio di percorso di esecuzione del codice che supera più limiti di trust che potrebbero essere mancanti se non viene creato un modello di minaccia. In questo esempio esiste un limite di attendibilità tra driver 1 e driver 3, poiché il driver 1 accetta l'input dall'app in modalità utente e lo passa direttamente al driver 3.

Tutti gli input provenienti dal driver dalla modalità utente non sono attendibili e devono essere convalidati. Gli input provenienti da altri driver possono anche non essere attendibili a seconda che il driver precedente fosse solo un semplice pass-through (ad esempio, i dati ricevuti dal driver 1 dall'app 1 , driver 1 non hanno eseguito alcuna convalida sui dati e appena passato al driver 3). Assicurarsi di identificare tutte le superfici di attacco e i limiti di attendibilità e convalidarli, creando un modello di minaccia completo.

Raccomandazioni Sicurezza di Windows modello

  • Impostare elenchi di controllo di accesso predefiniti sicuri nelle chiamate alla routine IoCreateDeviceSecure .
  • Specificare gli ACL nel file INF per ogni dispositivo. Questi ACL possono allentare gli elenchi di controllo di accesso predefiniti, se necessario.
  • Impostare la caratteristica FILE_DEVICE_SECURE_OPEN per applicare le impostazioni di sicurezza degli oggetti dispositivo allo spazio dei nomi del dispositivo.
  • Non definire IOCTLs che consentono di FILE_ANY_ACCESS a meno che tale accesso non possa essere sfruttato in modo dannoso.
  • Usare la routine IoValidateDeviceIoControlAccess per rafforzare la sicurezza su IOCTLS esistenti che consentono di FILE_ANY_ACCESS.
  • Creare un modello di minaccia per esaminare i limiti di sicurezza e cercare percorsi imprevisti. Per altre informazioni, vedere Modellazione delle minacce per i driver.
  • Per altre raccomandazioni sulla sicurezza dei driver, vedere Elenco di controllo per la sicurezza dei driver.

Vedere anche

Protezione degli oggetti dispositivo

Elenco di controllo per la sicurezza dei driver