Új GnuTLS bug miatt sebezhető egy csomó nyílt forrású szoftver

 ( trey | 2014. június 4., szerda - 6:48 )

Egy új sebezhetőséget fedeztek fel a Linux disztribúciók által széles körben szállított GnuTLS crypto library-ben. A hiba technikai elemzése elolvasható itt. Patch már van, így érdemes mielőbb frissíteni. Részletek az Ars Technica cikkében.

Hozzászólás megjelenítési lehetőségek

A választott hozzászólás megjelenítési mód a „Beállítás” gombbal rögzíthető.

Miert nem irjak ezeket ujra olyan nyelvben, amelyet nem erint a puffertulcsordulas?

*grabs popcorn

--
arch,xubuntu,debian,windows,android

dev: http://goo.gl/7Us0GN
BCI news: http://goo.gl/fvFM9C

Például?
Lehetőleg olyat mondj, ami gépikódra fordul!

Google Go

Nem vagyok nagy enthusiast, de pont ilyesmire elképzeletőnek tartanám. Ráadásul gyorsan is fordul -> testing kényelmesebb. És még C kódot is könnyen hívhatsz belőle.

Vagy uljunk fel a hype-nak, es Swift (by Apple). :D

FYI: a go sem teljesen memory-safe, ha ket threadbol is lehet modositani egy kozos adatstrukturat, akkor ott bizony boven lehet memory corruption.

Ezt kifejtenéd bővebben?

Te most a versenyhelyzetről beszélsz, nem? Arra mindig is fogsz találni lehetőséget a jelenlegi nyelvekben.

Itt most inkább arról van szó (nagyon lebutítva a dolgot), hogy túlírhatsz-e, vagy méginkább: túlolvashatsz-e egy konténert (tömböt, etc.), vagy sem. A go legjobb tudomásom szerint erre nem ad lehetőséget (sem a java, sem a python, stb.)

C++ esetén a QVector, és az std::vector bár a többiek szerint megoldásnak tűnik, ott mindig is ott lesz a veszély hogy a túloptimalizáló programozók belenyúlnak a belső reprezentációt ismerve a tömbbe; de hát ez a nyelv ilyen, ad rá lehetőséget. Go pedig nem.

Update: Így van, az én értelmezésem nem egyedi, memory-safety-ről ilyen esetekben beszélünk. (http://en.wikipedia.org/wiki/Memory_safety) Amiről te beszélsz az a contention; egészen más szemantikai szint. (És talán nem is ide tartozik, mert tippem szerint ezek az ssl libek single-threadesek)

a szakmai nyelv pongyolasaga, de amikor 'memoriakorrupcio hiba'-t emlegetunk, akkor igazabol kicsit keverjuk a szezont a fazonnal. a memoriakorrupcio ugyanis nem egy hibakategoria, hanem egy lehetseges tunet. egy puffertulcsordulas (tomb tulindexelese) hibakategoria, de mivel a tipikus esetben ez memoriakorrupciora vezet, ezert pongyolan ugy szoktuk csak mondani, hogy memoriakorrupcios hiba. igy viszont mar talan ertheto eax hozzaszolasa, egy versenyhelyzet hibanak siman lehet memoriakorrupcio a tunete (pl. a nemreg publikalt CVE-2014-0196) es ha egy kornyezet (nyelv, futtatasi rendszer, stb) nem garantalja ezen hibak nemletet (hajra kettos tagadas ;), akkor bizony az nem szamit memory safe-nek. a huszaros megoldas az szokott lenni amugy, hogy a nyelv/rendszer nem tamogatja a tobbszalu vegrehajtast, az osztott memoria hasznalatat, signal-okat, stb es akkor 'eleg' a tobbi memoriakorrupciora vezeto hibakategoria eliminalasa.

PS: The GnuTLS library is thread safe by design

OK-OK értem én, csak azt akartam kiemelni, hogy - ha már véletlenül rosszul fogalmazott - akkor pont ez az a szituáció, amikor van értelme a megkülönböztetésnek, mert arról szól a beszélgetés, hogy vannak nyelvek, amik _ezt_ a fajta hibát (a puffertúlírást-olvasást, stb.) kijavítják, ugyanakkor a párhuzamosításból fakadó hiba szemantikailag magasabb, azt nyelv lehetőségeitől függetlenül el tudod érni.

Nem, amikor azt irom hogy nem memory-safe, akkor azt ugy ertem hogy nem memory-safe. Amit irsz, az igaz a memory-safe nyelvekre (pl. java), de a go-ra nem. Pl.:

test.go

eax@debian:~/go$ go build test.go 
eax@debian:~/go$ gdb ./test
(gdb) run
Starting program: /home/eax/go/test 
0xf840028228
[New LWP 5340]

Program received signal SIGSEGV, Segmentation fault.
[Switching to LWP 5340]
0x0000000000400e37 in main.main () at /home/eax/go/test.go:33
33          fmt.Println("boom: ", *m.data) 
(gdb) i r
rax            0x7ffff7f9ef00   140737353740032
rbx            0x4141414141414141       4702111234474983745
rcx            0xf840028270     1066225795696
rdx            0xf840028270     1066225795696
rsi            0x7ffff7f9ef08   140737353740040
rdi            0x7ffff7f9ef68   140737353740136
rbp            0xf840028220     0xf840028220
rsp            0x7ffff7f9eee0   0x7ffff7f9eee0
r8             0x4569b8 4549048
r9             0x47d8b8 4708536
r10            0x0      0
r11            0x470ba8 4656040
r12            0x47d7c8 4708296
r13            0x10     16
r14            0x0      0
r15            0x0      0
rip            0x400e37 0x400e37 
eflags         0x10206  [ PF IF RF ]
cs             0x33     51
ss             0x2b     43
ds             0x0      0
es             0x0      0
fs             0x0      0
gs             0x0      0
(gdb) x/i $rip
=> 0x400e37 :    mov    (%rbx),%rbp
(gdb) 

--
"You're NOT paranoid, we really are out to get you!"

Ha jól értem, a probléma az, hogy egy metódus két külön szálból meghívódik, és közben memóriát allokáció történik, és míg az egyik jól kiszámolja, hogy akkor
az 5. helyre kell írni, a másik átállítja a tömb méretét 3-ra.

Ez ellen mind a java, mind a c#, mind a python, és talán még a go is véd, ugyanis el fog szállni a kód egy megfelelő exception-nel, mert ott nem tudsz puffertúlcsordulást
csinálni. A c-ben ez nincs védve, gondolom egyszerűen azért, mert megbíznak a fejlesztőben, hogy tudja, mit csinál. Na, ez az, ami miatt folyamatosan puffer túlcsordulás
miatt kell parázni.

az altalad felsorolt nyelvek egyike sem tamogatja a C nyelvbol ismert puffer fogalmat (mivel nem tamogatnak pointereket ill. pointer aritmetikat) tehat puffer tulcsordulasrol eleve nehez beszelni. amit tamogatnak az egy array tipus (ami mas fogalom, mint a C array tipusa), es futasidoben ellenoriznek minden indexelest (cserebe lassulast okozva termeszetesen). de mindettol fuggetlenul a felsorolt nyelvekben is siman lehet versenyhelyzetet okozo kodot irni, es az asm szintu implementaciotol fuggoen ebbol lehet memoriakorrupciot is csinalni. pl. egy array parhuzamos novelese es irasa kozott verseny van (l. a hivatkozott CVE-t), ha a nyelv/runtime maga nem szinkronizalja ezeket korrektul, akkor gaz van, ha meg igen, akkor meg lassu az egesz (python-nal eleve ott a GIL ugye).

Hú, most elgondolkodtattál... Azt találtam, hogy nem igaz az az állítás, hogy java-ban nincsenek pointerek támogatva, mert számomra is most derült ki, hogy
mégiscsak van, igaz, hogy misc-ben, de van.

Itt van a javadoc:

http://j7a.ru/classsun_1_1misc_1_1_unsafe.html

És egy teljesítményteszt, ami összehasonlítja a heap vs bytebuffer vs direct részt:

http://www.javacodegeeks.com/2013/08/which-memory-is-faster-heap-or-bytebuffer-or-direct.html

Namost, a direct bytebuffer is tartalmaz range check-et, és érdekes, hogy írásnál ez nem is jelent sebességkülönbséget!!!, csak olvasásnál...

Ez nekem igencsak jónak tűnik, és innentől kezdve jórészt indokolatlannak érzem azt a fajta félelmet, hogy majd az indexelés az lassítani fog.

Viszont, van egy érdekes ötletem... mi van, ha csinálok egy olyan kódot, ami az unsafe-et használja, tudok-e crasheltetni.. és igen, lehet:

import sun.misc.Unsafe;
import java.lang.reflect.Field;

public class CrashTest {

private static Unsafe unsafe;
static {
try {
Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
unsafe = (Unsafe) field.get(null);
} catch (Exception e) {
}
}

public static void main(String[] args) {
long pointer = unsafe.allocateMemory(4);

unsafe.putInt(pointer, 0);

System.out.println(unsafe.getInt(pointer));

System.out.println("Now here comes the crash");

for (long ptr = pointer; ptr < pointer + 500*10000000; ptr = ptr + 4){
unsafe.putInt(ptr, 1);
}

System.out.println(unsafe.getInt(pointer));

unsafe.freeMemory(pointer);
}

}

.NET natív kódra fordul (második körben). Természetesen nem a beépített SSL támogatásra gondolok, az Microsoftos natív kódba hív át, és abban ugyancsak lehetnek még felfedezésre váró hibák.

Persze nem lesz akkora a throughputja, mintha nyers C-ben írták volna, de valamit valamiért. Amíg a fejlesztők optimalizálás néven pont akkora puffereket allokálnak, ami szerintük kell, meg direkt a lehető legkisebb integer adattípusokat használják, addig lesznek ilyen hibák.

--

http://www.mitls.org/ + .net full aot (mono is tud ilyet).

Es keszul az ocaml (+?coq) tls implementacio is.

"Examples of such languages include Ada, Eiffel, Lisp, Modula-2, Smalltalk, OCaml and such C-derivatives as Cyclone, Rust and D. The Java and .NET Framework bytecode environments also require bounds checking on all arrays."

Mondjuk Rust-ban, de a nyelv teljesen mindegy. Csak ne legyen lukas, mert az nem.

szerk:
forras:en.wikipedia.org/wiki/Buffer_overflow
licensz: Creative Commons Attribution-ShareAlike License (WTF?)
+rohadjon meg minden olyan kezdemenyezes amely a felhasznalok szellemi tulajdonat copyrightolja sajatkent. Viva la CC0!

Ezek közül melyik nem interpretált? A Lisp tudtommal az, az Eiffelről is úgy rémlik, bár biztos nem vagyok benne, az Ada elég régi, talán az lehet egy opció, a többiről semmit sem tudok. Viszont attól tartok, hogy a többiek nem is elég elterjedtek ahhoz, hogy olyan helyen használják őket, ahol fontos lenne a biztonság.
De ez utóbbi csak a privát véleményem.

"A Lisp tudtommal interpretált."

Igazad is van, meg nem is. Elvileg az implementálás módja független a nyelvtől magától, a Lisp pedig pont az a nyelv, amelyikre ez gyakorlatilag is nagyon igaz. Tehát a Lisp lehet interpretált, compiled, everything in between, vagy ezek mind egyszerre (ahogy Schrödinger macskája is egyszerre halott és él).

Ma SPARK-ot kell használni: http://en.wikipedia.org/wiki/SPARK_(programming_language)

Akár C++-ban is lehetne memória-biztonságosan programozni, ha csak értékhatár-ellenőrzött container-eket használsz, és (referenciaszámlált (std::shared_ptr) vagy törléskor 0-zódó (QPointer)) smart pointereket használsz, nem?

A C++-ról addig hittem, hogy értek hozzá valamennyire, míg rá nem jöttem, hogy csak nevében emlékeztet a C-re. (magyarán fogalmam sincs ;) )

extern "C" {} :)

--

C++-ban sokféleképp lehet programozni, akár ugyanúgy is, mint C-ben, csak beépített tömb helyett vmi vector-féle containerrel, mutatók helyett meg smart pointerekkel.

De úgy az már nem is olyan, mint C-ben, mert ott nincs heavy weight std::vector, meg 8 féle smart pointer + 2-3 féle referencia. Sőt ezekkel már bejön a "kedvenc" C++ feature, a

}

amiről senki sem tudja, hogy mit csinál.

Hogy micsoda?!

Szerintem a RAII-ra/destruktorra gondol esetleg retval optimizációra, vagy kitudja mire, én is kíváncsi vagyok :-)

Ezek szerint nem olvastok elég C++ fanboy irodalmat. Egyik jól ismert kedvenc egysoros C++ kód a fenti, ami azt csinálja, hogy sutyiban meghív függvényeket.

ah, át van #define-olva? :-)

Nincs igazad, pont _elég_ c++ fanboy irodalmat olvasok :-)

Részvétem :)

Ja, a pont elég az a 0-ra vonatkozott :-)

Nem #define, a sutyiban meghívott függvény a destruktorokat jelenti.

persze hogy nem, }-t nem tudod átdefiniálni

na dehát a desktruktort írtam én is, akkor az nem volt jó megoldás? :-)

"esetleg retval optimizációra, vagy kitudja mire, én is kíváncsi vagyok :-)"

"Szerintem a RAII-ra/destruktorra gondol"

Szerintem csak a preprocesszort futtatja.

LOL :D :D :D

Milyen sutyiban meghívott destruktorok?
Pont azt várom a } -tól, hogy hívja meg a destruktorokat, eleve azért írom le, nincs itt semmi sutyi.

puff

Vagy legalább a crypto cuccokat auditáltatnák alaposan a nagy cégek.

Bár vannak próbálkozások azt nem értem miért nem lehet a fordító szintjén megoldani ezt a problémát, azzal hogy megvédik a stack-et és a heap-et a puffer túlcsordulástól. Természetesen ha a program szarul van megírva, és mindenféle pointereket castolgatnak össze vissza, vagy függvénypointereket használnak, az ellen nem védene, de nagy részt jó lenne. De ahogy látom a meglévő védelmeket sem használják pl.:
http://en.wikipedia.org/wiki/Buffer_overflow_protection

Dinamikus memóriafoglalásnál, ahol is a lefoglalt memória mérete és a címzés futásidőben derül ki, mit akarsz a fordító szintjén megoldani?
Statikus memóriafoglalásnál még csak-csak meg lehet ezt csinálni, de dinamikusnál nem. Ahhoz a runtime támogatása kell.

clang & gcc ASAN.

---
pontscho / fresh!mindworkz

Igen, es itt is runtime tamogatas kell hozza.
Malloc replacement van sokfele, a Boehm GC is kepes erre.

Nyilvan nem uszhato meg, es mint irjak is, a varhato atlagsebesseg a fele lesz igy, de mar van compiler szintu megoldas a kerdesre, raadasul ez _nem_ csak egy malloc alternativa. Van olyan eset amikor ez vallalhato kompromisszum.

---
pontscho / fresh!mindworkz

Ha nincs ilyen lehetoseg a programozasi nyelvben, a problema meg is van oldva. Praktikus dolog tud lenni a GC.
A "garancia" minosege sem mindegy: nehany teszt elvegzese nem teljesen ugyanaz, mint a teljes garancia a mukodesre (foleg bizonyithatoan).

Lehetne ha olyan kontenereket hasznalnanak miben van run-time ellenorzes. En pl Qt alatt .at() metodust hasznalom azert hogy kideruljon barmilyen problema. Gondolom ok eloterbe helyeztek a sebesseget inkabb.

Egyszer kiváncsi lennék, hogy valójában mekkora teljesítménynövekedést jelentenek a teljes könyvtár sebessége tekintetében? Mert hogy egy függvény 5msec-cel gyorsabb, az önmagában nem jelent semmit.

foleg, hogy 99%-ban halozaton hasznaljak :)

--
NetBSD - Simplicity is prerequisite for reliability

az szep, viszont abban az 5ms-ben nem nop van, hanem dolgozik a gep, aztan hiaba halozat/nem halozat:)


// Happy debugging, suckers
#define true (rand() > 10)

jah egy 50-200ms-es kesleltetesu unezetnel biztos nagyon sokat szamit :))

amugy meg mit er a gyors titkositas, ha nem is igazabol titkos?

--
NetBSD - Simplicity is prerequisite for reliability

Sokat, mert egy 5msec-es fvg eseteben egy oda vissza valasz (pl adatbazis szerver) es mindjart csak 100req/sec a maximalis atvitel, ugy hogy semmi mast nem csinaltal meg. Egy nagyon surun hasznalt fgv eseteben a vegere tobb 10x gyorsulast is tapasztalhatsz csak mert megsporoltal egyetlen egy step-et processzor szinten


// Happy debugging, suckers
#define true (rand() > 10)

Ez elméletileg igaz is, a kérdés az, hogy valójában valaki csinált-e teljesítménymérést azzal kapcsolatban, hogy az ADOTT esetben mennyivel hasznosabb a trükközés, mintha a biztonságra törekedtek volna...

Nem új az, csak most találtak rá :-P

Mennyire nem uj? Mert debianban meg 2.x a gnutls.

Ki a büdös franc használ GnuTLS-t egyébként... meg is érdemli.

--
GPLv3-as hozzászólás.

Mondjuk az, akinek olyasmi kell, amit pl. az OpenSSL nem tud: http://en.wikipedia.org/wiki/Comparison_of_TLS_implementations

És aki meg OpenSSL-t használ, az meg ezt érdemli meg...:
http://hup.hu/node/133043?comments_per_page=9999

Lehet, hogy az OpenSSL nem azért "Open", mert a source az, hanem azért, mert a használatával védett adatok...?

Nem kell nagy látnoknak lenni ahhoz, hogy kijelenthessük, még több hibát fognak benne felfedezni. Hiszen célzottan keresni kezdték/kezdik.

--
trey @ gépház

Több szem célzottan valóban többet lát :-P

Több szem többet lát. Nagy volt a hírverés körülötte, a vendorok és szolgáltatók is beszartak (hiszen őket is érintette), ebből kifolyólag a ZDI és társai fokozottabb örömmel vásárolnak OpenSSL exploitokat és sebezhetőségleírásokat (majd mi jól megvédünk titeket alapon). Mivel nagyobb a kereslet, az erre szakosodott hibakeresők is nagyobb kedvvel, elánnal esnek neki a kód auditálásának. Ebből, és az általam korábban linkelt dologból fakadóan várható, hogy egy csomó OpenSSL biztonsági figyelmeztető fog napvilágot látni.

Ez egy öngerjesztő folyamat. Nincs itt semmi szokatlan látnivaló.

--
trey @ gépház