Unele verificari ale limitelor sunt eliminate de compilatorul Apple si, eventual, altele, ducand la un posibil atac in special in versiunile de 32 de biti.

Desi declansat de o optimizare a compilatorului, acesta este un bug in Cap’n Proto, nu in compilator.

Kenton Varda <[email protected]> <[email protected]>

2017-04-17

CVE-2017-7892

  • Segfault de la distanta o aplicatie pe 32 de biti trimitandu-i un mesaj rau intentionat.
  • Exfiltrarea memoriei din astfel de aplicatii ar putea fi posibila, dar analiza noastra actuala indica faptul ca alte verificari ar cauza esecul oricarei astfel de incercari (vezi mai jos).
  • In prezent, am reprodus problema doar pe Mac OS folosind compilatorul Apple. Alti compilatori si platforme nu par sa aplice optimizarea problematica.
  • git commit 52bc956459a5e83d7c31be95763ff6399e064ae4
  • versiunea 0.5.3.1:
    • Unix: https://capnproto.org/capnproto-c++-0.5.3.1.tar.gz
    • Windows: https://capnproto.org/capnproto-c++-win32-0.5.3.1.zip
  • lansare 0.6 (viitor)

Urmatorul text contine speculatii despre exploatabilitatea acestei erori. Acest lucru este furnizat in scopuri informative, dar, deoarece aceste speculatii sunt deseori dovedite a fi gresite, nu trebuie sa va bazati pe acuratetea acestei sectiuni pentru siguranta serviciului dvs. Va rugam sa va actualizati biblioteca.

In timpul testarii periodice in pregatirea pentru lansare, s-a descoperit ca atunci cand Cap’n Proto este construit folosind versiunea actuala a compilatorului Apple Clang in modul pe 32 de biti cu optimizari activate, este vulnerabil la atac prin intrari malitioase special create, provocand aplicatia sa citeasca dintr-o locatie de memorie nevalida si sa se blocheze.

Mai exact, un mesaj rau intentionat ar putea contine un indicator indepartat indreptat in afara mesajului. Mesajele Cap’n Proto sunt impartite in segmente de memorie continua. Un indicator lung indreapta de la un segment la altul, indicand atat numarul segmentului, cat si un offset in cadrul acelui segment. Daca un indicator pozitiv rau intentionat continea un offset suficient de mare pentru a revarsa aritmetica indicatorului (infasurandu-se pana la inceputul memoriei), atunci ar scapa de verificarea limitelor, in parte deoarece compilatorul ar elimina jumatate din verificarea limitelor ca optimizare.

Adica, codul arata ca (simplificare):

cuvant * target = segmentStart + farPointer.

porno india maduras sensuales
largeporntube porno español trios
incestoxxx porno español abuelas
coños ricos abuelas por el culo
follando en el trastero maduras gozando
peleas xxx masajes porno en español
pollas peludas porno españolas peludas
inciesto español española viciosa
porno loco peliculas porno subtituladas en español
porno gay primera vez creampie española
chicas haciendo el amor videos porno corridas internas
pornoamater incesto abuelas
viejas tetonas alexa grace
pornox porno traducido al español
porno del bueno maduras gordibuenas
vecinas cachondas megan montaner follando
revistas xxx taboo.com
zoofilia con cabras chica se masturba
vieja gorda follando videos chicas gratis
maduras españolas masturbandose parejitas españolas follando

offset; if (target <segmentStart || target> = segmentEnd) {throwBoundsError (); } faceCeva (* tinta);

Pentru majoritatea observatorilor, acest cod pare a fi corect. Cu toate acestea, dupa cum se dovedeste, aritmetica indicatorului care depaseste este un comportament nedefinit in conformitate cu standardul C. Ca rezultat, compilatorului i se permite sa presupuna ca adaugarea pe prima linie nu se revarsa niciodata. Deoarece farPointer.offset este un numar nesemnat, compilatorul este capabil sa concluzioneze ca target <segmentStart evalueaza intotdeauna fals. Astfel, compilatorul elimina aceasta parte a verificarii. Din pacate, in cazul depasirii, aceasta este exact partea de verificare de care avem nevoie.

Pe baza atat a testarii fuzz, cat si a analizei logice, cred ca verificarea limitelor indicatorului indepartat este singura verificare afectata de aceasta optimizare. Daca este adevarat, atunci nu este posibila exfiltrarea memoriei prin aceasta vulnerabilitate: tinta unui indicator indepartat este intotdeauna de asteptat sa fie un alt indicator, care, la randul sau, indica obiectul final. Cel de-al doilea indicator va trece prin propria sa verificare a limitelor, care va esua (cu exceptia cazului in care se intampla cumva sa indice inapoi in limitele mesajului, caz in care nu se face rau).

Cred ca aceasta eroare nu afecteaza nicio platforma comuna pe 64 de biti, deoarece offsetul maxim exprimabil de un pointer indepartat este de 2 ^ 32 octeti. Pentru a declansa eroarea intr-un spatiu de adrese pe 64 de biti, locatia mesajului ar trebui sa inceapa cu 0xFFFFFFFF (alocata in cele mai mari 4 GB de spatiu de adrese), iar tinta ar trebui sa inceapa cu 0x00000000 (alocate in cele mai mici 4 GB de adresa spatiu). De obicei, pe arhitecturi pe 64 de biti, jumatatea superioara a spatiului de adrese este rezervata pentru nucleul sistemului de operare, astfel un mesaj nu ar putea fi localizat acolo.

Nu am reusit sa reproduc acest bug pe alte platforme, poate pentru ca optimizarea compilatorului nu este aplicata de alte compilatoare. Pe Linux, am testat GCC 4.9, 5.4 si 6.3, precum si Clang 3.6, 3.8 si 4.0. Niciunul nu a fost afectat. Cu toate acestea, comportamentul compilatorului este permis din punct de vedere tehnic, deci trebuie presupus ca se poate intampla si pe alte platforme.

Versiunea specifica a compilatorului care a fost observata a fi afectata este:

$ clang ++ – versiunea Apple LLVM versiunea 8.1.0 (clang-802.0.41) Tinta: x86_64-apple-darwin16.5.0 Modelul firului: posix InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/ usr / bin

(Nota: In ciuda faptului ca se bazeaza pe Clang, numerele versiunii compilatorului Apple nu au nicio relatie aparenta cu numerele versiunii Clang.)

Problema a fost surprinsa prin rularea testelor fuzz standard ale Cap’n Proto in aceasta configuratie. Aceste teste fac parte din suita de testare Cap’n Proto, care ruleaza atunci cand invocati verificarea, pe care instructiunile de instalare Cap’n Proto le sugereaza tuturor utilizatorilor.

Cu toate acestea, aceste teste fuzz au fost introduse dupa ramura de lansare 0.5.x, prin urmare nu sunt prezente in prezent in versiunile de lansare ale Cap’n Proto, doar in git. O versiune 0.6 va veni in curand, remediind acest lucru.

Comitetul de remediere a erorilor forteaza compilatorul sa efectueze toate verificarile aruncand indicatorii relevanti in uintptr_t. Conform standardului, numerele intregi nesemnate implementeaza aritmetica modulo, mai degraba decat lasand nedefinit overflow-ul, astfel compilatorul nu poate face ipotezele care conduc la eliminarea verificarii. S-a demonstrat ca aceasta schimbare rezolva problema in practica. Cu toate acestea, aceasta solutie rapida nu evita din punct de vedere tehnic un comportament nedefinit, deoarece codul inca calculeaza indicii care indica locatii nevalide inainte de a fi verificate. O solutie corecta din punct de vedere tehnic a fost implementata in urmatorul commit, 2ca8e41140ebc618b8fb314b393b0a507568cf21. Cu toate acestea, intrucat acest lucru a necesitat refacere mai extinsa, nu este adecvat pentru culegerea cireselor si va ateriza numai in versiunile 0.6 si in sus.