La verifica formale non garantisce un sistema sicuro. Niente garantisce un sistema sicuro. Ciò che la verifica formale può fare è fornire una garanzia molto elevata che alcune parti del sistema sono sicure.
La verifica formale fornisce una prova matematica che, in base a determinati presupposti, un modello del sistema ha determinate proprietà. Pertanto, se una parte del sistema è stata verificata formalmente, rimangono ancora diverse condizioni per la sicurezza del sistema:
- Le ipotesi sottostanti alla verifica sono soddisfatte?
- Il sistema corrisponde al modello che è stato verificato?
- La prova fornita dal sistema di verifica è corretta?
- Le proprietà comprovate sono sufficienti per garantire la sicurezza del sistema?
L'entità della verifica formale può variare molto. Ad esempio, buffer overflow - un tipo comune di vulnerabilità - può essere individuato abbastanza facilmente: la maggior parte delle lingue che sono di livello superiore a C o C ++ garantiscono l'assenza di buffer overflow nel programma compilato. Può comunque accadere che il compilatore permetta il passaggio del codice - mentre i bug del compilatore sono molto più rari dei bug del programma, non sono impossibili. Gli overflow del buffer sono solo un tipo, tuttavia; la maggior parte della sicurezza dei sistemi dipende molto più dal sapere che non ci sono buffer overflow. (Lettura correlata: Perché i computer non controllano se ci sono contenuti di memoria in qualche spazio di memoria? )
Per illustrare le limitazioni di cui sopra, vorrei fare un esempio concreto. Alcune smart card eseguono una Java Card macchina virtuale ed esegui solo bytecode che è stato verificato . Il verificatore bytecode, in linea di principio, garantisce che il codice non possa sbirciare o colpire al di fuori dello spazio di memoria assegnato. Questo evita alcune vulnerabilità ma non tutte:
- La verifica garantisce le sue proprietà solo se l'interprete bytecode si comporta secondo le sue specifiche. Inoltre, se l'hardware non esegue correttamente l'interprete, tutte le puntate sono disattivate (ad esempio, un modo per attaccare una smartcard è provocare un power glitch che comporta l'ignoranza di alcune istruzioni).
- Se è presente un bug che consente di caricare il codice senza passare attraverso il verificatore, è possibile che il codice sulla scheda non abbia le proprietà garantite dalla verifica.
- Il verificatore stesso potrebbe essere bacato e consentire il caricamento di codice errato.
- Anche se il codice delle applicazioni sulla scheda non accede direttamente alla memoria di altre applicazioni, potrebbe comunque spiarle o perturbarle in altri modi. Ad esempio, può sfruttare un canale laterale come il tempismo per dedurre le proprietà di altro codice in esecuzione sullo stesso dispositivo.
Inoltre, la sicurezza del sistema può dipendere da cose diverse dall'isolamento tra le applicazioni sulla scheda. Ad esempio, il sistema di autenticazione può consentire a un utente malintenzionato di assumere il controllo della carta, potrebbe esserci una vulnerabilità a livello di protocollo che consente all'autore dell'attacco di interrompere le comunicazioni, ecc.
In un sistema ad alta sicurezza, la verifica formale può aiutare in due modi:
- Dimostrando che il codice corrisponde alle sue specifiche. Ciò richiede un modello formale dell'ambiente di esecuzione (hardware, compilatore o interprete, libreria standard, ...) e molto lavoro.
- Dimostrando che le specifiche hanno alcune proprietà desiderabili. Ciò richiede una formalizzazione delle specifiche, una scelta giudiziosa delle proprietà e molto lavoro.
I Common Criteria per le valutazioni di sicurezza definiscono diversi livelli di garanzia . Solo il livello di garanzia più elevato (EAL7) richiede una verifica formale. Questo non è l'unico requisito: la verifica formale non preclude la valutazione di altri aspetti del sistema, tra cui documentazione, test di penetrazione, ecc.