1x2 PDF - TU Dortmund

Transcrição

1x2 PDF - TU Dortmund
Tafelübung zu BS
5. Sicherheit
Olaf Spinczyk
Arbeitsgruppe Eingebettete Systemsoftware
Lehrstuhl für Informatik 12
TU Dortmund
[email protected]
http://ess.cs.uni-dortmund.de/~os/
http://ess.cs.tu-dortmund.de/DE/Teaching/SS2013/BS/
1
Agenda
●
Besprechung Aufgabe 4: Dateioperationen
●
UNIX, C und Sicherheit
● Gefährliche
Funktionen in C
● Buffer Overflows
● Schutzmaßnahmen
BS: U5 – Sicherheit
2
Besprechung Aufgabe 4
●
→ Foliensatz Besprechung
BS: U5 – Sicherheit
3
„Gefährliche“ Funktionen
●
●
scanf()
gets()
liest so lange Zeichen von stdin, bis ein Newline oder EOF kommt,
und legt diese nacheinander ab buf in den Speicher
● ähnlich scanf("%s", buf);
●
●
strcpy()
strcat()
sprintf()
●
Was haben diese Funktionen gemeinsam?
●
●
Alle schreiben ab einer bestimmten Adresse in den Speicher.
● Zur Laufzeit kann nicht entschieden werden, ob die
Abbruchbedingung irgendwann erfüllt wird.
●
BS: U5 – Sicherheit
4
„Gefährliche“ Funktionen: gets()
●
Passwortabfrage in einem su-ähnlichen Programm
int
int ask_passwd(void)
ask_passwd(void)
{{
char
char buf[8];
buf[8];
printf("Passwort:");
printf("Passwort:");
gets(buf);
gets(buf);
if
if (check_passwd(buf))
(check_passwd(buf))
return
return 1;
1;
else
{
else {
printf("Falsches
printf("Falsches Passwort!\n");
Passwort!\n");
return
return 0;
0;
}}
}}
$ gcc -o login login.c
/tmp/ccoMGotc.o: In function `ask_passwd':
login.c:(.text+0x19): warning: the `gets' function
is dangerous and should not be used.
BS: U5 – Sicherheit
5
Pufferüberlauf
void
void start_shell(void)
start_shell(void) {{
gid_t
gid_t gid
gid == getegid();
getegid();
uid_t
uid
uid_t uid == geteuid();
geteuid();
if
if (setresgid(gid,
(setresgid(gid, gid,
gid, gid))
gid)) perror("setresgid");
perror("setresgid");
if
if (setresuid(uid,
(setresuid(uid, uid,
uid, uid))
uid)) perror("setresuid");
perror("setresuid");
execlp("/bin/sh",
execlp("/bin/sh", "/bin/sh",
"/bin/sh", NULL);
NULL);
}}
int
int main(void)
main(void) {{
if
if (ask_passwd())
(ask_passwd())
start_shell();
start_shell();
return
return 0;
0;
}}
$ ./login
Passwort:12345678abcdef
Falsches Passwort!
Segmentation fault
●
Was ist hier passiert?
BS: U5 – Sicherheit
6
Was ist passiert?
int
int ask_passwd(void)
ask_passwd(void) {{
char
char buf[8];
buf[8];
printf("Passwort:");
printf("Passwort:");
gets(buf);
gets(buf);
...
...
●
die Eingabe hat den
Framepointer und die
Rücksprungadresse
überschrieben
●
●
●
●
Stack-Layout kann auf eurer Maschine evtl.
anders aussehen, Disassembler verwenden!
→ Sprung auf eine nicht
ausführbare Adresse
→ Segmentation Fault
Das ist noch der
harmloseste Fall!
...
f
e
d
Rücksprungadresse
c
b
a
9
alter
Framepointer
%ebp
(Framepointer)
8
7
buf[7]
6
buf[6]
5
buf[5]
4
buf[4]
3
buf[3]
2
buf[2]
1
buf[1]
0
buf[0]
%esp
(Stackpointer)
BS: U5 – Sicherheit
7
Pufferüberlauf-Angriff
●
●
Prozess kann auf diese Weise zum Sprung zu beliebigen
Adressen gezwungen werden!
kann auch ausgenutzt werden:
$ nm login | fgrep start_shell
080485ab T start_shell
●
da solche Adressen aus nicht-darstellbaren Zeichen
bestehen können, ist ein Hilfsprogramm/-script nötig
Umleiten von stdin
● Ausgabe der Bytesequenz mit der Adresse am Ende (Byteorder!)
● „Weiterleitung“ von stdin
●
$ ( printf "12345678abcd\xab\x85\x04\x08\n" ;
cat /dev/stdin ) | ./login
BS: U5 – Sicherheit
8
Codeinjektion
●
Ein solcher Einsprungpunkt (start_shell) ist nett, aber
nicht unbedingt notwendig.
●
Sogar Programme, die nur „ungefährliche“ Funktionen
enthalten, können dazu gebracht werden, beliebiges zu
tun!
●
Anstatt nur einer Rücksprungadresse wird gleich
entsprechender Maschinencode (sog. Shellcode)
mitgeliefert, in den dann gesprungen werden kann.
● Rücksprungadresse wird mit Adresse innerhalb des
Stacks überschrieben, an dem der Shellcode liegt!
BS: U5 – Sicherheit
9
Weitere Techniken
●
Return to libc: Rücksprungadresse wird mit Adresse z.B.
der libc-Funktion system überschrieben
●
system(3) führt beliebige Shell-Kommandos aus (~ fork + exec)
system("ls
system("ls -l");
-l");
●
●
Heap-Überlauf: Überschreiben von anderen Variablen auf
dem Heap möglich
●
●
der Stack wird wie bei einem normalen Aufruf von system
präpariert!
dadurch indirekt oft ebenfalls beliebiger Code ausführbar
empfohlene Artikel (natürlich nicht prüfungsrelevant):
● Klassiker: "Smashing the Stack for Fun and Profit"
● modernere Techniken:
"x86-64 buffer overflow exploits and borrowed code chunks exploitation technique"
BS: U5 – Sicherheit
10
Praxisrelevanz?
●
Unix Morris Worm (sendmail) – Buffer Overflow / gets
●
●
●
siehe Vorlesung
Blaster Worm (aka. Lovsan, 2003)
SQL Slammer (2003)
Stack Buffer Overflow in Microsoft SQL Server (über UDP-Port 1434)
● rapide Ausbreitung (bis zu 75.000 Hosts in den ersten 10 Minuten)
● starke Beeinträchtigung des Internet-Datenverkehrs
●
●
Sasser (2004)
Stack Buffer Overflow in LSASS (Local Security Authority
Subsystem Service) (TCP-Port 445), unterschiedl. Varianten
● Autor: 18j. deutscher Informatikstudent (3,5 Jahre auf Bewährung!)
●
●
Conficker (2008 bis heute)
RPC Buffer Overflow, Shellcode
● ähnlich starke Verbreitung wie SQL Slammer (~3-15 Mio. PCs), u.a.
Teilausfall diverser Streitkräfte (Frz./Brit. Marine, Bundeswehr)
●
BS: U5 – Sicherheit
11
Schutzmaßnahmen (1)
●
Hardware
●
●
●
NX-Bit / XD-Bit (SPARC und neuere IA32/64-Prozessoren)
→ Stack-/Heap- und Daten-Speicherseiten Not eXecutable
Betriebssystem
●
address space randomization
●
stack randomization
Compiler
●
z.B. GCC Stack Smashing Protector (SSP, aka ProPolice)
●
standardmäßig im Einsatz z.B. unter OpenBSD, FreeBSD, Ubuntu
●
sonst meist per Compilerflag -fstack-protector zuschaltbar
●
Funktionsweise: Es werden bekannte Zahlen, „Canaries“, vor und
hinter den Puffer geschrieben und überwacht. („Canaries“ sind eine
Anspielung auf die Kanarienvögel in Kohlemienen, die bei giftigen
Gasen als erste umgekippt sind)
BS: U5 – Sicherheit
12
Schutzmaßnahmen (2)
●
Programmierer
strcpy(), strcat() → strncpy(), strncat()
● sprintf() → snprintf()
● gets() → fgets()
● scanf() → Feldbreite beschränken (scanf("%10s",buf))
●
BS: U5 – Sicherheit
13

Documentos relacionados