Jak může podtečení vyrovnávací paměti vést ke vzdálenému spuštění kódu na 64bitových bitech?

Mám následující souhrnný pseudokód v C89 z knihovny serveru ssh, který poskytuje pouze přístup k věcem jako git-shell (/bin/bash je nahrazen spuštěným programem, takže není možné dělat něco jiného) :

struct _raw_uncapped_ssh_string { // no limit on the size of the string; uint32_t len; char non_null_terminated_string[]; // by protocol design it have a minimum length of 1 }; typedef struct _raw_uncapped_ssh_string raw_ssh_string; union buffer { void * uncapped_zlib_decompressed_network_data; // yes, the size is uncapped, so it’s possible to put 4Gb of // data in it that would be copied later into memory. zlib // allow easily to turn some Mb in Gb of data, but it’s not // the point of the question. raw_ssh_string st; }; get_command (compressed_network_data) { size_t len; char * command; buffer string=uncompress_to_buffer(compressed_network_data); len=ntohl(string.st.len)+1; command=malloc(len+1); command[len]=0; // here’s the point, both the string length and content as // well it’s supplied size is controlled by the attacker. memcpy(command,string.st.data,len); return command; } 

Zde je jak je příkaz proveden později (řetězec command se nezmění po get_command()) .

const char *args[]={"/bin/bash",command,NULL}; // /bin/bash isn’t the shell, it has been replaced by git‑shell. // redirect the program output to the network. dup2(stdin, 0); dup2(stdout,1); dup2(stdout,2); close(stdin); close(stdout); //if this return execution failed and print an error message return execv(args[0],(char * const *)args); // I don’t know which is the system, so I can’t know about the libc behaviour. 

Nemohu dělat memcpy(command,string.st.data,0), protože třetí člen memcpy má minimální velikost 1 a v mém kontextu size_t používá 64bitové celé číslo, nemohu provést přetečení vyrovnávací paměti, protože existuje len.

Jediné, co mohu udělat, je nastavit len na hodnotu větší, než je hodnota přidělená string.st.data. Toto je podtečení vyrovnávací paměti, které mi umožňuje číst nepřidělenou paměť.
Dokážu přečíst paměť serveru, ale nevidím, jaká citlivá data může veřejný server ssh obsahovat (v mém případě seznam uživatelů, kteří může provádět ssh je veřejné) .

Stejně tak podtečení vyrovnávací paměti na memcpy umožňuje vzdálené provedení kódu?

Komentáře

  • Pokud kód skutečně funguje command[len] = 0 pak se jedná o přetečení vyrovnávací paměti, protože maximální index vyrovnávací paměti o délce len je len-1. Alternativně, pokud skutečný kód provede malloc(len+1) namísto malloc(len), můžete provést masivní přetečení vyrovnávací paměti nastavením len hodnota 0xFFFFFFFF.
  • @ThomasPornin: Ne, to je chyba z mé strany, ve skutečnosti to vyžaduje několik funkcí tento. Předpokládejme, že zbývající je pravda.
  • @ThomasPornin: Mluvím o 64 bitech, protože len je size_t, používá 64bitové celé číslo. Neexistuje tedy žádný způsob přetečení celého čísla.
  • @ThomasPornin Přidělují len+1, takže nastavení na 0 by mělo být platné.
  • @ RoraΖ: Mluvil o nastavení string.st.len na –1.

Odpověď

Obecně ne, podtečení vyrovnávací paměti nelze použít pro vzdálené spuštění kódu. Jelikož data řízená útočníkem nikdy neopustí prostor, který jim byl přidělen, nikdy nemají schopnost převzít průběh provádění programu.

Podtečení vyrovnávací paměti má potenciál pro jiné typy útoků, například zpřístupnění informací (pokud program počítá s vymazáním původního obsahu vyrovnávací paměti novými daty).

Komentáře

  • Nebo jako já viděl nedávno v git, později se změnil na přetečení vyrovnávací paměti.

Odpověď

Když jsem původně napsal tuto odpověď Zdá se, že jsem přečetl několik nedorozumění, která držíte. Tato nedorozumění by vám pravděpodobně zabránila porozumět mé odpovědi. Aby bylo jasné, tento text zvětším, abych zdůraznil, abych nebyl neúctivý:

Mnoho termínů, které používáte, neznamená to, co si myslíte, že znamenají.

Například:

  • „třetí člen memcpy neexistuje, protože memcpy je funkce, nikoli struct nebo union.
  • „Nemohu provést přetečení vyrovnávací paměti, protože tam je len a benzín mi nemůže dojít, protože tam je benzín. Prosím o Otázka? Zdá se mi to jako vhodná analogie, zejména proto, že teoreticky váš kód může vyvolat přetečení vyrovnávací paměti.
  • „Jediné, co můžu udělat, je nastavit len na hodnotu větší, než je hodnota přidělená string.st.data. Toto je podtečení vyrovnávací paměti … „ Ne, to není definice podtečení vyrovnávací paměti. K podtečení vyrovnávací paměti dochází, když přistupujete k mezím pole pomocí záporného indexu nebo indexu, který by způsobil aritmetické zalomení ukazatele může nastat. U některých konfigurací je to možné (dokonce i na „64bitových systémech“, ať už to znamená cokoli), ale pochybuji, že jste tím mysleli, když jste psali tato slova, protože jste je následovali s:
  • „… umožňující mi číst nepřidělenou paměť.“ Myslím, že jste možná mysleli „neinicializovanou paměť“. Aby bylo jasno, myslím, že jste chtěli říci, že vy „ve přidělil přebytek a ponechal přebytek neinicializovaný a možná s tím budete chtít něco udělat (viz calloc nebo memset).

Zvažme na chvíli char *fubar = NULL; … tento druh ukazatele má obecně nulu hodnota.Dereferencování je považováno za dereference nulového ukazatele , ale pokud napíšeme něco jako 0["hello"], dostaneme totéž jako "hello"[0] (to je "h"). Při útocích lze tedy použít dereference nulového ukazatele, když útočník ovládá výraz mezi hranatými závorkami (jako je tomu ve vaší situaci).

Vracíme se k fubar věc; řekněme memset(&fubar, UCHAR_MAX, sizeof fubar);, nyní fubar jsou všechny 1 bity, což znamená, že může být adresa to je největší adresa, které by náš systém mohl (teoreticky) vyhovět. Co když přistoupíme k fubar[1]? Jak můžete získat přístup k prvku za největší adresou? adresa se pak zabalí zpět? Technicky je to všechno nedefinované chování, ale kdybych měl pojmenovat to na běžné architektuře, bylo by to:

  1. Aritmetické přetečení ukazatel, vedoucí do …
  2. dereference nulového ukazatele a / nebo potenciálně podtečení vyrovnávací paměti .

Umožňuje podtečení vyrovnávací paměti na memcpy povolit vzdálené spuštění kódu?

Vyrovnávací paměť underflow může útočníkovi umožnit přepsat ukazatele funkcí umístěné v oblastech paměti před dotyčným polem. Pokud jsou tyto ukazatele funkcí vytvořeny tak, aby ukazovaly na shellcode, může tento shellcode být provedeny, když budou znovu vyvolány později.

V této poněkud nejasné části kódu se zdá, že existuje riziko podtečení vyrovnávací paměti, když má int širší doména než uint32_t, protože ntohl(string.st.len)+1 způsobí převod hodnoty uint32_t na int typ. Zvažte například, zda INT_MIN je -4294967296 (což je o méně než 0 - UINT32_MAX) a INT_MAX je 4294967295 … v podstatě by to byl 33bitový int s padding to pad out to the width of a byte; neobvyklé, ale možné. Za těchto okolností výraz ntohl(string.st.len)+1 není uint32_t v typu; je to int v typu a spíše než zalomení zpět na 0, když dojde k přetečení celého čísla bez znaménka , pravděpodobně se to zalomí na -4294967296 když dojde k přetečení celého čísla se znaménkem .

Pokud hledáte záruku proti podtečení vyrovnávací paměti , použijte U celočíselná doslovná přípona (tj. ntohl(string.st.len)+1U). Pak v této situaci „skončíte s tím, že výraz bude buď uint32_t nebo unsigned int (podle toho, který typ má největší doména).

Pokud se domníváte, že ntohl(string.st.len) může vrátit o jednu méně, než je maximální hodnota pro tento nepodepsaný typ (ať je jakýkoli), pak len=ntohl(string.st.len)+1 bude mít za následek maximální hodnotu, malloc(len+1) způsobí nepodepsané zabalení , takže nakonec vyvoláte malloc(0) a poté command[len]=0 zapíše dobře a skutečně za konec pole. Pak samozřejmě budete „mít také problém s memcpy(command,string.st.data,len); (jedná se o přetečení vyrovnávací paměti).

Podtečení vyrovnávací paměti a přetečení není jediným rizikem. Pokud don „t zkontrolujte návratovou hodnotu malloc a malloc vrací NULL pak lze použít dereference nulového ukazatele, která způsobí spuštění libovolného kódu. To znamená, že byste měli mít způsob komunikace malloc selhání zpět volajícímu. Z toho také vyplývá, že stejnou metodu můžete použít ke kontrole a sdělení problému s zabalením zpět volajícímu.

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *