Condividi tramite


Gestire la gestione

Una fonte significativa di problemi di sicurezza all'interno dei driver è l'uso di handle passati tra componenti in modalità utente e in modalità kernel. Esistono diversi problemi noti relativi all'utilizzo dell'handle all'interno dell'ambiente kernel, tra cui i seguenti:

  • Applicazione che passa il tipo di handle errato a un driver del kernel. Il driver del kernel potrebbe arrestarsi in modo anomalo cercando di usare un oggetto evento in cui è necessario un oggetto file.

  • Applicazione che passa un handle a un oggetto per il quale non ha l'accesso necessario. Il driver del kernel potrebbe eseguire un'operazione che funziona perché la chiamata proviene dalla modalità kernel, anche se l'utente non dispone di autorizzazioni adeguate per farlo.

  • Un'applicazione che passa un valore che non è un handle valido nello spazio indirizzi, ma è contrassegnato come handle di sistema per eseguire un'operazione dannosa sul sistema.

  • Applicazione che passa un valore che non è un handle appropriato per l'oggetto dispositivo (handle che questo driver non ha creato).

Per proteggersi da questi problemi, un driver del kernel deve prestare particolare attenzione per assicurarsi che gli handle passati siano validi. Il criterio più sicuro consiste nel creare eventuali handle necessari all'interno del contesto del driver. Questi handle, creati dai driver del kernel, devono specificare l'opzione OBJ_KERNEL_HANDLE, che creerà un handle valido nel contesto di processo arbitrario e uno accessibile solo da un chiamante in modalità kernel.

Per i driver che usano handle creati da un programma dell'applicazione, l'uso di questi handle deve essere eseguito con estrema attenzione:

  • La procedura consigliata consiste nel convertire l'handle in un puntatore a oggetti chiamando ObReferenceObjectByHandle, specificando i parametri AccessMode corretti (in genere da Irp-RequestorMode>), DesiredAccess e ObjectType, ad esempio IoFileObjectType o ExEventObjectType.

  • Se un handle deve essere usato direttamente all'interno di una chiamata, è preferibile usare le varianti Nt delle funzioni anziché le varianti Zw delle funzioni. In questo modo verrà applicato il controllo dei parametri e gestirà la convalida dal sistema operativo perché la modalità precedente sarà UserMode e quindi non attendibile . Si noti che i parametri passati alle funzioni Nt che sono puntatori potrebbero non riuscire a convalidare se la modalità precedente è UserMode. Le routine Nt e Zw restituiscono un parametro IoStatusBlock con informazioni sugli errori da controllare.

  • Gli errori devono essere intrappolati in modo appropriato e usare __try e __except in base alle esigenze. Molte delle routine di Gestione cache (Cc), Gestione memoria (Mm) e librerie di runtime del file system (FsRtl) generano un'eccezione quando si verifica un errore.

Nessun driver deve mai basarsi su handle o parametri passati da un'applicazione in modalità utente senza adottare precauzioni appropriate.

Si noti che se la variante Nt viene utilizzata per aprire un file, è necessario utilizzare anche la variante Nt per chiudere il file.