Přejít k navigační liště

Zdroják » Různé » Aktuálně: Tak nám hackli GitHub…

Aktuálně: Tak nám hackli GitHub…

Články Různé

Krátce poté, co zde vyšel seriál Jdu hacknout váš server, máme další článek na stejné téma. Tentokrát ale „žhavě aktuální“ o tom, jak jeden ruský programátor hacknul github (a poukázal na chybu v Rails, která se projevuje i na dalších serverech). A přitom stačilo, aby tým vývojářů Rails naslouchal…

Vše začalo v pátek, kdy @homakov vytvořil issue request, ve kterém navrhoval změnit standardní nastavení Active Record v Rails tak, aby vyžadoval od programátorů whitelist na Mass Assignmentu.

Jedná se přesně o to, co se řeší v PHP už velice dlouho – kontrola dat, které dostává skript od uživatelů ve formuláři. V Active Recordu (= „Doctrine pro Ruby“) můžete nastavit všechny parametry jednou metodou. V podstatě jde o to, že v rámci Ruby on Rails většina programátorů dělá v controlleru:

# save user data
Users.find(params[:id]).update_attributes(params[:user])

Pokud v rámci modelu Users nemáte nastaveno attr_accesible, pak můžete nastavit jakýkoliv parametr modelu, včetně (například) administrator.

Homakov reportoval issue, pohádal se s vedoucími developery Rails, a ti se nechali slyšet, že výhody standardního nastavení (kdy attr_accessible není použito) vyvažují jakékoli nevýhody plynoucí z vynucení. Homakov byl přesvědčen, že problém má ve skutečnosti obludné rozměry, a začal si hrát s Githubem, který je nad Ruby on Rails postaven.

V rámci přesvědčování Rails dev týmu vytvořil issue I’m bender from future, který byl založen v roce 3012. Udělal to jednoduše – ve firebugu přidal <input type="hidden" name="created" /> a, ke svému vlastnímu překvapení, zjistil, že to funguje. Proof of concept zaslal Githubu v pátek, a GitHub chybu ihned opravil.

Rails tým reagoval slovy „good one.“

Homakov pokračoval v experimentech. Napsal komentář jménem DHH (jeden z hlavních vývojářů Rails.) To byla docela legrace.

Potom mohl vymazat obsah jakéhokoliv příspěvku. To už nebyla sranda, to bylo docela nebezpečné.

Pak zjistil, že může přiřadit svůj SSH klíč k jakémukoliv projektu. Jackpot.

Rails tým stále ignoroval Homakovův požadavek i informace o závažnosti problému. Nakonec se tedy rozhodl, že udělá push do master větve ruby on rails. Nic nerozbil, jenom přidal jeden soubor a problém poté reportoval Githubu.

O github mu nešlo – šlo mu o standardní politiku Rails, která vede k bezpečnostním dírám. Github vydal roztomilé prohlášení, kde se rozplývají nad tím, jak problém proaktivně zjistili, smazali dotyčný SSH klíč a suspendovali účet tomu, kdo na exploit přišel.

Dozvuky

Rails komunita se okamžitě rozdělila na dva tábory – jeden tleskal, druhý Homakova odsuzoval. Faktem je, že i když mohl přistupovat k jakýmkoliv repozitářům, jediné, co udělal, bylo, že commitoval do rails/master. Mohl se přitom dostat k repositories, která jsou private, mohl tímto způsobem dělat s celým githubem, co by se mu zlíbilo. Na druhou stranu problém „prachsprostě využil“ a neoznámil jej nejdříve Githubu. Osobně si myslím, že udělal správnou věc – kdyby ho oznámil, díra v Rails aplikacích leží dodnes.

Hodinu po zmíněném pushi do masteru upravil Rails tým generátory tak, že je standardní politika restriktivní. Veškeré argumenty, které celou dobu stavěli proti, najednou ignorovali.

Dosah celé věci je mnohem závažnější, i když není vidět na první pohled – takto způsobenou díru obsahuje Posterous, Scribd, Speakerdeck a řada dalších služeb. A jedná se i o firmy, které mají velké finanční zázemí a mají dobré vývojáře! Popadaných webů bude v tomto týdnu asi nemálo. Máme se na co těšit, zatím je to docela show.

Nejsmutnější na celé věci je, že o chybě se ví minimálně od května 2007. A o celých pět let později to využije devatenáctiletý mladík k tomu, aby dokázal Rails týmu, že se jedná o skutečný problém.

Oprava bezpečnostní díry

Nejsem Ruby developer, a tak vás odkážu na tento článek. V podstatě by mělo do všech modelů stačit doplnit parametr attr_accessible, jak je vysvětleno v dokumentaci. Pokud jste o něm nikdy neslyšeli, nechtěl bych teď být ve vaší kůži.

Další čtení

Komentáře

Subscribe
Upozornit na
guest
42 Komentářů
Nejstarší
Nejnovější Most Voted
Inline Feedbacks
View all comments
stewe

pekne :D

Mennion

Zajímavé mi na tomhle přijde nezvládnutí ega vývojářů githubu. Možná se pletu, ale celé to na mě působí dojmem, že si vývojři řekli : „Přece nám tady nebude radit nějaký usmrkaný klučina s bezpečností“, protože jinak si neumim vysvětlit, že ten problém nechali dojít až do stavu commitovaní do hlavní větvě railsů…

sidik

Ono kde co nese označení „not a rails problem“. Rails devs jsou z větší části banda idiotů, s kterejma se nedá absolutně mluvit.

Mennion

Až tak útočný bych nebyl, ale (naivně) jsem si myslel, že vývojáři na jejich úrovni, už nebudou mít problém přiznat chybu, opravit ji a nebo se o ni normálně pobavit…

www

:-) no kdo to nezkusil, tak by asi tak utocny nebyl, to je fakt. a o jake urovni se bavime? kdyz si proctete na githubu nahlasene chyby a reakce na ne od rails vyvojaru, tak je to uz jasny. opravdu dobrych je mezi nima jen par.

František Kučera

Pěkné :-)

Jak to vlastně funguje? Definuji ve frameworku formulář, kde vyjmenuji atributy a všechno kolem se udělá samo. Nebo na straně serveru přijímám vstup z libovolného formuláře (který si třeba napíšu sám, tudíž framework neví, jaké atributy tam chci mít) a na straně serveru jen nechám nasypat POST parametry do vlastností objektu?

V prvním případě je to chyba frameworku, protože mohl vědět, které atributy tam chci – v druhém případě je to chyba aplikace a framework je v tom nevinně, protože nemohl tušit, které atributy vývojář chce nastavit a které ne.

František Kučera

Např. v Javě (JSP) jde udělat stejná věc, ale nemyslím si, že by to byla chyba – tohle je podle mého odpovědnost programátora aplikace. Programátor si přece může vyrobit DTOčko, do kterého půjdou nastavovat jen vybrané atributy, nebo je může nastavovat individuálně místo hromadně. Ale když místo toho zavolá funkci „nastav všechny atributy podle POST parametrů“, tak si framework myslí, že to je přesně to, co programátor chce. Je to přece stejné, jako když zavolám funkci/metodu na smazání entity – framework/jazyk/plat­forma, taky nemůže tušit, že mazat ve skutečnosti nechci a volám tu funkci omylem.

Další věc je, že aplikace nebývají často jen pouhým rozhraním k databázi a mají nějakou logiku – a součástí ní je třeba i to, kteří uživatelé/role mohou nastavovat které atributy kterým entitám. Některé atributy půjdou nastavovat třeba jen v určité hodiny, nebo při připojení z určité sítě nebo na základě jiných atributů (např. článku, který neprošel korekturou nepůjde nastavit stav na „vydáno“) atd. atd. Takže tam stejně nějaký „filtr“ vytvořený programátorem být musí. Je fajn, když tahle pravidla jdou vyjádřit deklarativně. Ale tak jako tak je to odpovědnost programátora. Přijde mi, že se spousta lidí nechalo unést tím, jak snadno se dá dělat software, aniž by četli dokumentaci nebo přemýšleli, co která funkce dělá – a takhle se jim to ošklivě vymstilo.

Srigi

Mna to prekvapilo aj tak. Yii framework v PHP, cista kopia RoR touto chybou out-of-box netrpi. Plati tam jednoduche pravidlo – field bez validatora (aj prachobycjany „required“) nie je mozne nastavovat masivnym priradenim.

Scaffolder validacne pravidla pekne do modelov pripravi z definicie tabuliek. Formulare si musi programator postrazit sam. Developer sa tak od zaciatku uci dobrym navykom.

Maly priklad – z beznej tabulky, povedzme ‚articles‘ sa nastavia validacne pravidla ‚required‘ pre stlpce s NOT NULL. Stlpec s AUTO INCREMENT sa ale vynecha – nie je mozne z vonka zmenit ID entity. Jasne, takato jednoducha logika nezabrani priradit rolu ‚admin‘ ak ma ten field validator. To uz si musi postrazit logika aplikacie.

sidik

Protože Xue u toho přemejšlí. A taky sleduje ostatní frameworky (nejen PHP) a snaží se vyhnout jejich chybám. Asiat no :D

Mennion

Přesně to mě napadlo, že tenhle problém elegantně řeší nějaký view model, který bude mapovat a bindovat jen ty property, které chci. Je to sice práce navíc, ale osobně se mi to u .net mvc mnohokrát oplatilo.

P.S. K čemu bude dobré, když whitelist/blac­klist bude výchozí chování?

IMHO více méně k ničemu, protože tím akorát omezím aktualizace atributů, které se nikdy nemění – např. primárního klíče nebo okamžiku vytvoření entity. Ale co všechny ty ostatní atributy? U nich totiž nemůžeme zakázat aktualizace, protože někdy je upravovat potřebujeme – např. administrátor může měnit role jiných uživatelů a jejich e-maily, běžný uživatel může měnit svůj e-mail ale ne jiných uživatelů atd.

Může ten whitelist/blac­klist být vázaný (alespoň) na role aktuálně přihlášeného uživatele? Pokud ne, tak je to na nic. Ne, tohle není řešení a stejně tam musí někde ta logika (kdo co může) být zapsaná.

Lol Phirae

Ale co všechny ty ostatní atributy? U nich totiž nemůžeme zakázat aktualizace, protože někdy je upravovat potřebujeme – např. administrátor může měnit role jiných uživatelů a jejich e-maily, běžný uživatel může měnit svůj e-mail ale ne jiných uživatelů atd.

No, to jistě. Ale od toho tam jsou role. :-) Např. ten administrátor. :-)

František Kučera

jj, to už jsem taky zjistil, více viz tehle komentář.

Michal

Good one :-)

Pooky

Kaju se, přesně tu samou chybu mám taky, shame on me…

blizz

prvý článok na zadrojáku ktorý som prečítal od začiatku do konca :P palec hore

allstar

Přesně stejná věc je i ve frameworku grails, akorát se to tam jmenuje jinak – attribut „.properties“.

Čelo

DHH k tématu poslal: https://gist.github.com/1975644
Celkem rozumím tomu, proč to řeší v controlleru a ne v modelu.

Karel

Z pohledu IT člověka se reakce GitHubu může zdát dětinská, ale z pohledu marketingu a legislativy neměli moc na výběr. Evidentně dlouhou dobu bagatelizovali problém a najednu jim někdo ukázal, že problém existuje. V té chvíli musí provozovatel udělat dvě věci – chybu promptně opravit a ukonejšit laickou veřejnost, že nešlo o vážný problém. A to konejšení laické veřejnosti je právě to zablokování účtu dotyčného a ještě větši bagatelizování ve smyslu „i kdyby snad někdo tu díru použil, my na to přijdeme a zjednáme nápravu“. Znalý člověk si sice poklepe na čelo, že tady logika hapruje, ale akcionář a zákazník si bude myslet „jo, těm nic neunikne“. Nejde tedy ani tak o projev uraženého ega, jako o snahu udržet si zdroj peněz. No a nebo, a to je můj osobní názor, jde o kombinaci obojího.

j

Tohle funguje presne do okamziku, kdy sedi na strane zakaznika managor, kterej nicemu nerozumi a nesleduje ani co se deje. Ovsem az si (i ten blbej managor) precte (trebas) zdejsi clanek, tak vyhodnoti tohle chovani jako velmi neduveryhodne a da od podobnyho partnera ruce pryc.

Delat chyby, je totiz normalni, ale nepriznat je, je vetsi pruser nez ta najvetsi chyba. Driv nebo pozdejs se to totiz stejne provali a pak to nekdo nalezite rozmazne.

Mennion

„Delat chyby, je totiz normalni, ale nepriznat je, je vetsi pruser nez ta najvetsi chyba“

Tesat do kamene. Z mého pohledu měli tu chybu opravit, zveřejnit na svém blogu, jak staré projekty aktualizovat.

mamlasek

Nemyslim si, ze by byl GitHub pouzivan z vetsi casti prave „laickou verejnosti“… Spis bych rekl, ze laik o GitHub nezavadi, popripade je procento takovych uzivatelu mrzce nizke.

Me

Tak to jsou v GitHub docela améři, míchat vnitřní atributy a ty co dostanou z formuláře, to se v php nedoporučovalo už před sto lety, klasickej příklad byl vždycky nastavení user_id na adnimistrátora :D

vks

no, jo, je to o par let mladsi jazyk a chcou byt proti proudu, tak si musi hloupost svych „registerGlobals“ poznat sami, protoze zkusenosti jsou temer neprenosne…

from wiki

Ruby i PHP jsou pro verejnost z roku 1995, Ruby vyvoj zacal o rok drive nez php

Wiki
http://cs.wikipedia.org/wiki/Ruby_(programovac%C3%AD_ja­zyk)

„Práce na něm započaly v roce 1993, první verze byla uveřejněna v roce 1995 „

http://cs.wikipedia.org/wiki/PHP

„Vše začalo v roce 1994“

fuzzy

Až na to že ten problém není v Ruby ale ve frameworku Ruby on Rails … a ten měl první release v roce 2004.

Me

To že RoR chybí nějaká vlastnost ještě neznemená, že to programátora nepraští do očí a něco si tam nedobastlí, aby to neměl děravé jak cedník, proto mne překvapuje, že to exprti na github ignorovali.

fuzzy

Ono to ale není tak že by „RoR“ nějaká vlastnost chyběla. Možnost filtrovat fieldy které lze přes mass assignment modifikovat tam je (whitelisting i blacklisting), akorát je to holt v defaultu vypnuté protože RoR vývojáři razí myšlenku že to v defaultní instalaci má být použitelné i pro naprosté začátečníky a tímhle by se to komplikovalo …

Ano, máte pravdu že programátoři githubu (a dalšího asi milionu projektů které RoR používají) to měli změnit a nastavit. Současně to pěkně ilustruje že bezpečnostní princip „defaultně zakázat, povolit jen vyjmenované“ má svůj smysl.

David Grudl

Z té myšlenky „že to v defaultní instalaci má být použitelné i pro naprosté začátečníky a tímhle by se to komplikovalo“ mě úplně jímá hrůza. Použitelnost pro naprosté začátečníky je skvělá věc, ale za žádných okolností to nesmí být na úkor bezpečnosti.

Proč by weby začátečníků měly být děravé? Protože jsou začátečníci? Právě naopak, začátečník se v bezpečnosti neorientuje a na framework spoléhá. Tímhle ho ale podvedl.

Čelo

konec dobrý, všechno dobré :)
Pochopili, změnili… osobně jsem rád, protože když jsem to při prozkoumávání RoR sám zjistil, tak jsem se tomuto přístupu hodně divil.

HKMaly

Chapu spravne, ze clovek ktery vymyslel v sequelu metodu set_fields byl genius protoze vyvojare Railsu tohle nenapadlo pet let? ( http://sequel.rubyforge.org/rdoc/classes/Sequel/Model/InstanceMethods.html#method-i-set_fields )

mat.

Ne. Nechápete to dobře. Jak už tady bylo zmiňované několikrát – vývojáře Railsu to pochopitelně napadlo. Jde jen o defaultní chování a jejich preference.

HKMaly

Jde o to, ze narozdil od uvedeneho attr_protected muze tahle funkce mit pri kazdem volani jine parametry.

Oldis

zkratka „tak jak sem to udelal, je to nejlepsi a nikdo nema pravo mi do toho zvanit.“

Frantisek S.

V rámci přesvědčování Rails dev týmu vytvořil issue I'm bender from future, který byl založen v roce 3012. Udělal to jednoduše – ve firebugu přidal <input type="hidden" name="created" /> a, ke svému vlastnímu překvapení, zjistil, že to funguje. Proof of concept zaslal Githubu v pátek, a GitHub chybu ihned opravil.

Rok 3012?

František Kučera

Ale pozitivní je, že počítali s tím, že někdo může zadat příspěvek v budoucnu – připraveni na všechno :-)

5o

Presne, ked som skusal rails (cca 3 r. dozadu) tak v niektorom zo screencastov na toto poukazovali, a odvtedy si pamatam tuto nebezpecnu dieru avsak rails som nechal tak a ostal pri PHP (nie preto).

V zende je to riesene cez formulare. Naplnim si formular parametrami a tie (ak je validny) vytiahnem. Pritom formular vrati iba tie parametre, ktore su v nom definovane (moznost nastavit filtre na hodnoty). Ak je vo formulari select tak pri zadani hodnoty ktora v nom nie je formular vrati chybu atd.

Čelo
Čelo

Enum a statická analýza kódu

Mám jednu univerzální radu pro začínající programátorty. V učení sice neexistují rychlé zkratky, ovšem tuhle radu můžete snadno začít používat a zrychlit tak tempo učení. Tou tajemnou ingrediencí je statická analýza kódu. Ukážeme si to na příkladu enum.