[ Home | Liste | F.A.Q. | Risorse | Cerca... ]


[ Data: precedente | successivo | indice ] [ Argomento: precedente | successivo | indice ]


Archivio: Aprile 2002 ml@sikurezza.org
Soggetto: Re: codice corretto, codice robusto, codice sicuro (ver. 3)
Mittente: Orlando Onorato
Data: 23 Apr 2002 11:52:52 -0000
Rispondo alle tue contestazioni:
1) Un input è valido se è previsto in fase di specifica! Non c'è bisogno di
garantirne la sua
validità... lo è! Non c'è poi nessun problema di validazione... io definisco
valido sono l'input
che il committente l'applicazione ha PREVISTO. In altre parole un Input è
valido quando è
PREVISTO! (Attenzione non si è parlato di Input SICURO!)

2) Un Input non valido è quello non previsto in fase di specifica (capito
molto spesso nella
pratica). E' vero si potrebbe pensare ad una funzione di validazione che
limiti gli input... ma questo verrà dopo, per adesso stiamo dando solo delle
definizioni, le soluzioni al problema
sarranno affrontate successivamente.

3) Il problema della dimensione dello stato sarà risolto successivamente...
ripeto che adesso stiamo dando delle definizioni.

Ho accolto con molto piacere le tue obiezioni e spero di poter continuare
questa discussione,
viste le mie risposte.
Tuttavia le cose che ho scritto le ho riviste...
ti invio quanto fatto.

________________________________________
1. Introduzione
Il problema della sicurezza è cruciale nel panorama informatico del giorno d
'oggi e vede nella programmazione non sicura le proprie basi. Molti problemi
di sicurezza nascono dal fatto che la quasi totalità di sviluppatori di
applicazioni software ha sempre scritto e continua a scrivere codice non
avendo la "sicurezza in mente".  Gli stessi linguaggi di programmazione, il
più famoso C, ad esempio, sono stati scritti per rispondere a
caratteristiche quali la efficienza, la semplicità, l'usabilità ma non
tenendo in considerazione aspetti di sicurezza.
Per anni ricercatori ed software house hanno puntato la loro attenzione più
nel risolvere i problemi di sicurezza con meccanismi che tentavano di
ridurre gli effetti della programmazione non sicura che nel risolvere il
problema alla radice.
Fortunatamente negli ultimi anni si avuto un cambio di tendenza e sempre più
importanza nell'ambito della ricerca sta assumendo il problema della
programmazione non sicura. Molti sono i casi di articoli scientifici in cui
vengono dettate regole da rispettare per evitare che il software scritto sia
soggetto a vulnerabilità conosciute. Tuttavia ancora oggi mancano articoli
che trattino la programmazione non sicura in modo sistematico. Le stesse
definizioni date di programmazione non sicura appaiono quanto mai ambigue se
non, in alcuni casi, contraddittorie.
Prima di passare oltre è opportuno riflettere sul fatto che non a caso
finora abbiamo sempre parlato di programmazione non sicura e non di
programmazione sicura. Questo è dovuto al fatto che la sicurezza è una
espressione relativa che non gode di proprietà assolute; in altri termini
non è mai possibile dimostrare che una applicazione è in assoluto sicura. E'
possibile, tuttavia, dimostrare che essa goda di proprietà che non la
rendono soggetta a relative vulnerabilità conosciute. Fatta questa doverosa
precisazione, la cui mancanza avrebbe inficiato il rigore del lavoro svolto,
con una sorte di abuso di linguaggio parleremo di programmazione sicura, ben
avendo in mente la relatività che essa nasconde.


2. Programmazione sicura
2.1 Environment-Application Interaction (EAI)
Osservando che molti problemi di sicurezza nascono da una inappropriata
interazione tra l'applicazione e l'ambiente in cui essa è eseguita, e che
comunque non è possibile definire criteri di sicurezza delle applicazioni
prescindendo dall'ambiente in cui esso opera, si è proceduti a distinguere i
sistemi in "application" (applicazione) ad "enviroment" (ambiente). I questo
modo ogni applicazione sarà vista come una entità che interagisce con un
ambiente, di cui fanno parte il software di sistema e le altre applicazioni
(Environment-Application Interaction EAI).
In base a questa suddivisione diamo le seguenti definizioni.:
Definizione  (Internal Entity) Ogni elemento del codice di una applicazione
e dello spazio dati della stessa, rappresenta una Internal Entitity.
Definizione  (Internal State) L'insieme dei valori assunti  dalle Internal
Entity di una applicazione è detto Internal State.
Una istruzione è una Internal Entitity. La variabile var di una
applicazione, per esempio, è una Internal Entity. Il valore di var è parte
dell'Internal State. La dimensione del buffer adoperato per l'Internal
Entity var è anch'essa parte dell'Internal State.
In generale tutte le informazioni relative al codice ed ai dati di una
applicazione, ad esempio stack space, heap space, data space, sono parte
dell'Internal State. L'Internal State definisce in pratica la configurazione
corrente delle Internal Entitys. Per ogni Internal Entity possono essere
prese in considerazione diverse caratteristiche come: un id, il tipo, l'
indirizzo di memoria, il valore assunto ecc. Il numero ed il tipo di
caratteristiche prese in considerazioni dipendono dalla applicazione in
esame e dal tipo di vulnerability che si vuole analizzare.
Definizione (Environment Entity) Ogni elemento che è esterno al codice di
una applicazione ed al proprio spazio dati è detto Enviroment Entity.
Definizione (Environment State) L'insieme dei valori assunti  dalle
Enviroment Entity di una applicazione è detto Enviroment State.
Ad esempio un file è  un Evironment Entity. L'esistenza di un file, i
permessi su un file sono invece parte dell'Enviroment State. Considerazioni
analoghe all'Internal State possono essere fatto all'Environment State.
Definizione (Global State) Si definisce Global State il risultato di una
funzione che dipendente dall'Internal State, dell'Environment State e dell'
Input. Esso può assumere i valori valido ed invalido.
Global State = function ( Internal State, Environment State, Input)
Un Global State invalido è anche detto Vunerability.
Elemento chiave per la programmazione sicura sono i Global State. Si rendono
quindi necessarie alcune precisazioni per meglio comprendere il loro
significato e valore.
Incominciamo con chiarire che l'Internal State ed l'Environment State, la
cui unione da luogo al Global State, non sono incorrelati, anzi è la loro
congiunzione che rende un Global State valido o meno. Per questo motivo una
applicazione è ritenibile sicura (Global State valido) in un ambiente e non
in un'altra. Esistono inoltre più Global State validi che scaturiscono da
combinazioni diverse di Internal State ed Environment State.
2.2 Programmazione corretta, robusta e sicura
Sempre più spesso si confonde la programmazione sicura con quella robusta
creando atteggiamenti e metodologie che non consentono di affrontare il
problema della sicurezza in modo efficace.
In questo paragrafo saranno date le definizioni di programmazione corretta,
programmazione robusta e programmazione  sicura  e verranno analizzate le
relative differenze al fine di sgombrare il campo da qualsiasi ambiguità.
Suddividiamo l'Input, l'Output ed il Global State di una applicazione in
"valido" ed "invalido", dove per validità si intende la coerenza con le
specifiche date, e per Input non solo quelli forniti dall'utente ma anche
quelli ricevuti da altre applicazioni.
Definizione (Programma corretto) Un programma è corretto se si comporta come
previsto dalle proprie specifiche; in altre parole un programma è corretto
se, sottoposto ad input validi, fornisce output validi.
Definizione (Programma robusto) Un programma è robusto se, sottoposto ad
input validi e/o invalidi, comunque fornisce output validi. Questo significa
che un programma robusto dovrà fornire output coerenti con le specifiche
anche se sottoposto ad input imprevisti. La nozione di robustezza di un
programma non ha una definizione che indichi precisamente cosa si debba fare
per ottenere software robusto. Da un programma robusto ci si aspetta che sia
corretto ma che sia in grado di comportarsi correttamente anche in presenza
di situazioni non previste dalle specifiche.
Definizione (Programma sicuro) Un programma è sicuro se, sottoposto ad input
invalidi e/o validi, si porta sempre in un Global State valido. Il fatto che
il programma sia sempre in uno Global State consente di evitare
comportamenti anomali, volutamente o involontariamente prodotti, che
possono, in un modo o in un altro, consentire al programma di eseguire
operazioni non desiderate. Non viene fatto nessuna ipotesi sul rapporto
input/output e quindi sulle funzionalità dell'applicazione.


figura 1 - applicazione corretto, robusto, sicuro.

Le definizioni  date rendono chiare le seguenti implicazioni:
· una applicazione robusta è anche corretta;
· una applicazione non sicura potrebbe comportarsi in modo corretto e
robusto;
· una applicazione  sicura potrebbe essere non corretta e non robusta;
· una applicazione sicura in un ambiente potrebbe non esserlo in un'altra.
In altre parole non c'è alcun legame diretto tra la robustezza/correttezza
di una applicazione e la sua sicurezza. Tuttavia è opportuno osservare che
la definizione data di applicazione sicura presuppone che l'applicazione
stessa reagisca ad input validi o/e invalidi in modo da portarsi sempre in
uno stato valido. Quando questo è possibile contrasta con requisiti di
efficienza e complessità; quando non è possibile contrasta con i requisiti
di funzionalità in quanto alcuni input e/o output non possono essere gestiti
e quindi accettati dall'applicazione in quanto porterebbero la stessa,
inevitabilmente, in uno Global State non valido.
Meritevole di nota è poi la scelta di distinguere il Global State  di un
sistema in valido e/o invalido e non in sicuro e/o non sicuro. Siccome una
applicazione  è sicura se il suo Global State è valido potrebbe sembrare più
opportuno parlare di Global State sicuro e/o non sicuro; questa scelta
tuttavia nasconderebbe una ambiguità di fondo. Uno Global State non è mai
sicuro di per sé ma lo è in riferimento ad una specifica applicazione (vedi
paragrafo successivo). Pare quindi più corretto parlare di Global State
valido che di Global State sicuro.
Nei capitolo successivi saranno analizzate le vulnerabilità più comuni e
definite per ognuna di esse uno Global State valido.
.questo mi consentirà di procedere in modo schematico definendo per ogni
vulnerabilità (security risk) un proprio stato valido!

2.3 Programmazione corretta e/o robusta vs. Programmazione sicura
Analizziamo in questo paragrafo quali siano le conseguenze, in termini di
approccio metodologico, tra la programmazione sicura e quella corretta e/o
robusta.
Appare chiaro che nella programmazione corretta e/o robusta il lavoro del
programmatore è tutto rivolto allo sviluppo delle funzionalità definite in
fase di specifica; in altre parole si programma tenendo in mente cosa il
programma deve fare.
Nelle programmazione sicura le cose cambiano; in fase di specifica occorre
definire gli stati validi; questi vengono individuati in modo da garantire
che il programma non esegue, in modo più o meno volontario, azioni non
desiderate. Ecco quindi che viene introdotto nella programmazione un aspetto
fin'ora mai considerato: bisogna programmare tenendo in mente non solo cosa
il programma deve fare ma anche cosa non deve fare! Questo cambiamento di
atteggiamento alla programmazione definisce quella che comunemente viene
chiamata: security risk, ossia l'analisi dei rischi alla sicurezza a cui un
programma in esecuzione è esposto, o espone il sistema su cui viene
eseguito. E' dall'analisi dei rischi che scaturiscono poi i Global State
validi di una applicazione.

2.4 Evitare Global State invalidi
Una volta definiti i Global State invalidi quali tecniche si possono
adoperare per evitare che essi vengano raggiunti da una applicazione?
Analizziamo i casi in cui l'Input fornito alla applicazione conduce la
stessa in un Global State invalido:
1) indipendentemente dall'Environment State.
2) indipendentemente dall'Internal State.
3) in funzione dell'Environment State e dell'Internal State.
4) Indipendentemente dall'Environment State e dall'Internal State.

2.4.1 Global State Invalido indipendentemente dall'Environment State
In questo caso:
Global State = function ( Internal State, Input)
Qualsiasi sia l'ambiente in cui l'applicazione è eseguita esistono Input
tali che rendono il Global State invalido, ed esso non dipende dal
Environment State. Diciamo sin dall'inizio che una situazione del genere non
solo è sperabile ma è da ricercare. Scrivere applicazioni la cui sicurezza è
indipendente dall'Environment State consente di scrivere e testare
applicazioni sicure in modo più semplice; in altre parole tutto ciò che
influisce sulla sicurezza è in nostro pieno possesso.
Analizziamo adesso tutte le possibili situazioni.
Se si verifica una situazione del genere:
per ogni Input: Global State = invalido
l'unica soluzione è quella di modificare l'applicazione; non esiste altro
rimedio.
Se invece si ha:
esistono Input: Global State = invalido
allora si possono adottare sostanzialmente due strategie:
1) Evitare che gli input che rendono il Global State invalido non vengano
forniti all'applicazione, ad esempio mediante funzioni di validazione degli
Input. Siccome questi porterebbero sicuramente l'applicazione in uno Global
State invalido potrebbe essere conveniente adoperare una politica di questo
tipo. Tuttavia è opportuno osservare che questa potrebbe influire
notevolmente sulle funzionalità della applicazione.
2) Modificare l'applicazione in modo da evitare di portarla in un Global
State invalido quando sottoposta a questi Input. E' opportuno notare che in
questo caso bisogna accertarsi di trovarsi ancora nel caso in esame
(indipendenza dell'Environment State).
Una situazione certamente desiderabile è quella in cui:
per ogni Input: Global State = valido
in questo caso potremmo dirci certi che la nostra applicazione è sicura.
Osserviamo però che una situazione del genere è quanto mai rara, non fosse
altro che per la necessità di una analisi esaustiva sugli Input possibili.

2.4.2 Global State Invalido indipendentemente dall'Internal State
In questo caso:
Global State = function ( Environment State, Input)
esistono Input tali che rendono il Global State invalido, ed esso non
dipende dall'Internal State.
Le considerazioni fatte nel paragrafo 2.4.1 possono essere estese a questa
situazione.

2.4.3 Global State Invalido in funzione dell'Internal State e dell'
Environment State
In questo caso:
Global State = function ( Internal State, Environment State, Input)
esistono Input tali che rendono il Global State invalido, ed esso dipende
sia dall'Internal State che dall'Environment State.
In questo caso le strategie che si possono adoperare sono:

1) l'inserimento dell'input non porta inevitabilmente ad un Global State
invalido; questo dipende dalla combinazione dell'Internal State e dell'
Environment State. Questo significa che la validazione dell'input potrebbe
essere un prezzo troppo caro da pagare a fronte di un evento poco frequente.
In questo caso occorrerebbe un monitor che verifichi il Global State e
quando invalido (o meglio prima che diventi invalido) esegue le dovute
azioni; tuttavia questa soluzione prevede un controllo runtime che potrebbe
inficiare la efficienza della applicazione.
2) è possibile che modificando l'applicazione stessa si determini una
condizione per cui il Global State non diventi mai invalido.

2.4.4 Global State Invalido indipendentemente dall'Internal State e dall'
Environment State
In questo caso:
Global State = function ( Input)
Le soluzioni possibili sono:
1) Evitare l'inserimento degli Input che rendono il Global State invalido
(funzione di validazione). In questo caso èssa risulta quanto mai necessaria
siccome l'inserimento di questi Input porterebbero inevitabilmente ad una
vulnerability.
2) Modificare l'applicazione cercando di portarsi in altri casi.

_________________________________________


----- Original Message -----
From: "Saverio Salatino" <ssalatino@supereva.it>
To: <ml@sikurezza.org>
Sent: Tuesday, April 23, 2002 10:30 AM
Subject: Re: codice corretto, codice robusto, codice sicuro (ver. 2)


> Orlando Onorato scrive:
> > Definizione (Programma corretto) Un programma ? corretto se si comporta
come
> > previsto dalle proprie specifiche; in altre parole un programma ?
corretto
> > se, sottoposto ad input validi, fornisce output validi.
>
> Cosa ti garantisce la validit? di un input? Non ? detto che in un ambito
teorico,
> ed avendo un programma che non sia propriamento stupido (ovvero
assimilabile
> ai modelli di automi a stati finiti o automi a pila), ogni input sia
validabile o
> meno (Problema della fermata di Turing).
>
> > Definizione (Programma robusto) Un programma ? robusto se, sottoposto ad
> > input validi e/o invalidi, comunque fornisce output validi. Questo
significa
> > che un programma robusto dovr? fornire output coerenti con le specifiche
> > anche se sottoposto ad input imprevisti. La nozione di robustezza di un
>
> Sembra parlando di modelli puramente teorici in input non valido, se
riconosciuto,
> non dovrebbe essere accettato, uscendo quindi con un opportuno messaggio
di errore.
>
> > Definizione (Programma sicuro) Un programma ? sicuro se, sottoposto ad
input
> > invalidi e/o validi, l'internal state e l'environment state sono validi.
Il
>
> Qua si passa decisamente ad un livello pi? pratico, per cui tenendo conto
> della numeor di possibili stati (finiti) assumibili da un ambiente reale,
> sarebbe, con notevole spreco di risorse, generare l'output completo
> delle possibile risposte ad ogni singola domanda "presentabile" ad un
programma ...
> Vi lascio immaginare la semplicit? della verifica gi? con un numero di
input
> possibili pari a 2^16 (giusto per dire tenerci mooooolto bassi).
> Senza tenere conto (ma di questo non mi intendo assolutamente) che il
nostro
> codice di alto livello raramente ? l'esatta rapressentazione di quello che
verr?
> eseguito a livello macchina, per cui bisognerebbe compiere l'analisi sul
codice
> generato dal compilatore, e non su quello di alto livello da noi scritto.
>
>
> Non so se tu abbia gi? discusso o meno la tua tesi, ma ad occhio quelle
sopra
> potrebbero essere delle obiezioni che ti potrebbero essere mosse in fase
di discussione.
> Buon lavoro
>
> Saverio Salatino
>
> ________________________________________________________
> http://www.sikurezza.org - Italian Security Mailing List
>


________________________________________________________
http://www.sikurezza.org - Italian Security Mailing List




[ Home | Liste | F.A.Q. | Risorse | Cerca... ]

www.sikurezza.org - Italian Security Mailing List
(c) 1999-2005