Paldium
Well-Known Member
»Unsere Anstrengungen liegen vor allem in der [...] vorausschauenden Sicherheit [...].«
Für alle, die mit dem von double-p geposteten Vortrag »Exploit Mitigation Techniques« nichts anfangen oder dieser ihnen zu theoretisch ist, einfach mal ein paar Beispielcodes.
Erstmal zu meinem System:
Guardpages
Eine Guardpage wird am Ende einer Page angelegt. Damit ich auch wirklich am Ende meiner zugewiesenen Page ankomme, schreibe ich 64 KBit Nullen:
randomisiertes malloc()
Ich reserviere einfach 20 Charpointer mit 500 Zeichen ... vollkommen beliebig:
Wie man sieht kann man nichts darüber aussagen, wo die Daten landen bzw. in welcher Reihenfolge dies geschieht (mal vor dem vorherigen Speicherplatz, dann wieder dahinter, etc.)
ProPolice
Ganz klar wird mir in meiner Funktion input der Stack überschrieben. Propolice wird das merken, da am Ende des Stacks Zufallswerte stehen, die am Ende der Funktion auf ihre Richtigkeit hin überprüft werden:
Und jetzt nochmal ohne Propolice:
systrace
(Seltsam, dass das noch gar nicht genannt wurde ...)
Jaaa, einfach mal Kreativität freien Lauf lassen und vorstellen, dass evil() irgendein Bytecode ist, den man mit einer vorherigen Schwachstelle (über Kommandozeile eingeschleust hat - oder was auch immer).
Mit systrace -A lege ich erstmal eine Policy an, so, wie das Programm laufen soll:
Ich geh hier jetzt nicht auf die Konfiguration von systrace ein, dafür gibt es Manualseiten. Es sei aber soviel gesagt, dass für trace nur noch das erlaubt ist, was bisher ausgeführt wurde. Mal sehen, was passiert, wenn ich jetzt die Shell über evil() starten will (mit -a erzwinge ich die neu erstellte Richtlinie):
Wenn ich Mist geschrieben habe oder es Verbesserungsvorschläge gibt, nur her damit! Schließlich will ich auch was dazulernen.
Für alle, die mit dem von double-p geposteten Vortrag »Exploit Mitigation Techniques« nichts anfangen oder dieser ihnen zu theoretisch ist, einfach mal ein paar Beispielcodes.
Erstmal zu meinem System:
Code:
$ uname -msr
OpenBSD 3.9 i386
Guardpages
Code:
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main(void)
{
char *pointer;
if ((pointer = malloc(10)) == NULL)
err(1, NULL);
memset(pointer, 0, 65536);
exit(0);
}
Eine Guardpage wird am Ende einer Page angelegt. Damit ich auch wirklich am Ende meiner zugewiesenen Page ankomme, schreibe ich 64 KBit Nullen:
Code:
$ gcc -o guard guard.c
$ ./guard
Segmentation fault (core dumped)
randomisiertes malloc()
Code:
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
int
main(void)
{
int i;
char *pointer[20];
for (i = 0; i < 20; i++) {
if ((pointer[i] = malloc(500)) == NULL)
err(1, NULL);
printf("%2d. Pointer zeigt auf %x\n", i + 1, pointer[i]);
}
for (i = 0; i < 20; i++) {
free(pointer[i]);
}
exit(0);
}
Ich reserviere einfach 20 Charpointer mit 500 Zeichen ... vollkommen beliebig:
Code:
$ gcc -o malloc malloc.c
$ ./malloc
1. Pointer zeigt auf 8a1d9000
2. Pointer zeigt auf 8a1d9200
3. Pointer zeigt auf 8a1d9400
4. Pointer zeigt auf 8a1d9600
5. Pointer zeigt auf 8a1d9800
6. Pointer zeigt auf 8a1d9a00
7. Pointer zeigt auf 8a1d9c00
8. Pointer zeigt auf 8a1d9e00
9. Pointer zeigt auf 84fb5000
10. Pointer zeigt auf 84fb5200
11. Pointer zeigt auf 84fb5400
12. Pointer zeigt auf 84fb5600
13. Pointer zeigt auf 84fb5800
14. Pointer zeigt auf 84fb5a00
15. Pointer zeigt auf 84fb5c00
16. Pointer zeigt auf 84fb5e00
17. Pointer zeigt auf 87876000
18. Pointer zeigt auf 87876200
19. Pointer zeigt auf 87876400
20. Pointer zeigt auf 87876600
$ ./malloc
1. Pointer zeigt auf 7f714000
2. Pointer zeigt auf 7f714200
3. Pointer zeigt auf 7f714400
4. Pointer zeigt auf 7f714600
5. Pointer zeigt auf 7f714800
6. Pointer zeigt auf 7f714a00
7. Pointer zeigt auf 7f714c00
8. Pointer zeigt auf 7f714e00
9. Pointer zeigt auf 851c0000
10. Pointer zeigt auf 851c0200
11. Pointer zeigt auf 851c0400
12. Pointer zeigt auf 851c0600
13. Pointer zeigt auf 851c0800
14. Pointer zeigt auf 851c0a00
15. Pointer zeigt auf 851c0c00
16. Pointer zeigt auf 851c0e00
17. Pointer zeigt auf 7c716000
18. Pointer zeigt auf 7c716200
19. Pointer zeigt auf 7c716400
20. Pointer zeigt auf 7c716600
Wie man sieht kann man nichts darüber aussagen, wo die Daten landen bzw. in welcher Reihenfolge dies geschieht (mal vor dem vorherigen Speicherplatz, dann wieder dahinter, etc.)
ProPolice
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void
input(void)
{
char eingabe[10];
memset(eingabe, 0, 20);
return;
}
int
main(void)
{
input();
exit(0);
}
Ganz klar wird mir in meiner Funktion input der Stack überschrieben. Propolice wird das merken, da am Ende des Stacks Zufallswerte stehen, die am Ende der Funktion auf ihre Richtigkeit hin überprüft werden:
Code:
$ gcc -o stack stack.c
$ ./stack
Abort trap (core dumped)
Und jetzt nochmal ohne Propolice:
Code:
$ gcc -fno-stack-protector -o stack stack.c
$ ./stack
$ _
systrace
(Seltsam, dass das noch gar nicht genannt wurde ...)
Code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void
evil(void)
{
char *nargv[2];
nargv[0] = "/bin/sh";
nargv[1] = NULL;
execvp("/bin/sh", nargv);
}
void
good(void)
{
char *nargv[2];
nargv[0] = "/bin/ls";
nargv[1] = NULL;
execvp("/bin/ls", nargv);
}
int
main(int argc, char **argv)
{
if (argc == 1)
good();
else
evil();
exit(1);
}
Jaaa, einfach mal Kreativität freien Lauf lassen und vorstellen, dass evil() irgendein Bytecode ist, den man mit einer vorherigen Schwachstelle (über Kommandozeile eingeschleust hat - oder was auch immer).
Mit systrace -A lege ich erstmal eine Policy an, so, wie das Programm laufen soll:
Code:
$ gcc -o trace trace.c
$ systrace -A ./trace
guard guard.core malloc.c stack.c trace
guard.c malloc stack stack.core trace.c
Ich geh hier jetzt nicht auf die Konfiguration von systrace ein, dafür gibt es Manualseiten. Es sei aber soviel gesagt, dass für trace nur noch das erlaubt ist, was bisher ausgeführt wurde. Mal sehen, was passiert, wenn ich jetzt die Shell über evil() starten will (mit -a erzwinge ich die neu erstellte Richtlinie):
Code:
$ systrace -a ./trace bytecode
Segmentation fault (core dumped)
Wenn ich Mist geschrieben habe oder es Verbesserungsvorschläge gibt, nur her damit! Schließlich will ich auch was dazulernen.