image

"Check compiler whether correct deal with sizeof operator"

zondag 12 februari 2006, 00:11 door patrickr, 10 reacties

Eentje in het Nederlands dan; Tijdens het doorspitten van de full disclosure archives (altijd fun) viel deze posting op. Zo ver ik het volg komt het er op neer dat sommige compilers (BCB6+ent_upd4 en tcc-0.9.23 confirmed) onverwacht gedrag vertonen. De onderstaande code print 'tsja' indien gecompileerd met een 'vulnerable' compiler:

int main (int argc, char ** argv) {
int i = -1;
if(i return 0;
}

Dit is (in mijn ogen) onverwacht gedrag omdat ik zou verwachten dat de (signed) integer 'i' gepromote wordt naar een unsigned int (dit omdat de sizeof normaal gesproken een unsigned return value heeft) en dan dus niet meer 'kleiner' is dan sizeof(int). De impact van dit onverwachte gedrag verschilt natuurlijk van applicatie tot applicatie.

Maar het punt is dat je een ultra-secure-evil-hacker-proof stuk C gecode kan hebben maar nog steeds 'onveilig' kan zijn als je compiler of interpreter 'lek' is. Moeten we nu allemaal aan de ida en bin-navi, gaan we er vanuit dat dit soort fouten niet veel voorkomen of gaan we allemaal compilers auditen?

Reacties (10)
12-02-2006, 01:54 door hzlz
compilers auditten lijkt me een logische stap in het produceren van nog
veiligere programma's
12-02-2006, 10:49 door Anoniem
gewoon niet doen, signed en unsigned met elkaar vergelijken.
dat is vragen om problemen
12-02-2006, 11:10 door Anoniem
kan iemand een voorbeeld geven dat in de echte wereld voor problemen
zou kunnen zorgen? ik kan zo snel niet iets bedenken... vrij vergezocht lijkt
me.
12-02-2006, 13:09 door Skizmo
waarom wordt een -1 ongevraagd gecast naar 0xffff ??
12-02-2006, 13:29 door Anoniem
Waarom zou je in godsnaam compilers gaan auditten? Je kan
toch het verwachte gedrag van de compileroutput simpelweg
testen? Auditten van compilers op security bugs is next too
nutteloos. Gebruik gewoon de ANSI C compatible test suite of
de andere standaard specificaties die er voor de
desbetreffende programmeer taal staan.

@Anoniem: In sommige gevallen ja, in de example code boeit
het geen reet of het een signed of unsigned int is. Die int
heeft nog steeds dezelfde grootte in bytes in het geheugen.
12-02-2006, 14:59 door Anoniem
@Anoniem:11:10

Als een sizeof() een waarde die te groot is rapporteert heb
je enorm veel kans op bounds checks die verkeerd gaan. Als
erachter interessante data ligt (saved instruction pointer,
saved frame pointer, of gewoon een variabele waarmee je
execution flow toch kan aanpassen) kun je veel dingen kapot
maken.

Zo vergezocht is het niet. Helemaal niet eigenlijk.
12-02-2006, 16:03 door Anoniem
beetje compiler waarschuwt toch voor zulke (domme) acties?
12-02-2006, 16:09 door G-Force
compiler en interpreter lek is ook vragen om problemen.
12-02-2006, 17:33 door Bitwiper
Door Jolt Oops op zondag 12 februari 2006 00:11
> Dit is (in mijn ogen) onverwacht gedrag omdat ik
> zou verwachten dat de (signed) integer 'i'
> gepromote wordt naar een unsigned int

gepromote? Je bedoelt dat 0xFFFFFFFF in het geheugen
ineens niet als -1 maar als +4294967295 zou moeten worden
gelezen, en dat dan wel verwacht gedrag en geen
(security) fouten zou opleveren?

Wel hebben alert7 (de FD poster) en jij gelijk dat Borland
zich niet aan haar eigen handleiding houdt. Je hebt echter
geen IDA nodig, gewoon een breakpoint zetten en een CPU
window openen werkt ook:
Unit1.cpp.9: int i = -1;
0040116C C745FCFFFFFFFF mov [ebp-0x04],0xffffffff
Unit1.cpp.10: if(i < sizeof(int)) printf("tsja!n);
00401173 837DFC04 cmp dword ptr [ebp-0x04],0x04
00401177 7D0B jnl +0x0b
00401179 68A4204000 push 0x004020a4
0040117E E87D010000 call CC3260._printf
dus een signed conditional jump (die niet genomen wordt
omdat -1 kleiner is dan 4).

Uit de online manual:
The fundamental types
...
Standard arithmetic conversions

When you use an arithmetic expression, such as a + b, where
a and b are different arithmetic types, C++Builder performs
certain internal conversions before the expression is
evaluated. These standard conversions include promotions of
"lower" types to "higher" types in the interests of accuracy
and consistency.
...
7. Otherwise, if either operand is of type unsigned, then
the other operand is converted to unsigned.

Vertrouwen op een dergelijke conversie is m.i. fundamenteel
fout (maakt niet uit welke kant op), doodeenvoudig omdat er
slechts voor de helft van alle mogelijke getallen een
overlap is tussen beide types; unsigned is dus helemaal geen
"higher" type dan signed. Normaal gesproken levert dit dan
ook een warning op: "W8012 Comparing signed and unsigned
values" (maar van mij had dit een foutmelding mogen zijn).

Het grootste probleem van deze compiler bug ("vergeten" dat
sizeof() unsigned teruggeeft) is m.i. niet het op
onverwachte wijze evalueren van de expressie, maar het feit
dat de programmeur er niet d.m.v. een warning op gewezen
wordt dat hij een fout gemaakt heeft.

De kans op security fouten door deze compiler bug is denk ik
klein; sizeof wordt meestal gebruikt om de grootte van
structs te bepalen en daarbij zal het meestal om unsigned
vergelijkingen gaan.

> Maar het punt is dat je een ultra-secure-evil-hacker-
> proof stuk C gecode kan hebben maar nog steeds
> 'onveilig' kan zijn als je compiler of interpreter 'lek' is.

Ja, maar ik maak me meer zorgen over libraries.

Erik van Straten
13-02-2006, 18:55 door Anoniem
> De kans op security fouten door deze compiler bug is denk ik
> klein; sizeof wordt meestal gebruikt om de grootte van
> structs te bepalen en daarbij zal het meestal om unsigned
> vergelijkingen gaan.

Hahaha, daar zit je erg fout. De kans is behoorlijk groot.
Er is superveel code die vulnerable is voor dergelijke bugs.
Het enige wat daartegen pleit is het feit dat mensen
voornamelijk gcc, en icc (intel compiler suite) gebruiken
en die vertonen dit gedrag afaik niet. Zo moeilijk is het
ook niet om een compiler te bouwen die aan specs voldoet.
Reageren

Deze posting is gelocked. Reageren is niet meer mogelijk.