Elenco di controllo per la sicurezza degli autisti
Questo articolo fornisce un elenco di controllo per la sicurezza dei driver che consente agli sviluppatori di driver di ridurre il rischio di compromissione dei driver. La sicurezza dei driver è fondamentale e influisce direttamente sull'affidabilità. Quando Windows rileva che è in corso un accesso errato alla memoria, il sistema operativo viene arrestato e viene visualizzata una schermata di errore blu. In qualità di partner Windows, è necessario lavorare per ridurre l'impatto significativo che un driver non riuscito ha sulla vita dei nostri clienti.
Per altre informazioni sui vantaggi offerti da un driver sicuro e affidabile, vedere Driver security guidance.
Panoramica della sicurezza dei driver
Un difetto di sicurezza è qualsiasi difetto che consente a un utente malintenzionato di causare un malfunzionamento di un driver in modo che consenta a un utente malintenzionato di ottenere accesso non autorizzato, modificare il sistema o compromettere i dati, causando potenzialmente l'arresto anomalo del sistema o diventare inutilizzabile. Inoltre, le vulnerabilità nel codice del driver possono consentire a un utente malintenzionato di accedere al kernel, creando una possibilità di compromettere l'intero sistema operativo.
Quando la maggior parte degli sviluppatori sta lavorando sul driver, il loro obiettivo è quello di far funzionare correttamente il driver e non sul fatto che un utente malintenzionato tenti di sfruttare le vulnerabilità all'interno del codice. Dopo il rilascio di un driver, tuttavia, gli utenti malintenzionati possono tentare di esaminare e identificare le vulnerabilità di sicurezza. Gli sviluppatori devono considerare questi problemi durante la fase di progettazione e implementazione per ridurre al minimo la probabilità di tali vulnerabilità. L'obiettivo è eliminare tutti i difetti di sicurezza noti prima del rilascio del driver.
La creazione di driver più sicuri richiede la collaborazione dell'architetto di sistema (pensando coscientemente alle potenziali minacce al driver), lo sviluppatore implementa il codice (codificando in modo difensivo le operazioni comuni che possono essere l'origine degli exploit) e il team di test (cercando in modo proattivo di individuare debolezze e vulnerabilità). Coordinando correttamente tutte queste attività, la sicurezza del conducente è notevolmente migliorata.
Oltre a evitare i problemi associati a un driver attaccato, molti dei passaggi descritti, ad esempio l'uso più preciso della memoria kernel, aumenteranno l'affidabilità del driver. Ciò riduce i costi di supporto e aumenta la soddisfazione dei clienti con il prodotto. Il completamento delle attività nell'elenco di controllo seguente consentirà di raggiungere tutti questi obiettivi.
Elenco di controllo per la sicurezza:Completare l'attività di sicurezza descritta in ognuno di questi argomenti.
Verificare che sia necessario un driver del kernel
Gestire il controllo di accesso dei driver
Controllare l'accesso ai driver solo per software
Seguire le linee guida per la codifica sicura dei driver
Implementare il codice compatibile con HVCI
Seguire le procedure consigliate specifiche per la tecnologia
Aggiungere annotazioni SAL al codice driver
Eseguire la revisione del codice peer
Eseguire l'analisi delle minacce
Usa CodeQL per controllare il codice del driver
Usare Driver Verifier per verificare la presenza di vulnerabilità
Verificare il codice con i test del programma di compatibilità hardware
Verifica i driver pronti per la spedizione con strumenti come BinSkim e SignTool
Non firmare il codice del driver di test per la produzione
Rivedere le risorse per la programmazione sicura
Esamina il riepilogo dei punti chiave
Verificare che sia necessario un driver del kernel
punto della checklist di sicurezza n. 1:Conferma che è necessario un driver del kernel e che un approccio a rischio inferiore, come un servizio o un'app di Windows, non sia un'opzione migliore.
I driver del kernel risiedono nel kernel di Windows e un problema durante l'esecuzione nel kernel può esporre l'intero sistema operativo. Se è disponibile un'altra opzione, è probabile che il costo sia inferiore e abbia meno rischi associati rispetto alla creazione di un nuovo driver del kernel.
Per ulteriori informazioni sull'uso dei driver Windows predefiniti, vedere Hai bisogno di scrivere un driver?.
Per informazioni sull'uso delle attività in background, vedere Sostieni la tua app con le attività in background.
Per informazioni sull'uso dei servizi Windows, vedere Services.
Usare i driver framework
Elemento dell'elenco di controllo della sicurezza n. 2:Usare i framework driver per ridurre le dimensioni del codice e aumentarne l'affidabilità e la sicurezza.
Usare i framework di driver di Windows per ridurre le dimensioni del codice e aumentarne l'affidabilità e la sicurezza. Per iniziare, rivedere Uso di WDF per sviluppare un driver. Per informazioni sull'uso della User Mode Driver Framework (UMDF) a rischio inferiore, vedere Scelta di un modello di driver.
La scrittura di un driver di vecchio stile
Il codice sorgente di Windows Driver Framework (WDF) è open source e disponibile in GitHub. Si tratta dello stesso codice sorgente WDF fornito in Windows. È possibile eseguire il debug del driver in modo più efficace quando è possibile seguire le interazioni tra il driver e WDF. Scaricarlo da https://github.com/Microsoft/Windows-Driver-Frameworks.
DMF - Driver Module Framework (Quadro del Modulo Driver)
Prendere in considerazione l'uso del Driver Module Framework (DMF) nel progetto del driver. Sviluppato dal team di Microsoft Surface, DMF è un framework che consente la creazione di oggetti WDF denominati moduli DMF. Il codice per questi moduli DMF può essere condiviso tra driver diversi. DMF fornisce inoltre una libreria di moduli DMF sviluppati per i driver e offrono il riutilizzo del codice per attività quali la gestione di thread e I/O. Un modulo DMF viene usato per incapsulare le attività del driver in unità più piccole. Ogni modulo è indipendente e ha un proprio codice, contesto e callback, semplificando il riutilizzo. Per altre informazioni, vedere Introducing Driver Module Framework e la documentazione del sito GitHub .
Gestire il controllo di accesso dei driver
voce dell'elenco di controllo della sicurezza n. 3:Esamina il driver per accertarti di controllare correttamente l'accesso.
Gestione del controllo di accesso dei driver - WDF
I driver devono funzionare per impedire agli utenti di accedere in modo non appropriato ai dispositivi e ai file di un computer. Per impedire l'accesso non autorizzato a dispositivi e file, è necessario:
Assegnare un nome agli oggetti dispositivo solo quando necessario. Gli oggetti dispositivo denominati sono in genere necessari solo per motivi legacy, ad esempio se si dispone di un'applicazione che prevede di aprire il dispositivo usando un nome specifico o se si usa un dispositivo/controllo non PNP. I driver WDF non devono denominare il proprio FDO del dispositivo PnP per creare un collegamento simbolico usando WdfDeviceCreateSymbolicLink.
Proteggere l'accesso a oggetti e interfacce del dispositivo.
Per consentire alle applicazioni o ad altri driver WDF di accedere al PDO del dispositivo PnP, è consigliabile usare le interfacce del dispositivo. Per ulteriori informazioni, vedere Utilizzo delle interfacce dei dispositivi. Un'interfaccia del dispositivo funge da collegamento simbolico al PDO dello stack di dispositivi.
Uno dei modi migliori per controllare l'accesso al PDO consiste nel specificare una stringa SDDL nell'INF. Se la stringa SDDL non è presente nel file INF, Windows applica un descrittore di sicurezza predefinito. Per ulteriori informazioni, consultare Protezione degli oggetti dispositivo e SDDL per gli oggetti dispositivo.
Per altre informazioni sul controllo dell'accesso, vedere:
Controllare l'accesso ai dispositivi nei driver KMDF
Nomi, descrittori di sicurezza e classi di dispositivi - Rendere accessibili gli oggetti dispositivo... e SICURO dal gennaio febbraio 2017 la newsletter NT Insider pubblicata da OSR.
Gestione del controllo di accesso dei driver - WDM
Se si usa un driver WDM e si usa un oggetto dispositivo denominato, è possibile usare IoCreateDeviceSecure e specificare uno SDDL per proteggerlo. Quando si implementa IoCreateDeviceSecure specificare sempre un GUID di classe personalizzato per DeviceClassGuid. Non è consigliabile specificare un GUID di classe esistente qui. In questo modo è possibile interrompere le impostazioni di sicurezza o la compatibilità per altri dispositivi appartenenti a tale classe. Per altre informazioni, vedere WdmlibIoCreateDeviceSecure.
Per altre informazioni, vedere:
Controllo dell'accesso ai dispositivi
Controllo dell'accesso ai namespace dei dispositivi
modello di sicurezza di Windows per sviluppatori di driver
Gerarchia dei rischi degli identificatori di sicurezza (SID)
La sezione seguente descrive la gerarchia di rischi dei SID comuni usati nel codice del driver. Per informazioni generali su SDDL, vedere SDDL per gli oggetti dei dispositivi, stringhe SIDe sintassi delle stringhe SDDL.
È importante comprendere che se i chiamanti con privilegi inferiori sono autorizzati ad accedere al kernel, il rischio di codice è aumentato. In questo diagramma di riepilogo, il rischio aumenta man mano che si consentono agli SID con privilegi inferiori di accedere alle funzionalità del driver.
SY (System)
\/
BA (Built-in Administrators)
\/
LS (Local Service)
\/
BU (Built-in User)
\/
AC (Application Container)
Seguendo il principio di sicurezza dei privilegi minimi generali, configurare solo il livello minimo di accesso necessario per il funzionamento del driver.
Controllo di sicurezza granulare IOCTL di WDM
Un IOCTL (Input/Output Control) in Windows è una chiamata di sistema per operazioni di input/output specifiche del dispositivo. IOCTLs vengono usati dalle applicazioni per comunicare con i driver di dispositivo, consentendo loro di inviare comandi o richiedere informazioni dall'hardware. Per altre informazioni, vedere Introduzione ai codici di controllo I/O e Richiesta di I/O di esempio - Panoramica.
Per gestire ulteriormente la sicurezza quando IOCTLs vengono inviati dai chiamanti in modalità utente, il codice del driver può includere la funzione IoValidateDeviceIoControlAccess. Questa funzione consente a un driver di controllare i diritti di accesso. Dopo aver ricevuto un IOCTL, un driver può chiamare IoValidateDeviceIoControlAccess, specificando FILE_READ_ACCESS, FILE_WRITE_ACCESS o entrambi.
L'implementazione di un controllo di sicurezza IOCTL granulare non sostituisce la necessità di gestire l'accesso ai driver usando le tecniche descritte in precedenza.
Per altre informazioni, vedere Definizione di codici di controllo I/O e problemi di sicurezza per i codici di controllo I/O.
Controllare l'accesso ai driver software esclusivamente
elemento elenco di controllo della sicurezza n. 4:Se verrà creato un driver solo software, è necessario implementare un controllo di accesso aggiuntivo.
I driver del kernel solo software non usano il plug-and-play (PnP) per associarsi con ID hardware specifici e possono essere eseguiti su qualsiasi PC. Tale driver può essere usato per scopi diversi da quello originariamente previsto, creando un vettore di attacco.
Poiché i driver del kernel solo software contengono rischi aggiuntivi, devono essere limitati all'esecuzione su hardware specifico, ad esempio usando un ID PnP univoco per abilitare la creazione di un driver PnP o controllando la tabella SMBIOS per la presenza di hardware specifico.
Si supponga, ad esempio, che OEM Fabrikam voglia distribuire un driver che consenta un'utilità di overclocking per i propri sistemi. Se questo driver solo software dovesse essere eseguito su un sistema di un OEM diverso, potrebbe provocare instabilità o danneggiamento del sistema. I sistemi di Fabrikam devono includere un ID PnP univoco per abilitare la creazione di un driver PnP aggiornabile anche tramite Windows Update. Se non è possibile e Fabrikam crea un driver legacy, tale driver deve trovare un altro metodo per verificare che sia in esecuzione su un sistema Fabrikam, ad esempio, esaminando la tabella SMBIOS prima di abilitare qualunque funzionalità.
Seguire le linee guida per la codifica sicura dei driver
elemento elenco di controllo per la sicurezza n. 5:Esaminare il codice e rimuovere eventuali vulnerabilità del codice note.
L'attività principale della creazione di driver sicuri consiste nell'identificare le aree nel codice che devono essere modificate per evitare vulnerabilità software note. Molte di queste vulnerabilità software note gestiscono il monitoraggio rigoroso dell'uso della memoria per evitare problemi con altri utenti sovrascrivendo o compromettendo in altro modo i percorsi di memoria usati dal driver.
Gli strumenti di analisi del codice, ad esempio CodeQL e test specifici del driver, possono essere usati per individuare, alcuni, ma non tutti, di queste vulnerabilità. Questi strumenti e test sono descritti più avanti in questo argomento.
Buffer di memoria
Controllare sempre le dimensioni dei buffer di input e di output per assicurarsi che i buffer possano contenere tutti i dati richiesti. Per altre informazioni, vedere Errore di controllo delle dimensioni dei buffer.
Inizializzare correttamente tutti i buffer di output con zeri prima di restituirli al chiamante. Per altre informazioni, vedere Errore di inizializzazione dei buffer di output.
Convalidare i buffer a lunghezza variabile. Per altre informazioni, vedere Errore di convalida dei buffer Variable-Length. Per altre informazioni sull'uso dei buffer e sull'uso di ProbeForRead per convalidare l'indirizzo di un buffer, vedere Buffer Handling.
Usare il metodo appropriato per accedere ai buffer di dati con IOCTLs
Una delle principali responsabilità di un driver Di Windows consiste nel trasferire i dati tra applicazioni in modalità utente e i dispositivi di un sistema. I tre metodi per l'accesso ai buffer di dati sono illustrati nella tabella seguente.
Tipo di buffer IOCTL | Sommario | Per altre informazioni |
---|---|---|
METHOD_BUFFERED | Consigliato per la maggior parte delle situazioni | Uso dell'I/O bufferizzato |
METHOD_IN_DIRECT o METHOD_OUT_DIRECT | Usato in alcune operazioni di I/O hardware ad alta velocità | uso di I/O diretto |
METODO_NESSUNO | Evitare, se possibile, | Utilizzo di I/O né bufferizzati né diretti |
In generale, l'I/O memorizzato nel buffer è consigliato perché fornisce i metodi di buffering più sicuri. Tuttavia, anche quando si usa l'I/O memorizzato nel buffer esistono rischi, ad esempio puntatori incorporati che devono essere mitigati.
Per altre informazioni sull'uso dei buffer in IOCTLs, vedere Metodi di per l'accesso ai buffer dei dati.
Errori nell'uso di I/O in modalità buffer IOCTL
Controllare le dimensioni dei buffer correlati a IOCTL. Per altre informazioni, vedere Errore di controllo delle dimensioni dei buffer.
Inizializzare correttamente i buffer di output. Per altre informazioni, vedere Errore di inizializzazione dei buffer di output.
Convalidare correttamente i buffer a lunghezza variabile. Per altre informazioni, vedere Errore di convalida dei buffer Variable-Length.
Quando si usa l'I/O memorizzato nel buffer, assicurarsi di restituire la lunghezza corretta per l'OutputBuffer nel campo Informazioni della struttura IO_STATUS_BLOCK. Non restituire direttamente la lunghezza direttamente da una richiesta READ. Si consideri, ad esempio, una situazione in cui i dati restituiti dallo spazio utente indicano che è presente un buffer 4K. Se il driver deve restituire effettivamente solo 200 byte, ma restituisce invece solo 4K nel campo Informazioni si è verificata una vulnerabilità di divulgazione di informazioni. Questo problema si verifica perché, nelle versioni precedenti di Windows, il buffer utilizzato dal gestore di I/O per l'I/O con buffer non viene azzerato. Di conseguenza, l'app utente recupera i 200 byte originali di dati più 4K-200 byte di qualsiasi elemento nel buffer (contenuto del pool non di paging). Questo scenario può verificarsi con tutti gli usi di I/O bufferizzato e non solo con ioctls.
Errori nell'I/O diretto di IOCTL
Gestire correttamente i buffer di lunghezza zero. Per altre informazioni, vedere Errors in Direct I/O.
Errori nel riferimento agli indirizzi dello spazio utente
Convalidare i puntatori incorporati nelle richieste di I/O memorizzate nel buffer. Per ulteriori informazioni, vedere Errori nel Riferimento User-Space Indirizzi.
Convalidare qualsiasi indirizzo nello spazio utente prima di provare a usarlo usando API come ProbeForRead.
Il codice del driver deve usare correttamente la memoria
Tutte le allocazioni del pool di driver devono trovarsi nel pool non eseguibile (NX). L'uso di pool di memoria NX è intrinsecamente più sicuro rispetto all'uso di pool eseguibili non paginati (NP) e offre una migliore protezione dagli attacchi di overflow.
Per consentire ai driver di supportare la virtualizzazione HVCI, sono previsti requisiti di memoria aggiuntivi. Per altre informazioni, vedere Implementare codice compatibile con HVCI più avanti in questo articolo.
Vulnerabilità TOCTOU
Esiste una vulnerabilità potenziale tempo di verifica dell'uso (TOCTOU) quando si usa L/O diretto (per IOCTLs o per lettura/scrittura). Tenere presente che quando il driver accede al buffer dei dati utente, l'app utente può accedere contemporaneamente allo stesso buffer di dati.
Per gestire questo rischio, copiare tutti i parametri che devono essere convalidati dal buffer dei dati utente alla memoria che è accessibile esclusivamente dalla modalità kernel, ad esempio lo stack o il pool. Dopo che i dati non sono accessibili dall'applicazione utente, convalidare e quindi operare sui dati passati.
Letture e scritture nei registri specifici del modello MSR
Gli intrinseci del compilatore, ad esempio __readmsr e __writemsr, possono essere usati per accedere ai registri specifici del modello. Se questo accesso è necessario, il driver deve sempre verificare che il registro in lettura o scrittura sia vincolato all'indice o all'intervallo previsto.
Per ulteriori informazioni ed esempi di codice, vedere Consente di leggere/scrivere gli MSR in Procedure consigliate per vincolare il comportamento con privilegi elevati nei driver in modalità kernel.
Manici
- Convalidare gli handle passati tra la memoria in modalità utente e quella in modalità kernel. Per altre informazioni, vedere Gestione degli handle e Mancata convalida degli handle degli oggetti.
Oggetti dei dispositivi
Proteggere gli oggetti del dispositivo. Per altre informazioni, vedere Protezione degli oggetti dispositivo.
Convalidare gli oggetti del dispositivo. Per altre informazioni, vedere Errore di convalida degli oggetti dispositivo.
IRP
I pacchetti di richieste I/O windows vengono usati per comunicare le richieste di I/O tra il sistema operativo e i driver in modalità kernel, incapsulando tutte le informazioni necessarie nel pacchetto. I pacchetti di richiesta I/O facilitano il trasferimento asincrono dei dati, la sincronizzazione e la gestione degli errori, garantendo comunicazioni efficienti e affidabili con i dispositivi hardware. Per ulteriori informazioni, consultare i pacchetti di richiesta I/O e la Panoramica del modello di I/O di Windows.
WDF e IRP
Uno dei vantaggi dell'uso di WDF è che i driver WDF in genere non accedono direttamente agli IRP. Ad esempio, il framework converte gli IRP WDM che rappresentano operazioni di lettura, scrittura e controllo I/O del dispositivo in oggetti di richiesta del framework che KMDF/UMDF ricevono nelle code I/O. Quando possibile, è consigliabile usare WDF.
Se è necessario scrivere un driver WDM, esaminare le indicazioni seguenti.
Gestire correttamente i buffer di I/O IRP
Esaminare questi argomenti che illustrano come convalidare i valori di input IRP:
DispatchReadWrite utilizzando I/O con buffering
DispatchReadWrite utilizzando I/O diretto
Errori in I/O diretto
Convalidare i valori associati a un IRP, ad esempio indirizzi e lunghezze del buffer.
Se si sceglie di utilizzare la modalità Neither I/O, tenere presente che, a differenza delle operazioni di Lettura e Scrittura, e diversamente da I/O memorizzato nel buffer e I/O diretto, quando si utilizza Neither I/O con IOCTL, i puntatori e le lunghezze del buffer non vengono convalidati dal Gestore I/O.
Gestire correttamente le operazioni di completamento di IRP
Un driver non deve mai completare un IRP con un valore di stato di STATUS_SUCCESS
a meno che non lo supporti ed elabori effettivamente. Per informazioni sui modi corretti per gestire le operazioni di completamento IRP, vedere Completamento IRP.
Gestire lo stato IRP in sospeso del driver
Il driver deve contrassegnare l'IRP in sospeso prima di salvare l'IRP, e dovrebbe prendere in considerazione l'inclusione sia della chiamata a IoMarkIrpPending sia dell'assegnazione in una sequenza sincronizzata. Per ulteriori informazioni, vedere Mancato controllo dello stato di un driver e Trattenere gli IRP in ingresso quando un dispositivo è in pausa.
Gestire correttamente le operazioni di annullamento dell'IRP
Le operazioni di annullamento possono essere difficili da scrivere correttamente perché in genere vengono eseguite in modo asincrono. I problemi nel codice che gestisce le operazioni di annullamento possono andare inosservati per molto tempo, perché questo codice in genere non viene eseguito di frequente in un sistema in esecuzione. Assicurarsi di leggere e comprendere tutte le informazioni fornite in Annullamento degli IRP. Prestare particolare attenzione a sincronizzare i di annullamento di IRP e punti da considerare quando si annullano i runtime di integrazione.
Un modo consigliato per ridurre al minimo i problemi di sincronizzazione associati alle operazioni di annullamento consiste nell'implementare una coda IRP annullabile.
Gestire correttamente le operazioni di pulizia e chiusura di IRP
Assicurati di comprendere la differenza tra le richieste IRP_MJ_CLEANUP e IRP_MJ_CLOSE. Le richieste di pulizia arrivano dopo che un'applicazione chiude tutti gli handle di un oggetto file, ma a volte prima che tutte le richieste di I/O siano state completate. Le richieste di chiusura arrivano dopo che tutte le richieste di I/O per l'oggetto file sono state completate o annullate. Per altre informazioni, vedere quanto segue:
DispatchCreate, DispatchClose e DispatchCreateClose Routinese
Errori durante la gestione delle operazioni di pulizia e chiusura
Per ulteriori informazioni sulla gestione corretta dei pacchetti di richiesta di I/O, vedere Errori aggiuntivi nella gestione dei pacchetti di richiesta di I/O.
Usare funzioni sicure
Usare funzioni stringa sicure. Per ulteriori informazioni, vedere Utilizzo delle Funzioni di Stringa Sicure.
Usare funzioni aritmetiche sicure. Per ulteriori informazioni, vedere routine di libreria degli interi sicuri.
Usare funzioni di conversione sicure. Per altre informazioni, vedere riepilogo di funzioni integer sicure Kernel-Mode.
Altri problemi di sicurezza
Usare un blocco o una sequenza interbloccata per evitare condizioni di concorrenza. Per altre informazioni, vedere Errori in un ambiente multiprocessore.
Assicurarsi che non siano installati filtri di network Transport Driver Interface (TDI) o provider di servizi a più livelli (LSP) dal driver o dai pacchetti software associati durante l'installazione o l'utilizzo. Usare invece API moderne, ad esempio Windows Filtering Platform (WFP) .
Vulnerabilità del codice aggiuntive
Oltre alle possibili vulnerabilità descritte in questo articolo, vengono fornite informazioni aggiuntive sul miglioramento della sicurezza del codice driver della modalità kernel: Creazione di driver affidabili Kernel-Mode.
Per altre informazioni sulla codifica sicura C e C++, vedere Proteggere le risorse di codifica alla fine di questo articolo.
Implementare codice compatibile con HVCI
elemento elenco di controllo per la sicurezza n. 6:Verificare che il driver usi memoria in modo che sia compatibile con HVCI.
Integrità della memoria e compatibilità HVCI
L'integrità della memoria, nota anche come Integrità del codice protetta da Hypervisor (HVCI) usa la tecnologia hardware e la virtualizzazione per isolare la funzione decisionale di integrità del codice (CI) dal resto del sistema operativo. Quando si utilizza la sicurezza basata sulla virtualizzazione per isolare l'Integrità del Codice, l'unico modo in cui la memoria del kernel può diventare eseguibile è tramite una verifica di Integrità del Codice. Ciò significa che le pagine di memoria kernel non possono mai essere scrivibili e eseguibili (W+X) e il codice eseguibile non può essere modificato direttamente.
Per implementare il codice compatibile con HVCI, assicura che il codice del driver esso segua:
- Scegli di aderire a NX per impostazione predefinita
- Usa le API/flag NX per l'allocazione della memoria (NonPagedPoolNx)
- Non usa sezioni sia scrivibili che eseguibili
- Non tenta di modificare direttamente la memoria di sistema eseguibile
- Non usa codice dinamico nel kernel
- Non carica i file di dati come eseguibili
- L'allineamento delle sezioni è un multiplo di 0x1000 (PAGE_SIZE). Ad esempio, DRIVER_ALIGNMENT=0x1000
Per altre informazioni sull'uso dello strumento e un elenco di chiamate di memoria incompatibili, vedere Implementare codice compatibile con HVCI.
Per ulteriori informazioni sul test di sicurezza relativo ai fondamenti del sistema, vedere il test di preparazione per l'integrità del codice HyperVisor e l'integrità del codice (HVCI) Hypervisor-Protected.
Migliorare la sicurezza dell'installazione dei dispositivi
elemento della lista di controllo per la sicurezza n. 7:Esaminare le linee guida per la creazione e l'installazione del driver per garantire di seguire le procedure consigliate.
Quando si crea il codice che installa il pacchetto driver, è necessario assicurarsi che l'installazione del dispositivo venga sempre eseguita in modo sicuro. Un'installazione sicura del dispositivo è una delle operazioni seguenti:
- Limita l'accesso al dispositivo e alle relative classi di interfaccia dispositivo
- Limita l'accesso ai servizi driver creati per il dispositivo
- Protegge i file driver dalla modifica o dall'eliminazione
- Limita l'accesso alle voci del Registro di sistema del dispositivo
- Limita l'accesso alle classi WMI del dispositivo
- Usa correttamente le funzioni SetupAPI
Per altre informazioni, vedere quanto segue:
Creazione di installazioni di dispositivi sicure
Linee guida per l'uso di SetupAPI
Uso delle Funzioni di Installazione dei Dispositivi
argomenti avanzati sull'installazione di dispositivi e driver
Seguire le migliori pratiche di codifica specifiche della tecnologia
elemento della checklist di sicurezza n. 8:Rivedere le seguenti indicazioni specifiche per la tecnologia del driver.
File system
Per altre informazioni sulla sicurezza dei driver del file system, vedere quanto segue:
Introduzione alla sicurezza dei file system
Problemi di sicurezza del file system
Funzionalità di sicurezza per i file system
Coesistenza con altri Driver di Filtro del File System
Iniziativa Virus Microsoft
Microsoft Virus Initiative (MVI) aiuta le organizzazioni a migliorare le soluzioni di sicurezza su cui i clienti si affidano per mantenerli al sicuro. Microsoft offre strumenti, risorse e conoscenze per supportare esperienze migliori insieme con prestazioni, affidabilità e compatibilità ottimali. Microsoft collabora con i partner MVI per definire e seguire le procedure di distribuzione sicura (SDP) per supportare la sicurezza e la resilienza dei clienti comuni.
Se si è un fornitore di software antivirus, vedere Microsoft Virus Initiative per informazioni su come partecipare a MVI per maggiori dettagli sulla distribuzione del software. Per informazioni su come i fornitori di sicurezza possono sfruttare meglio le funzionalità di sicurezza integrate di Windows per una maggiore sicurezza e affidabilità, vedere procedure consigliate per la sicurezza di Windows per l'integrazione e la gestione degli strumenti di sicurezza.
NDIS - Rete
Per informazioni sulla sicurezza dei driver NDIS, vedere Problemi di sicurezza per i driver di rete.
Stampanti
Per informazioni relative alla sicurezza dei driver della stampante, vedere Considerazioni sulla sicurezza dei driver della stampante V4.
Problemi di sicurezza per i driver windows di acquisizione di immagini (WIA)
Per informazioni sulla sicurezza WIA, vedere Problemi di sicurezza per i driver Windows di acquisizione di immagini (WIA).
Aggiungere annotazioni SAL al codice driver
elemento della lista di controllo di sicurezza n. 9:Aggiungere annotazioni SAL al codice del driver.
Il linguaggio di annotazione del codice sorgente (SAL) fornisce un set di annotazioni che è possibile usare per descrivere come una funzione usa i relativi parametri, i presupposti su di essi e le garanzie che rende al termine. Le annotazioni sono definite nel file di intestazione sal.h
. L'analisi del codice di Visual Studio per C++ usa annotazioni SAL per modificarne l'analisi delle funzioni. Per altre informazioni sullo sviluppo di driver SAL 2.0 per Windows, vedere annotazioni SAL 2.0 per i driver di Windows e Uso di annotazioni SAL per ridurre i difetti del codice C/C++.
Per informazioni generali su SAL, vedere questo articolo disponibile in OSR. Annotazioni SAL: Non odiarmi perché sono bella
Eseguire la revisione del codice tra pari
voce elenco di controllo per la sicurezza n. 10:Eseguire la revisione del codice peer per cercare i problemi non rilevati dagli altri strumenti e processi
Cercare revisori esperti del codice per cercare problemi che potrebbero non essere stati rilevati. Un secondo set di occhi spesso vedrà problemi che potresti aver trascurato.
Se non si dispone di personale adatto per esaminare il codice internamente, considerare di coinvolgere aiuti esterni per questo scopo.
Eseguire l'analisi delle minacce
elemento elenco di controllo della sicurezza n. 11:modificare un modello di minaccia del driver esistente o creare un modello di minaccia personalizzato per il driver.
Nel considerare la sicurezza, una metodologia comune consiste nel creare modelli di minaccia specifici che tentano di descrivere i tipi di attacchi possibili. Questa tecnica è utile quando si progetta un driver perché impone allo sviluppatore di considerare in anticipo i potenziali vettori di attacco contro un driver. Dopo aver identificato potenziali minacce, uno sviluppatore di driver può quindi prendere in considerazione mezzi per difendersi da queste minacce per rafforzare la sicurezza complessiva del componente driver.
Questo articolo fornisce indicazioni specifiche per i driver per la creazione di un modello di minaccia leggero: modellazione delle minacce per driver. L'articolo fornisce un diagramma del modello di minaccia del driver di esempio che può servire come punto di partenza per il vostro driver.
Le procedure consigliate per il ciclo di vita di sviluppo della sicurezza (SDL) e gli strumenti associati possono essere usati da IHV e OEM per migliorare la sicurezza dei propri prodotti. Per altre informazioni, vedere raccomandazioni SDL per gli OEM.
Usare CodeQL per controllare il codice del driver
elemento elenco di controllo per la sicurezza n. 12:Usare CodeQL per verificare la presenza di vulnerabilità nel codice del driver.
CodeQL, di GitHub, è un motore di analisi del codice semantico e la combinazione di una vasta gamma di query di sicurezza insieme a una solida piattaforma lo rende uno strumento utile per proteggere il codice driver. Per ulteriori informazioni, vedere CodeQL e il Test del logo degli Static Tools.
Usare Driver Verifier per verificare la presenza di vulnerabilità
voce elenco di controllo sicurezza n. 13:Usare Driver Verifier per verificare la presenza di vulnerabilità nel codice del driver.
Driver Verifier usa un set di regole di interfaccia e un modello del sistema operativo per determinare se il driver interagisce correttamente con il sistema operativo Windows. Driver Verifier rileva i difetti nel codice del driver che potrebbero indicare bug potenziali nei driver.
Driver Verifier consente il test in tempo reale del driver. Driver Verifier monitora i driver in modalità kernel di Windows e i driver grafici per rilevare chiamate di funzione o azioni non valide che potrebbero danneggiare il sistema. Un debugger collegato consente la visualizzazione dell'esecuzione del codice del sistema operativo e del driver in tempo reale. Driver Verifier può sottoporre i driver di Windows a un'ampia gamma di stress e test per individuare comportamenti non corretti. Per altre informazioni, vedere Driver Verifier.
Il driver Verifer funziona con i driver WDM e KMDF. Per informazioni specifiche su ciò che può verificare, vedere gli argomenti seguenti.
- Regole per i driver WDM
- regole di per i driver kmdf
Per ulteriori informazioni sui driver con cui Driver Verifier può lavorare, vedere Regole di conformità DDI e Driver supportati. Per le regole di verifica aggiuntive per tipi specifici di driver, vedere:
- Regole per i driver NDIS
- Regole per i driver Storport
- Regole per i driver audio
- Regole per i driver AVStream
Per acquisire familiarità con DV, è possibile usare uno dei driver di esempio (ad esempio, l'esempio di tostapane in primo piano: https://github.com/Microsoft/Windows-driver-samples/tree/main/general/toaster/toastDrv/kmdf/func/featured).
Controllare il codice con i test del programma di compatibilità hardware
elemento elenco di controllo per la sicurezza n. 14:Usare i test del programma di compatibilità hardware correlati alla sicurezza per verificare la presenza di problemi di sicurezza.
Il programma di compatibilità hardware include test correlati alla sicurezza che possono essere usati per cercare vulnerabilità del codice. Il programma di compatibilità hardware di Windows sfrutta i test nel Windows Hardware Lab Kit (HLK). I test HLK Device Fundamentals possono essere usati dalla riga di comando per mettere alla prova il codice del driver e individuare eventuali punti deboli. Per informazioni generali sui test fondamentali del dispositivo e sul programma di compatibilità hardware, vedere Windows Hardware Lab Kit.
I test seguenti sono esempi di test che possono essere utili per controllare il codice driver per alcuni comportamenti associati alle vulnerabilità del codice:
DF - Test di fuzzing casuale IOCTL (Affidabilità)
DF - Test con apertura secondaria fuzz (affidabilità)
DF - Test buffer di lunghezza zero fuzz (Affidabilità)
DF - Test casuale FUZZ FSCTL (Affidabilità)
DF - Test dell'API Mizz Misc (Reliability)
È anche possibile utilizzare il fuzz testing del ritardo di sincronizzazione del kernel incluso in Driver Verifier,.
I test chaos (simultanei hardware e sistema operativo) eseguono diversi test del driver PnP, test fuzz del driver di dispositivo e test del sistema di alimentazione simultaneamente. Per altre informazioni, vedere CHAOS Tests (Device Fundamentals).
I test di penetrazione sui principi fondamentali del dispositivo eseguono varie forme di attacchi di input, che costituiscono un elemento fondamentale dei test di sicurezza. I test di attacco e penetrazione possono aiutare a identificare le vulnerabilità nelle interfacce software. Per altre informazioni, vedere Test di penetrazione (Nozioni fondamentali sui dispositivi).
Usare il Device Guard - Test di conformità, insieme agli altri strumenti descritti in questo articolo, per verificare che il driver sia compatibile con HVCI.
Strumenti di test personalizzati e specifici del dominio
Prendere in considerazione lo sviluppo di test di sicurezza personalizzati specifici del dominio. Per sviluppare test aggiuntivi, raccogliere input dai progettisti originali del software, nonché risorse di sviluppo non correlate familiari con il tipo specifico di driver in fase di sviluppo e una o più persone che hanno familiarità con l'analisi e la prevenzione delle intrusioni di sicurezza.
Controllare i driver pronti per la spedizione con strumenti come BinSkim e SignTool
elemento elenco di controllo per la sicurezza n. 15:Controllare il codice compilato con gli strumenti come BinSkim e SignTool prima del caricamento nel Centro per i partner.
Usare strumenti come BinSkim e SignTool per esaminare i file binari per controllare il codice compilato prima del caricamento nel Centro per i partner da distribuire tramite Windows Update. La presenza di strumenti per controllare i file binari compilati, prima che vengano inviati per la distribuzione, aggiunge un altro livello di protezione.
BinSkim
BinSkim può identificare procedure di codifica e compilazione che possono potenzialmente rendere vulnerabile il file binario. BinSkim verifica la presenza di:
- Uso di set di strumenti del compilatore obsoleti: i file binari devono essere compilati con i set di strumenti del compilatore più recenti, laddove possibile, per ottimizzare l'uso delle mitigazioni di sicurezza correnti a livello di compilatore e del sistema operativo.
- Impostazioni di compilazione non sicure: i file binari devono essere compilati con le impostazioni più sicure possibili per abilitare le mitigazioni della sicurezza fornite dal sistema operativo, ottimizzare gli errori del compilatore e segnalare avvisi interattivi, tra le altre cose.
- Problemi di firma: i file binari firmati devono essere firmati con algoritmi con crittografia avanzata.
BinSkim è uno strumento open source e genera file di output che usano il formato di interscambio dei risultati dell'analisi statica (SARIF). BinSkim sostituisce il precedente strumento BinScope .
Per altre informazioni su BinSkim, vedere Usare BinSkim per controllare i file binari e la guida utente BinSkim.
SignTool
Usare SignTool per controllare i file del driver con firma di rilascio. Per altre informazioni, vedere Verifica della firma di un Release-Signed file del driver e Verifica della firma di un file di catalogo firmato da un certificato di versione commerciale.
Non firmare il codice di test di produzione
elemento elenco di controllo per la sicurezza n. 16:Firma del codice di produzione, sviluppo, test e codice del driver del kernel di produzione.
Il codice del driver kernel usato per lo sviluppo, il test o la produzione può includere funzionalità pericolose che rappresentano un rischio per la sicurezza. Questo codice pericoloso non deve mai essere firmato con un certificato considerato attendibile da Windows. Il meccanismo corretto per l'esecuzione di codice driver pericoloso consiste nel disabilitare l'avvio protetto UEFI, abilitare il BCD "TESTSIGNING" e firmare il codice di sviluppo, test e produzione usando un certificato non attendibile (ad esempio, uno generato da makecert.exe).
Il codice firmato da un certificato SPC (Software Publishers Certificate) attendibile o da una firma WHQL (Hardware Quality Labs) windows non deve facilitare il bypass delle tecnologie di sicurezza e integrità del codice Windows. Prima che il codice venga firmato con una firma SPC o WHQL attendibile, verificare che sia conforme alle linee guida fornite da Creazione di driver affidabili Kernel-Mode. Inoltre, il codice non deve contenere comportamenti pericolosi, descritti di seguito.
Di seguito sono riportati alcuni esempi di comportamento pericoloso:
- Fornire la possibilità di mappare la memoria del kernel, fisica o del dispositivo in modalità utente.
- Fornire la possibilità di leggere o scrivere nella memoria del kernel, fisica o del dispositivo, inclusa la porta di input/output (I/O).
- Fornire l'accesso all'archiviazione che ignora il controllo di accesso di Windows.
- Possibilità di modificare hardware o firmware che il driver non è stato progettato per gestire.
Eseguire la firma corretta del driver di versione e distribuire il pacchetto driver con Windows Update
voce elenco di controllo per la sicurezza n. 17:Usare il portale per i partner windows per inviare il pacchetto driver da firmare e distribuire tramite Windows Update.
Prima di rilasciare un pacchetto driver al pubblico, inviare il pacchetto per la certificazione. Per altre informazioni, vedere Test per le prestazioni e la compatibilità e Introduzione al programma hardware.
L'uso di Windows Update è fortemente consigliato per la distribuzione dei pacchetti driver. Windows Update offre un sistema di distribuzione affidabile, sicuro, scalabile a livello globale e conforme alle normative che deve essere usato per distribuire gli aggiornamenti dei driver. Per altre informazioni, vedere Distribuzione di un pacchetto driver.
Usa implementazione graduale e driver in anteprima nel Centro per i partner per Windows Hardware per distribuire il pacchetto driver all'interno di anelli Windows Insider definiti, fornendo al tempo stesso il monitoraggio e la valutazione automatici. Monitorare l'implementazione del driver usando le misure del driver Microsoft , ad esempio percentuale di computer senza un arresto anomalo della modalità kernel per mantenere la qualità.
Per una descrizione delle procedure di distribuzione sicura del software, fare riferimento a CISA Distribuzione Sicura del Software: Come i Produttori di Software Possono Garantire Affidabilità per i Clienti.
Informazioni sul modo in cui i driver vengono segnalati usando il Microsoft Vulnerable and Malicious Driver Reporting Center
voce elenco di controllo per la sicurezza n. 18: Informazioni sul modo in cui i driver vengono segnalati usando il Microsoft Vulnerabile e Dannoso Driver Reporting Center
Chiunque può inviare un driver discutibile usando Microsoft Vulnerabile e Dannoso Driver Reporting Center. Fare riferimento a questo post del blog per informazioni su come inviare i driver per l'analisi - Migliorare la sicurezza del kernel con il nuovo Microsoft Vulnerable and Malicious Driver Reporting Center
Il Reporting Center può scansionare e analizzare i driver Windows creati per architetture x86 e x64. I driver vulnerabili e dannosi scansionati vengono contrassegnati per l'analisi e l'indagine da parte del team dei Driver Vulnerabili di Microsoft. Dopo aver confermato i driver vulnerabili, viene visualizzata una notifica appropriata e vengono aggiunti all'elenco di blocco dei driver vulnerabili. Per altre informazioni, vedere regole di blocco dei driver consigliate da Microsoft. Queste regole vengono applicate per impostazione predefinita ai dispositivi abilitati per l'integrità del codice protetto da Hypervisor (HVCI) e Windows 10 in modalità S.
Esaminare le risorse di codifica sicura
elemento elenco di controllo per la sicurezza n. 19:Esaminare queste risorse per approfondire la comprensione delle procedure consigliate per la codifica sicura applicabili agli sviluppatori di driver.
Linee guida per Microsoft NISTIR 8397
La pubblicazione del governo degli Stati Uniti NISTIR 8397: Guidelines on Minimum Standards for Developer Verification of Software by the National Institute of Standards and Technology (NIST) contiene indicazioni su come creare software affidabile e sicuro in qualsiasi linguaggio di programmazione.
Creare programmi C++ affidabili e sicuri riepiloga come usare i prodotti per sviluppatori Microsoft per C++ e altri linguaggi per seguire le linee guida NISTIR 8397.
Database di vulnerabilità del software noto NIST
National Vulnerability Database (NVD) è un repository ricercabile di difetti software correlati alla sicurezza, inclusi i driver di Windows.
Ricerca nel database delle vulnerabilità NIST
panoramica del database di vulnerabilità nazionale
Proteggere gli standard di codifica
Carnegie Mellon University SEI CERT - C Coding Standard: regole per lo sviluppo di sistemi sicuri, affidabili e sicuri (PDF).
MITRE - Debolezze risolte dal CERT C Secure Coding Standard
Microsoft Visual Studio: Usare i verificatori delle Linee Guida principali di C++
Proteggere le organizzazioni di codifica
Cybersecurity and Infrastructure Security Agency (CISA)
Carnegie Mellon University SEI CERT
OSR
OSR fornisce servizi di formazione e consulenza per lo sviluppo di driver. Questi articoli della newsletter osr evidenziano i problemi di sicurezza dei driver.
è necessario usare la protezione: all'interno del driver & di sicurezza dei dispositivi
Mettere in sicurezza i Driver - Un sondaggio sulle Tecniche
Meltdown e Spectre: Che ne dici dei driver?
Case study sulla vulnerabilità del driver
Sicurezza della catena di approvvigionamento software e fatturazione del software (SBOMs)
SBOMs fornisce un elenco di ingredienti usati nella creazione di un componente software, ad esempio software open source, componenti e potenzialmente anche strumenti di compilazione. Ciò consente ai produttori e ai consumatori di migliorare l'inventario e valutare il rischio di licenze e vulnerabilità. Microsoft utilizza lo SPDX (Software Package Data Exchange) come formato del documento SBOM. Per ulteriori informazioni, vedere Generazione di distinte base software (SBOM) con SPDX presso Microsoft e Microsoft rende open source il suo strumento di generazione di distinte base software (SBOM).
L'iniziativa SCITT (Supply Chain Integrity, Transparency and Trust) è un set di standard Internet IETF per la gestione della conformità dei beni e dei servizi nelle catene di fornitura end-to-end. SCITT supporta la verifica continuativa di beni e servizi in cui l'autenticità di entità, prove, criteri e artefatti può essere garantita e le azioni delle entità possono essere autorizzate, non ripudiabili, non modificabili e controllabili.
Libri
24 peccati mortali della sicurezza software: errori di programmazione e come risolverli di Michael Howard, David LeBlanc e John Viega
scritturaSecure Software Second Edition, Michael Howard e David LeBlanc
L'arte della valutazione della sicurezza del software: identificazione e prevenzione delle vulnerabilità software, Mark Dowd, John McDonald e Justin Schuh
Secure Coding in C e C++ (SEI Series in Software Engineering) 2ª Edizione, Robert C. Seacord
programmazione del modello di driver di Microsoft Windows (seconda edizione), Walter Oney
Sviluppo di driver con Windows Driver Foundation (Guida di riferimento per sviluppatori), Penny Orwick e Guy Smith
Formazione
La formazione sui driver Windows è disponibile da fornitori come i seguenti:
Il training online per la codifica sicura è disponibile da un'ampia gamma di origini. Ad esempio, questo corso è disponibile da coursera on:
Identificare le vulnerabilità di sicurezza nella programmazione C/C++.
SAFECode offre anche formazione gratuita:
Certificazione professionale
CERT offre una certificazione Secure Coding Professional.
Riepilogo delle considerazioni chiave
La sicurezza dei driver è un'impresa complessa contenente molti elementi, ma ecco alcuni punti chiave da considerare:
I driver risiedono nel kernel di Windows, e avere un problema durante l'esecuzione nel kernel espone l'intero sistema operativo. Per questo motivo, prestare particolare attenzione alla sicurezza dei driver e alla progettazione tenendo conto della sicurezza.
Applicare il principio dei privilegi minimi:
un. Usare una stringa SDDL stringente per limitare l'accesso al driver
b. Limitare ulteriormente i singoli IOCTL
Creare un modello di minaccia per identificare i vettori di attacco e valutare se è possibile limitare ulteriormente qualsiasi elemento.
Prestare attenzione ai puntatori incorporati che vengono passati dalla modalità utente. È necessario sondarli, accedervi all'interno di un blocco try except, e sono soggetti a problemi di tempo di controllo-utilizzo (ToCToU) a meno che il valore del buffer non sia catturato e confrontato.
Se non si è certi, usare METHOD_BUFFERED come metodo di buffering IOCTL.
Usare utilità di analisi del codice, ad esempio CodeQL, per cercare vulnerabilità del codice note e correggere eventuali problemi identificati.
Cercare revisori esperti del codice per cercare problemi che potrebbero non essere stati rilevati.
Usare i verificatori del driver e testare il driver con più input, inclusi i case degli angoli.