GNU/Linux >> Znalost Linux >  >> Linux

Jak se vyhnout útokům typu Stack Smashing pomocí GCC

Rozbíjení zásobníku je módní termín používaný pro přetečení zásobníku zásobníku. Týká se útoků, které využívají chyby v kódu umožňující přetečení vyrovnávací paměti. Dříve bylo výhradně odpovědností programátorů/vývojářů ujistit se, že v jejich kódu neexistuje možnost přetečení vyrovnávací paměti, ale časem mají kompilátory jako gcc příznaky, které zajišťují, že problémy s přetečením vyrovnávací paměti nebudou zneužity crackery k poškození systému. nebo program.

O těchto příznacích jsem se dozvěděl, když jsem se snažil reprodukovat přetečení vyrovnávací paměti na mém Ubuntu 12.04 s verzí gcc 4.6.3. Zde je to, co jsem se snažil udělat:

#include <stdio.h>
#include <string.h>

int main(void)
{
    int len = 0;
    char str[10] = {0};

    printf("\n Enter the name \n");

    gets(str); // Used gets() to cause buffer overflow

    printf("\n len = [%d] \n", len);

    len  = strlen(str);
    printf("\n len of string entered is : [%d]\n", len);

    return 0;
}

Ve výše uvedeném kódu jsem použil get() k přijetí řetězce od uživatele. a pak vypočítal délku tohoto řetězce a vytiskl zpět na stdout. Cílem je vložit řetězec, jehož délka je více než 10 bajtů. Protože get() nekontroluje hranice pole, tak se pokusí zkopírovat vstup do vyrovnávací paměti str a tím dojde k přetečení vyrovnávací paměti.

Toto se stalo, když jsem spustil program:

$ ./stacksmash 

 Enter the name
TheGeekStuff

 len = [0] 

 len of string entered is : [12]
*** stack smashing detected ***: ./stacksmash terminated
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(__fortify_fail+0x45)[0xb76e4045]
/lib/i386-linux-gnu/libc.so.6(+0x103ffa)[0xb76e3ffa]
./stacksmash[0x8048548]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0xb75f94d3]
./stacksmash[0x8048401]
======= Memory map: ========
08048000-08049000 r-xp 00000000 08:06 528260     /home/himanshu/practice/stacksmash
08049000-0804a000 r--p 00000000 08:06 528260     /home/himanshu/practice/stacksmash
0804a000-0804b000 rw-p 00001000 08:06 528260     /home/himanshu/practice/stacksmash
0973a000-0975b000 rw-p 00000000 00:00 0          [heap]
b75af000-b75cb000 r-xp 00000000 08:06 787381     /lib/i386-linux-gnu/libgcc_s.so.1
b75cb000-b75cc000 r--p 0001b000 08:06 787381     /lib/i386-linux-gnu/libgcc_s.so.1
b75cc000-b75cd000 rw-p 0001c000 08:06 787381     /lib/i386-linux-gnu/libgcc_s.so.1
b75df000-b75e0000 rw-p 00000000 00:00 0
b75e0000-b7783000 r-xp 00000000 08:06 787152     /lib/i386-linux-gnu/libc-2.15.so
b7783000-b7784000 ---p 001a3000 08:06 787152     /lib/i386-linux-gnu/libc-2.15.so
b7784000-b7786000 r--p 001a3000 08:06 787152     /lib/i386-linux-gnu/libc-2.15.so
b7786000-b7787000 rw-p 001a5000 08:06 787152     /lib/i386-linux-gnu/libc-2.15.so
b7787000-b778a000 rw-p 00000000 00:00 0
b7799000-b779e000 rw-p 00000000 00:00 0
b779e000-b779f000 r-xp 00000000 00:00 0          [vdso]
b779f000-b77bf000 r-xp 00000000 08:06 794147     /lib/i386-linux-gnu/ld-2.15.so
b77bf000-b77c0000 r--p 0001f000 08:06 794147     /lib/i386-linux-gnu/ld-2.15.so
b77c0000-b77c1000 rw-p 00020000 08:06 794147     /lib/i386-linux-gnu/ld-2.15.so
bfaec000-bfb0d000 rw-p 00000000 00:00 0          [stack]
Aborted (core dumped)

Bylo to příjemné překvapení, že prováděcí prostředí bylo nějak schopno detekovat, že by v tomto případě mohlo dojít k přetečení vyrovnávací paměti. Ve výstupu můžete vidět, že bylo zjištěno rozbíjení zásobníku. To mě přimělo prozkoumat, jak bylo zjištěno přetečení vyrovnávací paměti.

Při hledání důvodu jsem narazil na příznak gcc ‚-fstack-protector‘. Zde je popis tohoto příznaku (z manuálové stránky):

-fstack-protector

Vysílejte další kód pro kontrolu přetečení vyrovnávací paměti, jako jsou útoky na rozbíjení zásobníku. To se provádí přidáním proměnné guard k funkcím se zranitelnými objekty. To zahrnuje funkce, které volají alloca, a funkce s vyrovnávacími pamětmi většími než 8 bajtů. Ochrany jsou inicializovány při vstupu do funkce a poté zkontrolovány při ukončení funkce. Pokud selže ochranná kontrola, vytiskne se chybová zpráva a program se ukončí.

POZNÁMKA:V Ubuntu 6.10 a novějších verzích je tato možnost ve výchozím nastavení povolena pro C, C++, ObjC, ObjC++, pokud není nalezen žádný z -fno-stack-protector, -nostdlib ani -ffreestanding.

Takže vidíte, že gcc má tento příznak, který vydává další kód pro kontrolu přetečení vyrovnávací paměti. Další otázka, která mě napadla, byla, že jsem tento příznak při kompilaci nikdy nezahrnul a jak se tato funkce povolila. Pak jsem si přečetl poslední dva řádky, které říkaly, že pro Ubuntu 6.10 je tato funkce ve výchozím nastavení povolena.

Poté jsem se jako další krok rozhodl tuto funkci deaktivovat použitím příznaku ‚-fno-stack-protector‘ při kompilaci a poté jsem se pokusil provést stejný případ použití, jaký jsem dělal dříve.

Zde je návod, jak jsem to udělal:

$ gcc -Wall -fno-stack-protector stacksmash.c -o stacksmash
$ ./stacksmash 

 Enter the name
TheGeekStuff

 len = [26214] 

 len of string entered is : [12]

Vidíme tedy, že jakmile byl kód zkompilován s tímto příznakem a poté se stejným vstupem, prováděcí prostředí nebylo schopno detekovat přetečení vyrovnávací paměti, ke kterému skutečně došlo, a poškodilo hodnotu proměnné ‚len‘.

Také, pokud s gcc začínáte, měli byste rozumět nejčastěji používaným možnostem kompilátoru gcc, o kterých jsme hovořili dříve.


Linux
  1. Jak nainstalovat WordPress s LAMP Stack na Ubuntu 16.04

  2. Jak nainstalovat Magento 2.4 s LEMP Stack na Ubuntu 20.04

  3. Zjistěte, jak zastavit útoky XML-RPC pomocí .htaccess

  1. Jak nainstalovat MERN Stack s Nginx na Debian 11

  2. Jak získat trasování zásobníku pro C++ pomocí gcc s informacemi o čísle řádku?

  3. jak nainstalovat gcc 4.9.2 na RHEL 7.4

  1. Jak nastavit RPATH a RUNPATH s GCC/LD?

  2. Jak podložit soubor pomocí FF pomocí dd?

  3. Jak grep ps výstup s hlavičkami