(delsi) buffer overflow - prunik

Pavel Kankovsky peak na argo.troja.mff.cuni.cz
Pondělí Srpen 7 12:06:27 CEST 2000


On Sun, 6 Aug 2000, Jaroslav Gratz wrote:

> |----------------instrukční segment-------------------|
>                      |---------datový segment---------|
>                                   |---stack segment---|

Nikoli. Rika se tomu "flat model" a vypada to takto:

  |---------- code segment ------------|  (cs)
  |---------- data segment ------------|  (ds, es, ss)

na Linuxu je ds == ss, ted z hlavy nevim, jestli to plati i pro Win32,
ale asi ano. V kazdem pripade maji urcite vsechny segmenty stejny offset,
aby mohl program existenci segmentu srdecne ignorovat (protoze pak lze
ukazatele redukovat na offsety).

> Prostě v rámci jednoho procesu se segmenty překrývají a je možné
> beztrestně přepsat zásobník z datového segmentu a spustit kód na
> zásobníku.

Navratova adresa na zasobniku se asi bez vyjimky prepisuje pretecenim
nejake automaticke promenne, ktera je taky na zasobniku, a tudiz si
oddelenim stack seg. nepomuzete. Pomohlo by (pro tento partikularni druh 
problemu), kdyby byly dva zasobniky: jeden pro navratove instrukce a druhy
pro automaticky promenne a mozna i pro parametry (jestli jste mel TOHLE
na mysli, pak to nebylo moc jasne), ale vyzadovalo by to nestandardni
kejkle. A take by neslo prekladat s -fomit-frame-pointer, coz je na
intelech, ktere nemaji registru nazbyt, celkem dulezita optimalizace.

> Špatné řešení. Generovat za běhu programu dynamicky nějaký kód na zásobník
> a ten potom spouštět je nesystémové a nepřehledné. Zásobník potom musí být
> spustitelný se všemi důsledky, co z toho vyplývají. Když už měli vývojáři
> gcc potřebu použít dynamicky generovaný kód, měli to udělat jinde než na
> zásobníku.

Kod trampoliny ma zivotnost ekvivaletni automaticke promenne, proto dava
dost dobry smysl ho umistit na stejne misto jako automatickou promennou
...tj. na zasobnik.

> |-instrukční segment-|-----datový segment----|----stack segment----|
>                      |-datový segment pouze pro čtení (není nutný)-|
> 
> Parametry by se na zásobník předávaly tak jako doteď, buď
> push [promenna] nebo mov [ebp+n],reg. Čtení parametrů mov reg,[ebp+n].

Dejme tomu, ze mam kod:

  void f(char *a) { strcpy(a, "....neco hodne dlouheho..."); }
  void g(char a)  { f(&a); }

Zabranite prepsani navratove adresy? Pokud ano, jak to prelozite?

> To máte pravdu, tady by to nepomohlo. Ale přepsání zásobníku a
> překrývající se segmenty jsou mnohem nebezpečnější, protože dávají
> útočníkovi možnost spustit jeho vlastní kód.

Varianty 2 a 3 (ktere jste rafinovane vymazal) ano.

> Vzhledem k tomu, kolik existuje buffer overflow exploitů, se mi to zdá
> celkem důležité (ale to je pouze můj názor). A lidé jsou omylní a stále
> budou přibývat nové exploity.

Pochybuji, ze nejaky *exploit* nekdy vznikl omylem. :)
Nicmene Vami navrhovane reseni bude vzdycky polovicate. A polovicatych
(nikoli v hanlivem smyslu) reseni uz nekolik funkcnich mame: Openwall,
StackGuard, takze znovuvynalezate kolo.

--Pavel Kankovsky aka Peak  [ Boycott Microsoft--http://www.vcnet.com/bms ]
"Resistance is futile. Open your source code and prepare for assimilation."




Další informace o konferenci Linux