Programmazione Sicura A cura di Orlando Bassotto
Roadmap L'importanza della protezione del codice Panoramica generale sui rischi Validazione dell'input Azioni di prevenzione Conclusione Risorse
L'importante e' proteggersi
Cosa proteggere? Applicazioni per il trattamento di dati sensibili Applicazioni amministrative (Utilizzate da root o Administrator) Servizi di rete (Daemons, servizi, non escludendo CGI) Applicazioni con elevazione di privilegi (SUID)
Pitfall comuni Incuria nell'analisi del codice da parte dello sviluppatore stesso Mancanza di auditing del codice (dovuti a costi e tempi di sviluppo) Trasporto dei dati insicuro Fattori esterni Noncuranza da parte dell'amministratore di sistema Noncuranza da parte degli utenti
L'ambiente UNIX
L'ambiente UNIX Presenta una forma di autenticazione basata su login e password. Utilizza una tipologia di controllo DAC, basata su permessi di lettura, scrittura, esecuzione distinti tra utente, gruppo e altro. Ogni utente ha un user id ed un group id numerico, puo' appartenere a piu' gruppi. Permette l'elevazione dei privilegi utilizzando lo SUID bit sull'eseguibile.
L'ambiente UNIX Caratteristiche dei processi UNIX Identificati mediante un PID (Process Identifier) Privilegi di esecuzione mediante UID e GID. Limitazione nell'uso delle risorse Parametri di scheduling (priorita', policy di scheduling, etc) Root del filesystem (ambiente chrooted) Permessi creazione file mediante umask Variabili d'ambiente
L'ambiente UNIX Ogni processo ha una set di credenziali che descrivono i suoi privilegi RUID, RGID: UID e GID dell'utente che esegue il processo EUID, EGID: UID e GID effettivi per ogni controllo di privilegio SUID, SGID: UID e GID salvati, utilizzati per effettuare l'elevazione di privilegi. FSUID, FSGID: UID e GID utilizzati per i controlli su filesystem. (Solo Linux)
SUID: Perche'? Alcune applicazioni necessitano di particolari privilegi per poter compiere azioni che come utenti 'regolari' non possono eseguire. L'applicazione dovrebbe switchare dal suo RUID al SUID impostato solo per il tempo strettamente necessario per poi perdere definitivamente i privilegi. L'acquisizione e la perdita di privilegi e' un fattore fondamentale dal punto della sicurezza.
Rischi Penetrazione nel sistema Sottrazione, modifica o distruzione di informazioni riservate Utilizzo illecito del sistema Distributed Denial of Service Infezione da parte di virus
Validazione dell'input
Cosa validare? Parametri da linea di comando Variabili d'ambiente File descriptors Contenuto dei file Input da applicazioni WEB (specialmente CGI) Encoding dei caratteri (UTF-8, etc)
Parametri da linea di comando Vettore degli argomenti non totalmente trustable Buffer overflow Format string o bad parsing Boundary check
Variabili d'ambiente Variabili di inizializzazione (es. LD_PRELOAD) Variabili global-scope (es. IFS, PATH)
File descriptors Controllo dei file descriptors ereditati dai processi figli. Dirottamento dell'output di un programma (es. stdout dirottato su /etc/passwd)
Contenuto dei file Ulteriore minaccia della corretta interpretazione dell'input Stessi problemi inerenti alla validazione dei parametri da riga di comando
Input da applicazioni WEB Decoding dell'URI Corretta interpretazione degli headers Corretta interpretazione logica degli argomenti Encoding dei caratteri
Encoding dei caratteri Sequenze non valide Codifica Unicode/ISO10646 Multibyte strings Piu' codifiche possibili per la stessa sequenza di caratteri
Azioni di prevenzione
Azioni di prevenzione Corretta gestione dei dati sensibili Ordine e tipo delle variabili locali (es. array nello stack) Variabili signed ed unsigned Funzioni di copia boundary checked (es. snprintf al posto di sprintf, strncpy al posto di strcpy, etc)
Azioni di prevenzione Mantenimento dei privilegi fino a che strettamente necessari Utilizzo di funzioni o librerie error-proof Sistemi di protezione compile-time StackGuard come patch di gcc Propolice come preparser dei sorgenti Lint come sistema di prevenzione da errori generici
Auditing del codice Errori concettuali Errori di implementazione Errori 'umani' Ricerca di vulnerabilita' successive alla stesura del codice
Conclusioni
Conclusioni Non dare niente per scontato, entrare in un'ottica paranoica. Analizzare come vulnerabilita' note siano state exploitate. Pensare ai possibili contesti di utilizzo del programma. Limitare l'uso di risorse il piu' possibile. Negare per default e concedere solo cio' che e' ammesso. Fare attenzioni alle possibili race-conditions. Meglio un controllo in piu' che uno in meno.
Risorse Sikurezza - http://sikurezza.org Mailing List - devel@sikurezza.org Security Focus - http://www.securityfocus.com Open Web Application Security Project - http://www.owasp.org Secure Programming for Linux and Unix HOWTO di David A. Wheeler
Ringraziamenti Yvette Agostini (vodka@s0ftpj.org) Marco Valleri (naga@blackhats.it) Fabio Pietrosanti (naif@blackhats.it) Stefano Zanero (stefano.zanero@s0ftpj.org) Fabio Busatto (fabio.busatto@sikurezza.org) Andrea Cocito (blackye@break.net)
Riferimenti Orlando Bassotto nextie@s0ftpj.org