Title: Buffer%20overflow%20attack%20and%20defense
1Buffer overflow attack and defense
C Consiglio Nazionale delle Ricerche Iit
Istituto di Informatica e Telematica - Pisa
Università G. dAnnunzioDipartimento di
Scienze, Pescara
2Errori del codice
- Un errore del codice può influire sulla sicurezza
del software (in alcuni casi con conseguenze
catastrofiche). - Ad esempio nel giugno 1996 il satellite europeo
Ariane 5 è esploso subito dopo il lancio a causa
di un errore nel software il programma tentò di
inserire un numero di 64 bit in uno spazio di 16
bit, provocando un overflow.
3(No Transcript)
4Buffer overflow
- Il problema dei buffer overflow è sicuramente
quello più comune tra tutti i tipi di insicurezza
nel codice C, mentre è praticamente assente in
linguaggi di più alto livello che non lasciano al
programmatore la gestione della memoria. - I problemi di buffer overflow sono stati la
principale causa dei problemi di sicurezza
riscontrati negli utlimi 10 anni. - La tecnica del buffer overflow consiste nel
forzare la scrittura in memoria con una quantità
di informazioni superiore a quella accettabile.
Se il software è privo di controlli è possibile
inserire del codice eseguibile (bytecode) in
queste stringhe di overflow che consentono ad
esempio di eseguire comandi su shell (shellcode).
Inoltre se il software viene eseguito in modalità
root un attacco di questo tipo può garantire il
pieno possesso di tutte le funzionalità del
sistema. - I buffer overflow possono essere eseguiti sulle
seguenti zone di memoria stack, heap e bss
(block started by symbol).
5Organizzazione della memoria di un processo
- Per capire la tecnica del buffer overflow è
necessario studiare l'organizzazione della
memoria di un processo (programma). - I processi sono divisi, in memoria, in tre
regioni testo, dati e stack. La regione testo è
fissata, contiene il codice del programma ed è a
sola lettura. Qualsiasi tentativo di scrittura
provoca una violazione di segmento. La regione
dati contiene i dati inizializzati e non
(variabili statiche e globali) relativi al
processo mentre la regione stack contiene i dati
dinamici (utilizzati nella chiamata di funzioni).
0x00000000
Indirizzi di memoria bassi
Indirizzi di memoria alti
0xFFFFFFFF
6Organizzazione della memoria di un processo
7 a volte considereremo il disegno opposto
8Lo Stack
- Lo stack (pila) è una struttura dati di tipo LIFO
(Last In First Out) che consente di memorizzare
un numero variabile di informazioni. - Questa struttura dati viene utilizzata
all'interno dell'architettura degli elaboratori
per gestire le chiamate di funzioni (call in
assembly). La zona di memoria destinata alla
gestione dello stack viene suddivisa logicamente
in aree (stack frame) per ogni chiamata di
funzione.
xpop
push(x)
Stack
1) xa, 2) xb, 3) xc
1) xc, 2) xb, 3) xa
9Lo Stack e i registri di sistema
- Ogni processo viene eseguito step-by-step tramite
l'elaborazione di istruzioni successive.
L'indirizzo di memoria dell'istruzione da
eseguire, in un preciso istante, è contenuto nel
registro di sistema EIP (Extended Instruction
Pointer) a 32 bit (1dword).
10Lo Stack e i registri di sistema
- Oltre a questo registro di sistema esistono altri
registri utili per la gestione di chiamate di
funzioni (call). Il registro EBP (Extended Base
Pointer) che punta alla base di uno stack frame
ed il registro ESP (Extended Stack Pointer) che
punta alla cima dello stack frame.
11Lo Stack e i registri di sistema
- Quando viene richiamata una funzione (call) il
sistema inserisce nello stack l'indirizzo
dell'istruzione successiva, push(EIP4) dove 4
indica 4 byte (4byte1dword), successivamente
inserisce nello stack il puntatore alla base
dello stack frame corrente, push (EBP) ed infine
copia l'ESP attuale sull'EBP inizializzando così
il nuovo stack frame.
12- EIP, EBP, ESP
- EIP va in stack
- EBP va in stack (chiamato SFP)
- EBP ESP
- Settato nuovo ESP (lunghezza della procedura
chiamata)
13Un esempio in C
Analizziamo quest'esempio di codice in C per
capire meglio l'allocazione dello stack
framevoid test_function (int a, int b)
char flag char buffer10 int main()
test_function (1,2) exit(0)
EIP
Stato dello stack frame
Indirizzo di ritorno (ret) EIP 4 byte
SFP Saved Frame Pointer, valore utilizzato per
rispristinare lo stato originale di EBP (prima
della chiamata di test_function())
14Lo stack frame
- Alle variabili locali della funzione
test_function si fa riferimento mediante
sottrazione del valore del frame pointer EBP e
gli argomenti della funzione mediante addizione a
tale valore. - Quando una funzione viene richiamata, il
puntatore EIP diventa l'indirizzo di inizio del
codice della funzione. - La memoria dello stack è utilizzata per le
variabili locali e gli argomenti della funzione.
Dopo il termine dell'esecuzione della funzione,
l'intero stack frame viene estratto dallo stack
in modo da riprendere l'esecuzione
sull'istruzione di ritorno (ret).
15Esempio di overflow
Analizziamo quest'esempio di codice in C che
provoca un overflowvoid overflow_function
(char str) char buffer20
strcpy(buffer, str) // Funzione che copia str
nel buffer int main() char
big_string128 int i for(i0 i lt 128
i) big_stringi 'A'
overflow_function(big_string) exit(0)
Questa istruzioneprovoca un overflow!
16Segmentation fault
Perchè il codice precedente provoca un
Segmentation fault?
1) La prima chiamata di overflow_function
inizializza correttamente lo stack frame
2) Al momento del termine dell'esecuzione della
funzione overflow_function, l'istruzione di
ritorno è stata sovrascritta con il carattere A
(segmentation fault!)
memoriabassa
memoriabassa
AA...A
buffer
20 byte
SFP
A
Indirizzo di ritorno (ret)
A
108 byte
str (argomento)
A
memoriaalta
A
17Buffer overflow (basati sullo stack)
- Cosa succede se l'istruzione di ritorno (ret)
contiene un indirizzo di memoria valido? - In questo caso il processo continuerebbe
indisturbato eseguendo l'istruzione successiva
contenuta in ret. - Il buffer overflow basato sullo stack consiste
proprio nello sfruttare tale possibilità
sostituendo l'istruzione di ritorno ret con un
nuovo puntatore ad una porzione di codice
inserita manualmente da un intruso. - Come è possibile
- modificare tale istruzione di ritorno ed
- inserire arbitrariamente del codice in un
processo?
18Cos'è un Buffer Overrun
- Si verifica quando i dati superano la dimensione
prevista e sovrascrivono altri valori - È frequente soprattutto nel codice C/C non
gestito - Può essere di quattro tipi
- buffer overrun basato sullo stack
- buffer overrun dell'heap
- Sovrascrittura della v-table e del puntatore a
funzione - Sovrascrittura del gestore eccezioni
- Può essere sfruttato dai worm
19Possibili conseguenze dei sovraccarichi buffer
Possibile conseguenza Obiettivo dell'hacker
Violazione dell'accesso Realizzare gli attacchi DoS (denial of service) contro i server
Instabilità Interferire con il normale funzionamento del software
Inserimento di codice Ottenere privilegi per il proprio codice Sfruttare dati aziendali di vitale importanza Eseguire azioni distruttive
20I buffer overrun dell'heap
- Sovrascrivono i dati memorizzati nell'heap
- Sono più difficili da sfruttare di un buffer
overrun
xxxxxxxxxxxxxx
strcpy
21I buffer overrun dell'heap example 1
- class CustomerRecord
-
- private
- char szName20
- char szAddress10
- char szPassword20
- char szCreditHistory200
- char szBankDetails25
22- void ChangeAddress (char a)
-
- strcpy (szAddress, a)
-
- bool ChangePassword (char newpwd, char oldpwd)
-
- bool resfalse
- if (strcmp (oldpwd, szPassword)0)
-
- strcpy (szPassword, newpwd)
- restrue
-
- return res
-
23- char GetSensitiveData (char pwd)
-
- if (strcmp (pwd, szPassword)0)
-
- // return all the personal info!
- return "Here's all the personal info...\n"
-
- else
- return ""
-
24- Eseguire procedura
- Come faccio ad ottenere
- GetSensitiveData password
- Se non conosco la passwordsecret??
- Trucco
- ChangeAddress ?
- Buffer overflow su ?? Heap!! ?
- char szAddress10
- char szPassword20
25Esempio di sovraccarico buffer basato sullo stack
- int main(int argc, char argv)
-
- //A blatant shortcut
- printf("Address of foo p\n", foo)
- printf("Address of bar p\n", bar)
- foo(argv1)
- return 0
-
- Attacco lanciare bar
- senza che codice lanci bar
26- void foo(const char input)
-
- char buf10
- //What? No extra arguments supplied to
printf? - //It is a cheap trick to view the stack
- printf("My stack looks like\np\np\np\np\n
p\np\n\n") - //Pass the user input straight to secure code
public enemy 1. - strcpy(buf, input)
- printf("s\n", buf)
- printf("Now the stack looks
like\np\np\np\np\np\np\n\n") -
- void bar(void)
-
- printf("The attack!\n")
-
27- Devo passare dei parametri a foo, in modo tale
che AL RITORNO mi vada prima ad eseguire bar!!! - Quindi devo far scrivere a foo sul suo indirizzo
di ritorno lindirizzo di bar
28Eseguiamo codice
- 00000000
- 00000A28
- 7FFDC000
- 0012FEE4
- 0040108A
- 0032116F
buf
SFP
ret
29Dopo chiamata procedura e input 12345
- 34333231
- 00000035
- 7FFDF000
- 0012FEE4
- 0040108A
- 0032116F
- Dove ho scritto su buffer 12345 ???
- Conosciamo cygnus HexEditor
- Little-big endian
buf
SFP
ret
30- Conosciamo cygnus HexEditor
- 12345
- In esadecimale
- 31 32 33 34 35
31- Big-endian e little-endian sono due metodi
differenti usati dai calcolatori per
immagazzinare in memoria dati di dimensione
superiore al byte (es. word, dword, qword).
32- big-endian è la memorizzazione che inizia dal
byte più significativo per finire col meno
significativo è utilizzata dai processori
Motorola, IBM e Sun e nei protocolli usati in
Internet - viene anche chiamato network byte order.
- little-endian è la memorizzazione che inizia dal
byte meno significativo per finire col più
significativo è utilizzata dai processori Intel
e Digital
33Etimologia ?
- Big-endian e little-endian sono tratti dal nome
dei due gruppi di persone incontrati dal
personaggio fantastico Gulliver durante i suoi
viaggi, in continuo litigio su quale lato fosse
il migliore da rompere nelle uova.
34esempi
Nel caso di una DWORD, il numero esadecimale
0x01234567 verrà immagazzinato rispettivamente
Little endian Big endian
----------------
---------------- 0x670x450x230x01
0x010x230x450x67
---------------- ----------------
byte 0 1 2 3 0 1 2
3 (Negli esempi il valore in grassetto è il
byte più significativo)
35Dopo chiamata procedura e input 12345
- 34333231
- 00000035
- 7FFDF000
- 0012FEE4
- 0040108A
- 0032116F
- Dove ho scritto su buffer 12345 ???
- Conosciamo cygnus HexEditor
- Little-big endian
buf
SFP
ret
Allora che input devo dare ?? per ottenere cosa
???
36- Provare input 1234
- 12341234
- 1234123412 (10 byte) per buff
- 123412341234 (posso facilmente salvarne di piu
perche allocate multipli di dword) - Poi sovrascrivo indirizzo EBP e indirizzo di
ritorno!! - Uso di editor esadecimale
- FINE!! ?
37Weird example!!! LAB!
38- the goal is to enter a serial and to get the good
boy message - Using a buffer overflow of the stack!!
- Tools
- Debugger
- odbg110.zip
- Disassembler
- freeida43.exe
- Hexeditor
- cygnusfe.zip
39-- The analyst's weird crackme -- ----------------
----------------- enter your serial please
40!Run ida disassembler!
- No way to go to the
- CODE00401177 push offset
aWooCongrats format
41The source ?
int main() int i,len,temp unsigned
char name75 unsigned long check0
printf("-- The analyst's weird crackme --\n")
printf("---------------------------------\n")
printf("enter your serial please\n")
gets(name) asm nop
lenstrlen(name)
42 //cout ltlt len if (len lt 25) goto theend
if (len gt 120 ) goto theend for (i1 i lt
len i) temp namei
if (temp 31337) goto theend if
(temp lt 5000) goto theend if (temp gt 15000)
goto theend goto theend
printf("wOO! congrats )\n")
theend getch() return 0
43- Analisi dellassembler
- Push (per mettere su stack parametri della gets,
) - CODE0040112E pop ecx
- CODE0040112F lea eax,
ebps buffer - CODE00401132 push eax
s - CODE00401133 call _gets
get entered serial - CODE00401138 pop ecx
- CODE00401139 nop
- CODE0040113A lea edx,
ebps - CODE0040113D push edx
s
44- Quanto è grande buffer in memoria?
45Vediamo struttura stack!!
- Pulsante open stack variables (CTRL-K)
- FFFFFFB4 s db ?
- FFFFFFB5 db ? undefined
-
-
- FFFFFFFD db ? undefined
- FFFFFFFE db ? undefined
- FFFFFFFF db ? undefined
- 00000000 s db 4 dup(?)
- 00000004 r db 4 dup(?)
- 00000008 argc dd ?
- 0000000C argv dd ?
offset (FFFFFFFF) - 00000010 envp dd ?
offset (FFFFFFFF) - 00000014
Buf di quante word?
46- Siccome indirizzo delle istruzioni di successo è
00401177 - dovremo provocare un buffer overflow in una
procedura e inserire come codice di ritorno
quello - Tramite editor esadecimale
- 00401177 ? w_at_
47n.b
- Finora abbiamo solo modificato puntatore ..
- Non abbiamo iniettato noi codice (lo faremo
nellesercitazione linux)
48Di solito,
- Lo scopo di un buffer overflow attack è di
modificare il funzionamento di un programma
privilegiato in modo da prenderne il controllo e,
nel caso il programma abbia sufficienti
privilegi, prendere il controllo dell host. - Typically the attacker
- is attacking a root program, and
- immediately executes code similar to exec(sh)
to get a root shell.
49- To achieve this goal, the attacker must achieve
two sub-goals - Arrange for suitable code to be available in the
program's address space. - Get the program to jump to that code, with
suitable parameters loaded into registers
memory.
50The buffer part
- how the attack code is placed in the victim
programs address space - Inject it!
- It is already there
- For instance, if the attack code needs to execute
exec(/bin/sh), and there exists code in libc
that executes exec(arg) where arg is a string
pointer argument, then the attacker need only
change a pointer to point to /bin/sh and jump
to the appropriate instructions in the libc
library
51The overflow part
- how the attacker overflows a program buffer to
alter adjacent program state - Overflow a buffer with weak bound check, with the
goal of corrupting the state of an adjacent part
of the programs state (adjacent pointers)
52Le vie di ingresso!!
53Buffer overflow (basati sullo stack)
- Ovviamente il processo deve avere delle "vie
d'ingresso". Ad esempio dei parametri che
l'utente può specificare nella linea di comando,
dei pacchetti da inviare ad una porta in ascolto
del processo (quest'ultimo caso è quello più
pericoloso perchè consente di effettuari attachi
da remoto). - In questa sede consideriamo l'esempio classico
di attacco basato sul buffer overflow dello stack
su di un parametro del processo a linea di
comando. - Che tipo di codice è possibile inserire in un
attacco basato su buffer overflow? Si deve
utilizzare un bytecode, ossia un codice autonomo,
scritto in linguaggio macchina, che non deve
contenere determinati caratteri speciali nelle
sue istruzioni perchè deve sembrare un buffer di
dati.
54- Un tipico esempio di bytecode è il cosiddetto
shellcode. Ossia un bytecode che genera una
shell. - Se si riesce a manomettere un programma suid
root in maniera che esegua una shellcode è
possibile prendere il possesso di un sistema,
avendo privilegi da root, mentre il sistema è
convinto che il programma suid root stia ancora
assolvendo i suoi compiti previsti.
55- A questo punto sorgono due problemi (1) Dal
momento che dobbiamo inserire del codice di tipo
bytecode nello stack, che è una struttura
dinamica, come possiamo determinare la posizione
assoluta in memoria della nostra prima istruzione
bytecode?(2) Una volta determinata questa
posizione come possiamo modificare l'istruzione
di ritorno ret dello stack frame? - Non è possibile determinare la posizione
assoluta del bytecode nello stack, per questo
motivo è necessario utilizzare un espediente, il
NOP sled (NOP nessuna operazione, sled è la
traduzione di slitta)
56- NOP è un istruzione assembler vuota, non esegue
niente. Viene utilizzata per gestire
sincronizzazioni su cicli di calcolo... - La tecnica del NOP sled consiste nell'inserire
prima del nostro bytecode un grande array di
istruzioni NOP (una slitta di NOP). Così facendo
anche se l'istruzione di ritorno (ret) dovesse
saltare su una posizione qualsiasi della slitta
di NOP alla fine il bytecode verrebbe comunque
eseguito. - Ciò non toglie che per risolvere il primo
problema dobbiamo comunque avere una stima
dell'indirizzo del bytecode.
57- Una volta che abbiamo stimato la possibile
posizione del nostro bytecode possiamo utilizzare
un'altra tecnica per risolvere il secondo
problema che consiste nel riempire la fine del
nostro buffer, dopo il bytecode, con l'indirizzo
di ritorno stimato. - In questa maniera, purchè uno di questi
indirizzi di ritorno sovrascriva l'indirizzo di
ritorno reale, l'espediente darà il risultato
desiderato. - Utilizzando queste tecniche il nostro buffer
avrà una forma del genere
58- Di seguito è riportato il codice assembly
(memorizzato in una variabile definita in C) di
una shellcode (si veda il file exploit.c in
allegato) - char shellcode "\x31\xc0\xb0\x46\x31\xdb\x31\x
c9\xcd\x80\xeb\x16\x5b\x31\xc0"
"\x88\x43\x07\x89\x5b\x08\x89\x43\x0c\xb0\x0b\x8d\
x4b\x08\x8d" "\x53\x0c\xcd\x80\xe8\xe5\xff\xff\xff
\x2f\x62\x69\x6e\x2f\x73""\x68" - Gli step per l'esecuzione del ns. buffer
overflow 1) stima dell'indirizzo di ritorno
(ret), nel ns. caso retstack pointer 2) buffer
NOP sled shellcode indirizzo ret ripetuto
3) esecuzione del programma vuln.c che ha
vulnerabilità passandogli come parametro buffer
il buffer costruito in exploit.c (tramite
l'istruzione exec(./vuln,vuln,buffer,0))
59Heap!!
60 - Un tipo di vulerabilità simile allo stack-based
buffer overflow è lo heap-based buffer overflow
che segue lo stesso principio - ma partendo da variabili allocate nello heap,
quindi non staticamente ma dinamicamente con
funzioni della famiglia malloc(). - Lo heap ("mucchio") è una zona di memoria
allocata dinamicamente durante l'esecuzione
(runtime) di un processo. - Un array di caratteri, allocato dinamicamente
attraverso una chiamata malloc/calloc fara' parte
dello heap. In generale qualunque assegnazione
dinamica di memoria contigua farà parte dello
heap. Viceversa, quando la porzione di memoria
non e' piu' utile, viene chiamata una funzione
che libera tale zona di memoria free().
61Un semplice overflow basato su heap
- Consideriamo l'esempio contenuto nel file heap.c
(in allegato). In questo caso si allocano due
variabili userinput e outputfile nello heap con
dimensioni fisse e pari a 20 byte. - Cosa succede se si inserisce un valore gt di 20
byte in una delle due variabili? Si ha un
overflow. E se le due variabili vengono allocate
in memoria in zone contigue l'overflow su una di
esse può sovrascrivere il contenuto dell'altra. - char userinput malloc(20)
- char outputfile malloc(20)
-
- Ad esempio un overflow sulla
- variabile userinput provoca la
- sovrascrittura della variabile outputfile.
Heap
userinput
20
outputfile
20
62- Proviamo ad eseguire il programma heap.c
- ./heap prova
- ---DEBUG--
- userinput _at_ 0x80499d8 prova
- outputfile _at_ 0x80499f0 /tmp/notes
- distance between 24
- -----------------
- Writing to prova to the end of /tmp/notes...
- Cosa succede se utilizziamo un parametro con più
di 24 byte? - ./heap 123456789012345678901234test
- ---DEBUG--
- userinput _at_ 0x80499d8 12345678901234567890123
4test - outputfile _at_ 0x80499f0 test
- distance between 24
- -----------------
- Writing to 123456789012345678901234test to the
end of test...
63BSS
64Buffer overflow (basati su BSS, Block Started by
Symbol)
- I buffer overflow basati su BSS sfruttano lo
stesso principio dei buffer overflow basati su
heap. Le variabili globali e statiche di un
programma vengono allocate nella zona di memoria
BSS in maniera contigua. Un overflow di una di
queste variabili provoca la sovrascrittura di
altre variabili. - Consideriamo l'esempio (bss_game.c, in
allegato). In questo programma si utilizzano due
variabili statiche static char buffer20
static int (function_ptr) (int user_pick) - Come per l'esempio sullo heap è possibile
provocare un overflow della variabile buffer
(parametro del programma) sovrascrivendo il
contenuto del puntatore a funzione function_ptr!
In questo caso posso far eseguire un bytecode
come per il buffer overflow basato sullo stack!!!
65Come evitare buffer overflow
66Come difendersi dai buffer overrun
- Utilizzare con particolare cautela le seguenti
funzioni - strcpy
- strncpy
- CopyMemory
- MultiByteToWideChar
- Utilizzare l'opzione di compilazione /GS in
Visual C per individuare i sovraccarichi buffer - Utilizzare strsafe.h per un gestione del buffer
più sicura
67- La soluzione più immediata e sicura consiste
nell'inserire controlli sulle dimensioni dei
parametri inseriti dall'utente, in modo da
assicurarsi che non si verifichino overflow. - Molte volte, soprattutto in programmi complessi,
l'utilizzo di controlli sulle dimensioni delle
variabili può risultare pesante. Si possono così
utilizzare funzioni che non provocano overflow
anche in presenza di parametri sovradimensionati.
Ad esempio l'utilizzo delle funzioni Cstrlcpy()
e strlcat() al posto di strcpy(). - Un alternativa è l'utilizzo di librerie
considerate "sicure progettate proprio per
evitare buffer overflow. Ad esempio LibSafe
(http//www.research.avayalabs.com/project/libsafe
/). - Altre possibilità di prevenire buffer overflow
sono fornite da strumenti in grado di rilevare
tali bug, come StackGuard (per i buffer overflow
basati sullo stack). http//www.cse.ogi.edu/DISC/p
rojects/immunix/StackGuard/
68Defenses
- Writing correct code
- Code auditing
- Non executable buffer
- Data segment non executable
- Code pointer integrity checking
- detect that a code pointer has been corrupted
before it is dereferenced. - Stack Introspection by Snarskii
- Create a new libc
- Stackguard (Activation Record Integrity
Checking) - Pointguard (function pointer integrity checking)
69Defenses
- Array bounds checking
- The Compaq C compiler for the Alpha CPU
(-check_bounds) - only explicit array references are checked, i.e.
a3 is checked, while (a3) is not - since all C arrays are converted to pointers when
passed as arguments, no bounds checking is
performed on accesses made by subroutines - dangerous library functions (i.e. strcpy()) are
not normally compiled with bounds checking, and
remain dangerous even with bounds checking
enabled - Richard Jones and Paul Kelly developed a gcc
patch that does full array bounds checking for C
programs. - The performance costs are substantial
- Purify is a memory usage debugging tool for C
programs. - Purify uses object code insertion to instrument
all memory accesses. After linking with the
Purify linker and libraries, one gets a standard
native executable program that checks all of its
array references to ensure that they are
legitimate. - imposes a 3 to 5 times slowdown.
- Type-Safe Languages
70Safe and unsafe functions
71Strcpy vs strncpy
char strcpy ( char destination, const char
source )
- Copies the C string pointed by source into the
array pointed by destination, including the
terminating null character. - To avoid overflows, the size of the array pointed
by destination shall be long enough to contain
the same C string as source (including the
terminating null character), and should not
overlap in memory with source.
72Strcpy vs strncpy
char strncpy ( char destination, const char
source, size_t num )
- Copies the first num characters of source to
destination. - If the end of the source C string (which is
signaled by a null-character) is found before
num characters have been copied, destination is
padded with zeros until a total of num
characters have been written to it. - No null-character is implicitly appended to the
end of destination, so destination will only be
null-terminated if the length of the C string in
source is less than num.
73strncpy
- if the length of the src string is gt n, you end
up without null termination - char destLEN
- char src ... / src is set to point to a source
string of unknown length / - strncpy(dest,src,LEN)
- destLEN-1'\0' / null terminate for safety /
74strncpy
- Using strncpy() has performance implications,
because it zero-fills all the available space in
the target buffer after the \0 terminator. - a strncpy() of a 13-byte buffer into a 2048-byte
buffer overwrites the entire 2048-byte buffer
75strnlcpy
- Look on the web!!
- Problemi di compatibilità!!
76- Fail solo se input o buf e un illegal pointer
- Se input troppo lungo verrà troncato ?
77- Non si tronca il buffer, se troppo lungo si
ottiene errore GESTITO!!
78Sprintf vs snprintf
int sprintf (String, Format, Value, ...) char
String const char Format
- The sprintf subroutine converts, formats, and
stores the Value parameter values, under control
of the Format parameter, into consecutive bytes,
starting at the address specified by the String
parameter. The sprintf subroutine places a null
character (\0) at the end. You must ensure that
enough storage space is available to contain the
formatted string.
79Sprintf vs snprintf
int snprintf (String, Number, Format, Value, . .
.) char String int Number const char
Format
- The snprintf subroutine is identical to the
sprintf subroutine with the addition of the
Number parameter, which states the size of the
buffer referred to by the String parameter.
80_snprintf
- In w32 environment
- Non setta il \0 finale!!! ?
81Gets vs fgets
- char gets(char s)
- read a line of data from STDIN. gets continues to
read characters until NEWLINE or EOF is seen - The NEWLINE character is NOT placed in the buffer
- gets does NOT check the size of the buffer and
overflow on the stack can occour.
82- char fgets(char s, int n, FILE stream)
- fgets is used to read a line of data from an
external source. - If fgets is reading STDIN, the NEWLINE character
is placed into the buffer. - it checks that the incoming data does not exceed
the buffer size
83Use strsafe.h!!
84Secure Programming open-source software
85Open vs closed source
- Open-source software is more secure than closed
software - E.S. Raymond, The Cathedral the Bazaar Musings
on Linux and Open Source by an Accidental
Revolutionary, OReilly Assoc., 1999. - And the contrary
- K. Brown, Opening the Open Source Debate, Alexis
de Tocqueville Inst., 2002 www.adti.net/cgi-loca
l/SoftCart.100.exe/online-store/scstore/p-
brown_1.html?Lscstorellfs8476ff0a810a104202762
2 - !!The defender can install and configure the SW
with high security concerns!! - !!The attacker know the source code!! (if the
defender just install it wothout any personal
configuration!)
86Toward a perfect software!
- Software auditing
- which prevents vulnerabilities by searching for
them ahead of time, with or without automatic
analysis - Vulnerability mitigation
- which are compile-time techniques that stop bugs
at runtime - Behavior management
- which are operating system features that either
limit potential damage or block specific
behaviors known to be dangerous
87SW auditing tools
881. Software auditing
- Auditing source code for correctness!!
- Good practice!! ?
- Difficult and time-consuming ?
- Sardonix project (2003)
- Record which code has been audited and by whom
- Provide rank for people partecipating to the
project (to be used in the resume) - Help novice auditors with a lot of resources and
FAQ - Static analyzers
- Dynamic debuggers
89Sardonix resource
- Static analyzers
- Sintactically check the code
- Ok for strongly typed languages (Java, ML, )
- But some false positive/negative
- Undecidable for for weakly typed languages (C,
Perl, ) - Use some heuristics
- Dynamic debuggers
- Run the program under test loads
902. Vulnerability mitigation tools
913. Behaviour management