Mihai BUDIU - budiu@cs.cornell.edu
http://www.cs.cornell.edu/Info/People/budiu/budiu.html
18 martie 1997
Ken Thomson este unul dintre numele cele mai mari din istoria calculatoarelor. Sau, dacă asta poate fi contestat, este cu siguranţă unul dintre numele cele mai faimoase. Ken Thomson lucrează la laboratoarele Bell, care au aparţinut firmei AT&T. (Laboratoarele Bell au fost sediul cercetării gigantului telecomunicaţiilor; multe dintre descoperirile revoluţionare ale secolului au fost făcute aici. O lista ne-exhaustivă trebuie să cuprindă: sateliţii de telecomunicaţii, bateriile solare, tranzistorul, laser-ul, sistemul de operare Unix şi limbajul C++. La ora actuală AT&T a fost spartă în bucăţi de legea americană anti-trust, aşa că o parte însemnată a laboratoarelor Bell a devenit o firmă independentă numită Lucent Technologies).
Ken Thomson este practic inventatorul Unix-ului. (Am scris un articol ceva mai detaliat in BYTE din August 1996 despre istoria acestui faimos sistem de operare). Acest sistem a revoluţionat în multe privinţe sistemele de calcul, iar influenţele sale se dovedesc fructuoase şi în ziua de azi. Pentru această realizare lui Thomson i-a fost decernat în 1984 premiul Turing al ACM (Association for Computing Machinery), care pentru lumea calculatoarelor este echivalent cu un Nobel.
În cuvîntarea ţinută cu prilejul decernării premiului, Thomson a dezvăluit cea mai mare fraudă informatică, al cărei autor este el însuşi. Textul comunicării este ``Reflections on Trusting Trust'', adică ``Reflecţii asupra încrederii în încredere''. Problema centrală care pe care Thomson o pune este dacă putem avea încredere în programele pe care le folosim, şi cum putem dobîndi încredere în ele. Expunerea lui arată că posibilitatea de a citi programele nu este o garanţie suficientă pentru a ne asigura de corectitudinea lor!
O mulţime de bani se investesc în ziua de azi în cercetări legate de această întrebare. Fericiţi sunt cei care nu au avut niciodată de suferit de pe urma viruşilor. În ziua de azi programele devin din ce în ce mai mobile (de exemplu applet-urile sunt programe transferate prin reţea în momentul cînd clientul de web accesează un document) şi Internetul este calul de bătaie al marilor firme, care au înţeles că o mulţime de bani se pot obţine prin servicii oferite prin reţea. Întrebările lui Thomson sunt cu atît mai acute din această cauză, iar răspunsuri pe deplin satisfăcătoare sunt departe de a fi date.
Thomson sesiza însă gravitatea acestor probleme acum 20 de ani, cînd calculatoarele erau departe de a fi atît de răspîndite. Iată povestea lui:
Thomson este, după cum am spus, autorul sistemului de operare Unix. Sistemul Unix este conceput pentru calculatoare care sunt folosite de mai mulţi utilizatori simultan, şi din cauza aceasta adresează de la bun început destul de serios problema securităţii. Unix-ul încearcă să izoleze procesele care se execută pe o aceeaşi maşină între ele, ca să nu se poată incomoda. (Un proces este un program care a fost pornit in execuţie, deci un obiect activ). În Unix programele care sunt executate de un acelaşi utilizator au oarecari posibilităţi lărgite de a se influenţa reciproc; de exemplu un proces al meu poate omorîpe un altul care-mi aparţine, dar nu poate omorînici unul din procesele care nu a fost create de mine. (Mai precis, poate trimite semnale, care uneori pot cauza moartea; moartea unui proces este încetarea execuţiei sale).
Pentru a putea decide ce drepturi au procesele, ele trebuie să fie asociate cumva utilizatorilor. Asocierea aceasta este realizată în Unix de programul /bin/login.
(În cele ce urmează vom simplifica discuţia pentru a pune în valoare doar detaliile care ne interesează; în realitate lucrurile sunt puţin mai complicate. Poate vom consacra cîndva un articol special securităţii în sistemele Unix.)
Programul login face legătura dintre un utilizator şi procesele sale; acest program autentifică un utilizator testînd cunoaşterea unui secret. Această verificare se face cînd utilizatorul se aşează prima oară în faţa calculatorului (face ``login''), o singură dată, şi efectele ei sunt vizibile pînă cînd utilizatorul părăseşte terminalul în mod explicit (face ``logout''). Toate comenzile lansate de la acest terminal între cele două evenimente sunt implicit ale utilizatorului care a fost autentificat. (Dacă utilizatorul părăseşte terminalul pentru o pauză de cafea şi altcineva îl foloseşte în răstimp, calculatorul nu are nici o metodă de a verifica acest lucru, şi ia comenzile ca fiind executate de persoana care a fost ultima autentificată. Calculatorul nu are la ora actuală nici o metodă de a ``simţi'' lumea exterioară, pentru a observa că utilizatorul este altul.)
Lucrurile funcţionează cam aşa:
uid=813(budiu) gid=5(users)
budiu:PGffJFh3BfCAw:831:5:Mihai Budiu:/home/budiu:/bin/bash
Cîmpurile sunt separate cu semnul ``:''. Primul este numele meu de utilizator asociat, al doilea este parola mea criptată, al treilea este numărul (uid) asociat mie; celelalte nu ne interesează prea tare în acest articol, dar pentru curioşi sunt: numărul grupului din care fac parte, numele meu real, directorul meu casă şi programul cu care conversez eu în mod normal (``shell''-ul meu).
Discuţia se poate dovedi pe alocuri confuză pentru că acelaşi cuvînt se foloseşte simultan pentru a desemna mai multe lucruri; de pildă ``login'' înseamnă:
Din schema asta complexă trebuie reţinut un lucru destul de simplu: toate procesele mele moştenesc de la /bin/login uid-ul meu; /bin/login este singurul program care mă identifică.
De acest lucru s-a folosit Thomson pentru a crea o intrare universală (o ``uşa din spate neştiută de nimeni'': a ``back door''): Thomson a scris programul /bin/login în aşa fel încît dacă cineva tastează numele lui şi o parolă fixată să fie acceptat în sistem chiar dacă nu are dreptul (adică chiar dacă în /etc/passwd nu există nici o linie pentru Thomson!). În felul acesta Thomson poate avea acces neîngrădit la orice sistem Unix din lume.
Lumea şi-a exprimat dintotdeauna temerile cu privire la programe cumpărate pe de-a gata: ele sunt întotdeauna susceptibile să conţină asemenea portiţe care îi dau fabricantului tot felul de privilegii din momentul în care programele ajung să se execute. Nu ne vom lansa în consideraţii etice aici, mai bine să urmărim mai departe subterfugiile lui Thomson, care nu se opresc aici!
Thomson este gata să pună la dispoziţia celor sperioşi sursele C ale programului /bin/login, pe care aceştia să le poată inspecta. Programul în principiu trebuie să fie destul de simplu ceva de genul (scris în pseudo-C):
while (1) { scrie("login: "); nume = citeste(); scrie("Password: "); parola = citeste(); criptata = cripteaza(parola); parola_corecta = cauta_parola("/etc/passwd", nume); if (egale(criptata, parola_corecta)) { uid = cauta_uid("/etc/passwd", nume); shell = cauta_shell("/etc/passwd", nume); executa(shell); } }
Dar dacă sursele sunt vizibile, oricine poate depista porţiunea în care în funcţie de o comparaţie cu numele lui Thomson se ia o decizie specială.
Probabil testul arată cam aşa:
usa_din_spate() { if (egale(nume, "Thomson") && egale(parola, "secret")) executa("/bin/sh"); }
Testul poate fi invocat inserînd o linie care cheamă funcţia usa_din_spate() în locul unde am lăsat o linie albă în sursele lui login.
Thomson a scos acest test din sursele programului /bin/login, dar a modificat compilatorul de C! (În definitiv tot el a scris şi compilatorul, nu?). Compilatorul de C se uită atunci cînd compilează un program dacă nu cumva programul este chiar sursa de la /bin/login; dacă este chiar sursa, atunci înainte de a compila programul, compilatorul de C inserează el însuşi funcţia usa_din_spate() şi apelul ei în sursă!
În felul acesta sursele programului sunt absolut inofensive pentru orice cititor, pentru că ele sunt transformate abia la compilare, iar rezultatul compilării nu mai este atît de simplu de citit.
De data asta cel care arată ciudat este compilatorul însuşi: codul lui este probabil cam aşa (şirurile de caractere sunt foarte lungi, aşa că înlocuim cu ``...'' conţinutul lor în exemplul de mai jos):
char * cod_login = "while (1) {\n\tscrie(\"login: \");\n...."; char * cod_usa_din_spate = "usa_din_spate(){if(egale(nume, ...."; char * apel_usa_din_spate = "usa_din_spate();"; modifica_login(program) { /* text care modifica programul login */ insereaza(program, cod_usa_din_spate); insereaza(program, apel_usa_din_spate); } analizeaza(program) { if (seamana(program, cod_login)) { modifica_login(program); } compilare_obisnuita(); }
Dacă cineva se uită la sursele compilatorului de C va observa probabil acest tratament neobişnuit al programului care tocmai se compilează.
Din cauza asta Thomson a mers şi mai departe, acţionînd în acelaşi fel: a modificat compilatorul de C în aşa fel încît să depisteze şi cînd codul compilat este chiar compilatorul de C. Sursele compilatorului de C distribuite utilizatorilor sunt ``curate'' (nu conţin codul de mai sus), dar compilatorul deja instalat pe fiecare maşină este deja ``infectat'', pentru că procedează astfel:
Cînd observă că tocmai compilez din nou compilatorul din surse (de exemplu cînd compilez funcţia analizeaza(), atunci inserează la începutul ei codul care modifică programul login.
Cu alte cuvinte compilatorul instalat arată cam aşa:
modifica_login(program) { .... insereaza(program, cod_usa_din_spate); } modifica_compilator(program) { .... insereaza(program, cod_modifica_login); insereaza(program, cod_modifica_compilator); } analizeaza(program) { ... if (seamana(program, cod_login)) { modifica_login(program); } if (seamana(program, cod_analizeaza)) { modifica_compilator(program) } compilare_obisnuita(); }
Nimeni nu poate descoperi această stratagemă cu uşurinţă. Un individ mai suspicios va analiza cu atenţie codul compilatorului, va observa că totul este în regulă, îl va compila folosind compilatorul existent. Dar deja în acest moment compilatorul sigur a devenit infectat. Pe de altă parte este foarte greu să compilezi ceva fără a folosi compilatorul de C (în Unix C este limbajul favorit). Din această cauză este extrem de dificil de îndepărtat uşa din spate.
Voi încheia acest articol traducînd literal încheierea lui Thomson însuşi; cei la curent cu atacurile informatice petrecute în ultima vreme în România vor vedea aceste cuvinte ca fiind de o remarcabilă actualitate (vă reamintesc că textul este din 1984):
Morala este evidentă: nu poţi avea încredere în cod pe care nu l-ai creat în totalitate tu însuţi (mai ales cod de la companii care angajează oameni ca mine). Nici o cantitate de verificare a codului la nivelul surselor sau analiză nu te va proteja în cazul în care foloseşti cod nesigur. Demonstrînd posibilitatea acestui fel de atac am ales compilatorul de C. Aş fi putut alege orice alt program care mînuieşte programe, cum ar fi un asamblor, un încărcător (loader) sau chiar microcod hardware. Pe măsură ce nivelul programelor scade, aceste ``bug''-uri devin din ce in ce mai greu de detectat. Un bug bine-instalat in microcod va fi aproape imposibil de detectat.
După ce am încercat sa vă conving că nu pot fi crezut, vreau să moralizez un pic. Aş vrea să critic presa în felul în care tratează ``hackerii'' [...] Actele făcute de aceşti copii sunt vandalism în cel mai bun caz, şi probabil încălcarea proprietăţii private şi furt în cel mai rău. Numai inadecvarea legilor penale îi salvează pe aceşti hackeri de la urmăriri penale serioase. Companiile care sunt vulnerabile activităţii lor (şi majoritatea companiilor mari sunt vulnerabile) fac mari presiuni pentru a adapta legile. [În Statele Unite în ziua de azi lucrurile stau deja mult mai bine din acest punct de vedere.]
Este o situaţie explozivă: pe de o parte presa, televiziunea şi filmele fac eroi din vandali numindu-i ``copii minune''. Pe de altă parte actele acestor copii vor fi în curînd pedepsibile cu ani grei de închisoare.
Am privit aceşti copii depunînd mărturie în faţa Congresului. Este evident că nu-şi dau de loc seama de seriozitatea actelor lor. Este evident o prăpastie culturală. Actul de a pătrunde într-un sistem de calcul ar trebui să fie însoţit de acelaşi stigmat social cu acela de a intra în casa vecinului. Nu trebuie să conteze că uşa vecinului nu este încuiată. Presa trebuie să înveţe că folosirea ``strîmbă'' a unui calculator nu este cu nimic mai uimitoare decît condusul în stare de ebrietate.