Sezení v PHP. Vytvoření jednoduchého systému registrace uživatelů v PHP a MySQL Borovský index php uživatele

Dnes se podíváme na zneužití kritické 1denní zranitelnosti v populárním CMS Joomla, která explodovala na internetu na konci října. Budeme mluvit o zranitelnostech s čísly CVE-2016-8869, CVE-2016-8870 a CVE-2016-9081. Všechny tři pocházejí z jednoho kusu kódu, který dlouhých pět let dřel v hlubinách frameworku a čekal v křídlech, aby se pak osvobodil a přinesl s sebou chaos, hacknuté stránky a slzy nevinných uživatelů této Joomly. Pouze ti nejstatečnější a nejodvážnější vývojáři, jejichž oči jsou červené od světla monitorů a klávesnice poseté drobky chleba, dokázali vyzvat běsnící zlé duchy a položit hlavu na oltář oprav.

VAROVÁNÍ Všechny informace jsou poskytovány pouze pro informační účely. Redakce ani autor nenesou odpovědnost za případné škody způsobené materiály tohoto článku. Kde to všechno začalo

6. října 2016 vytvořil Demis Palma téma na Stack Exchange, ve kterém se zeptal: proč vlastně v Joomle verze 3.6 existují dvě metody pro registraci uživatelů se stejným jménem register()? První je v řadiči UsersControllerRegistration a druhý je v řadiči UsersControllerUser. Damis chtěl vědět, jestli byla někde použita metoda UsersControllerUser::register() nebo jestli to byl jen evoluční anachronismus, který zbyl ze staré logiky. Jeho obavou bylo, že i když tuto metodu nepoužívá žádný pohled, lze ji volat vytvořeným dotazem. Na což jsem dostal odpověď od vývojáře pod přezdívkou itoctopus, který potvrdil: problém skutečně existuje. A poslal zprávu vývojářům Joomly.

Pak se události vyvíjely nejrychleji. 18. října vývojáři Joomly přijali zprávu od Damise, který v té době vypracoval PoC, který by umožňoval registraci uživatele. Na svých webových stránkách zveřejnil poznámku, kde mluvil obecně o problému, který našel, a svých názorech na tuto záležitost. Ve stejný den je vydána nová verze Joomla 3.6.3, která stále obsahuje zranitelný kód.

Poté Davide Tampellini roztočí chybu do bodu, kdy nezaregistruje jednoduchého uživatele, ale správce. A 21. října dorazí k bezpečnostnímu týmu Joomla nový případ. Už se v něm mluví o navýšení privilegií. Ve stejný den se na webu Joomla objevuje oznámení, že v úterý 25. října bude vydána další verze se sériovým číslem 3.6.3, která opravuje kritickou zranitelnost v jádře systému.

25. října Joomla Security Strike Team našel nejnovější problém vytvořený kouskem kódu objeveným Damisem. Poté je do hlavní větve oficiálního úložiště Joomla podstrčen commit z 21. října s nenápadným názvem Prepare 3.6.4 Stable Release, který nešťastnou chybu opravuje.

Poté, co toto vyjde, se do vývojářské komunity připojí řada zainteresovaných jednotlivců – začnou propagovat zranitelnost a připravovat exploity.

27. října výzkumník Harry Roberts nahraje do repozitáře Xiphos Research hotový exploit, který dokáže nahrát soubor PHP na server se zranitelným CMS.

Podrobnosti

Pozadí je u konce, přejděme k nejzajímavější části – analýze zranitelnosti. Nainstaloval jsem Joomlu 3.6.3 jako testovací verzi, takže všechna čísla řádků budou relevantní pro tuto verzi. A všechny cesty k souborům, které uvidíte níže, budou uvedeny vzhledem ke kořenovému adresáři nainstalovaného CMS.

Díky objevu Damise Palmy víme, že existují dvě metody, které provádějí registraci uživatele do systému. První z nich používá CMS a nachází se v souboru /components/com_users/controllers/registration.php:108. Druhý (ten, který budeme muset zavolat) žije v /components/com_users/controllers/user.php:293. Pojďme se na to podívat blíže.

286: /** 287: * Metoda registrace uživatele. 288: * 289: * @return boolean 290: * 291: * @od 1.6 292: */ 293: registr veřejné funkce () 294: ( 295: JSession::checkToken("post") nebo jexit(JText::_ ("JINVALID_TOKEN") ... 300: // Získání dat formuláře 301: $data = $this->input->post->get("user", array(), "array" . 315: $return = $model->validate($form, $data: // Kontrola chyb 318: if ($return === false) 319: ( ... 345: / /); Dokončete registraci 346: $return = $model->register($data);

Zde jsem nechal jen zajímavé řádky. Plnou verzi zranitelné metody si můžete prohlédnout v úložišti Joomla.

Pojďme zjistit, co se děje při běžné registraci uživatele: jaké údaje jsou odesílány a jak jsou zpracovávány. Pokud je v nastavení povolena registrace uživatele, formulář najdete na http://joomla.local/index.php/component/users/?view=registration.


Legitimní žádost o registraci uživatele vypadá jako na následujícím snímku obrazovky.


Komponenta com_users je zodpovědná za práci s uživateli. Věnujte pozornost parametru úlohy v požadavku. Má formát $controller.$method . Podívejme se na strukturu souborů.

Názvy skriptů ve složce controllers odpovídají názvům volaných controllerů. Protože náš požadavek má nyní $controller = "registrace" , bude zavolán soubor registration.php a jeho metoda register().

Pozor, otázka: jak přenést zpracování registrace na zranitelné místo v kódu? Asi už to tušíte. Názvy zranitelných a skutečných metod jsou stejné (registrovat), takže stačí změnit název volaného řadiče. Kde se nachází náš zranitelný kontrolor? Přesně tak, v souboru user.php. Ukázalo se, že $controller = "user" . Když vše dáme dohromady, dostaneme task = user.register . Nyní je žádost o registraci zpracována metodou, kterou potřebujeme.


Druhá věc, kterou musíme udělat, je odeslat data ve správném formátu. Všechno je zde jednoduché. Legitimate register() od nás očekává pole s názvem jform , do kterého předáme registrační údaje - jméno, přihlašovací jméno, heslo, email (viz snímek obrazovky s požadavkem).

  • /components/com_users/controllers/registration.php: 124: // Získejte uživatelská data. 125: $requestData = $this->input->post->get("jform", array(), "array");

Náš klient získává tato data z pole s názvem user.

  • /components/com_users/controllers/user.php: 301: // Získání dat formuláře. 302: $data = $this->input->post->get("user", array(), "pole");

Proto měníme názvy všech parametrů v požadavku z jfrom na user .

Naším třetím krokem je nalezení platného CSRF tokenu, protože bez něj nebude registrace.

  • /components/com_users/controllers/user.php: 296: JSession::checkToken("post") nebo jexit(JText::_("JINVALID_TOKEN"));

Vypadá to jako hash MD5 a můžete si to vzít například z autorizačního formuláře na webu /index.php/component/users/?view=login.


Nyní můžete vytvářet uživatele pomocí požadované metody. Pokud vše fungovalo, pak vám blahopřejeme – právě jste zneužili chybu zabezpečení CVE-2016-8870 „chybějící kontrola oprávnění pro registraci nových uživatelů“.

Takto to vypadá v „pracovní“ metodě register() z řadiče UsersControllerRegistration:

  • /components/com_users/controllers/registration.php: 113: // Pokud je registrace zakázána - Přesměrování na přihlašovací stránku. 114: if (JComponentHelper::getParams("com_users")->get("allowUserRegistration") == 0) 115: ( 116: $this->setRedirect(JRoute::_("index.php?option=com_users&view=) login", false)); 117: 118: return false; 119: )

A tak ve zranitelném:

  • /components/com_users/controllers/user.php:

Jo, v žádném případě.

Abychom porozuměli druhému, mnohem závažnějšímu problému, odešleme požadavek, který jsme vytvořili, a podívejme se, jak se provádí v různých částech kódu. Zde je část, která je odpovědná za ověření údajů odeslaných uživatelem v metodě pracovníka:

Pokračování je dostupné pouze pro členy Možnost 1. Připojte se ke komunitě „stránky“ a přečtěte si všechny materiály na stránce

Členství v komunitě ve stanoveném období vám umožní přístup ke VŠEM hackerským materiálům, zvýší vaši osobní kumulativní slevu a umožní vám nashromáždit profesionální hodnocení Xakep Score!

Skriptovací jazyk na serveru Apache.

index.php je nejběžnějším počátečním souborem pro zahájení práce se skriptovacím programovacím jazykem PHP na WEB serveru, zejména na Apache.

Pro začátečníky stačí vědět, že většina webů začíná svou práci s tímto souborem. Soubor je umístěn v kořenovém adresáři hlavního úložiště souborů webu. Může být také umístěn uvnitř adresářů. Poté server Apache vyhledá a načte nejprve index.php v požadovaném adresáři, pokud není v souboru nastavení serveru htaccess uvedeno něco jiného

Jak donutit Apache, aby nejprve načetl index.php (možnosti).

Jak to udělat správně:

# takže práce začíná pouze s index.php DirectoryIndex index.php

Mnoho lidí také dělá toto:

# spusťte skripty kontrolou zadané sekvence DirectoryIndex index.php index.html index.shtml

Zde stojí za to trochu vysvětlit algoritmus akcí:

  • Snažíme se načíst index.php.
  • Pokud je adresář index.php ), pokusíme se načíst index.html .
  • Pokud index.html není v kořenovém adresáři nalezen, pokusíme se načíst index.s html
  • Existuje mnoho dalších možností pro správu stahování, ale musíte si přečíst pokročilejší specifikaci htaccess.

    Tato metoda se obvykle používá, pokud chtějí chránit index.php před skenováním různých zranitelností, například:

    Index.php?mode=page&url="%20AND1="1

    Pokud je index.php jiný, pak vše, co následuje za index.php, nemá žádný význam. Existují však i jiné způsoby, jak určit, který soubor je hlavním spouštěcím souborem na webovém serveru. Takže z této metody neexistuje žádné zvláštní zabezpečení. Ale zvyšuje se nepohodlnost použití. Proto by se s touto metodou mělo zacházet velmi opatrně a ohleduplně.

    Jak skrýt index.php přes htaccess

    Na webovém serveru Apache musí být povolen modul mod_rewrite. Dnes má tento modul povolený téměř každý, ale v každém případě se o tom musíte ujistit, jinak to nebude fungovat. Tuto metodu využívají především SEO optimalizátory.

    Kód pro skrytí index.php

    # povolit modul mod_rewrite RewriteEngine na # vše po odeslání index.php do hlavního příkazového řádku RewriteCond %(THE_REQUEST) ^(3,9)\ /index\.php\ HTTP/ # odstranit index.php z příkazového řádku tak že pouze užitečné informace RewriteRule ^index\.php$ http://site/

    Jak odeslat všechny požadavky přes index.php (přesměrování)

    Obecně zde také není nic složitého.

    # Zapněte mod_rewrite RewriteEngine na # pokud požadavek není soubor, pak bude odeslán do index.php # toto se provádí, pokud váš soubor index.php nezvládá #, co je požadováno, protože je často nutné rozdělit projekt na menší moduly RewriteCond %(REQUEST_FILENAME) !-f # pokud požadavek není adresář, bude odeslán do index.php # toto je provedeno tak, aby adresáře jako /images/ nebyly přesměrovány na index.php RewriteCond % (REQUEST_FILENAME) !-d # odešlete vše ostatní do index.php a pracujte tam RewriteRule (.*) index.php [L]

    Jak stáhnout index.php

    Pokud WEBový průvodce vyhovuje bezpečnostním pravidlům, index.php nelze podle definice stáhnout.

    Index.php si můžete stáhnout pouze pokud:

    • Nastavení v (.htaccess) je zapsáno špatně. Zde je na vině pouze samotný WEB master.
    • K serveru je přístup přes FTP protokol. Nejběžnější způsob. Oběť je podle potřeby pod různými záminkami lákána na předem připravený web (vyhráli jste milion, máte zablokovaný účet na sociálních sítích a podobně). Jakmile se dostanete na požadovanou stránku, cookies se od vás zkopírují. Poté se je pokusí použít ke vstupu na váš web. Tomu se lze snadno vyhnout, jen ke správě webu nepoužívejte WEBová rozhraní a neinstalujte do počítače žádné programy od vám neznámých autorů z neznámých zdrojů, například: všemožné internetové akcelerátory nebo pochybné panely nástrojů s pochybnou účinností , ale velmi silná vytrvalost při instalaci .
    • Na server (zadní vrátka) je nainstalován další skript. Prostřednictvím takového skriptu můžete získat jakýkoli soubor ze serveru, aniž by jej spouštěl obslužný program PHP. Takové soubory lze na server nahrát prostřednictvím běžných a známých zranitelností systému správy obsahu (CMS). Například: WordPress, Joomla, DLE, Drupal, Codeigniter a tak dále. Dále se pod maskou avatara stáhne speciálně vygenerovaný soubor .gif, který lze později vyvolat se znalostí jeho umístění na serveru oběti. Pokud CMS nezpracovává takové soubory správně, lze přes něj získat potřebný přístup k webu. Nebo na CMS, jako je WordPress, Joomla a další, je nainstalován široce inzerovaný plugin (například: index vyhledávání php), který zdánlivě plní svou funkci, ale zároveň prosakuje data o webu jeho vývojářům, čímž umožňuje aby používali stránky tímto způsobem, jak chtějí.

    Něco takového. Pokud máte dotazy, zeptejte se je v komentářích a brzy se v tomto článku objeví vysvětlující odpověď.

    Dalo by se dlouho polemizovat, proč někteří lidé rádi svinsky a ničí plody cizí práce, ale tak či onak je to fakt, který je relevantní i pro virtuální svět. I na úsvitu domácího PC, tzn. Když k nim všichni začali mít přístup, začal tento mor. Byl napsán první virus, hacknuta první webová stránka... teď už to nikoho nepřekvapí. Mnozí jsou již zvyklí, že čas od času vídají nápisy jako „Byl jsem tady super-duper hacker“ a další projevy počítačového vandalismu.

    K většině těchto útoků dochází v důsledku zneužívání děr ve skriptech serveru. Tento článek bude hovořit o zakrytí stejných mezer pro hackery.

    Jak tedy bylo řečeno, hacker může na stránky přistupovat prostřednictvím serverových skriptů (samozřejmě existuje mnoho dalších možností, například odcizení hesla - pomocí trojského koně, snifferu nebo dokonce drze z počítače uživatele, ale to je samostatné téma). Proč serverové? Ano, protože s klientskými - těmi, které jsou spuštěny na počítači návštěvníka webu, nemůže nic dělat. Nemají žádná přístupová práva k serveru, kromě toho, že z něj mohou přijímat informace a to je vše, ale v žádném případě klientské skripty nebudou moci na serveru samostatně nic měnit.

    Nejrozšířenější serverovou technologií je dnes PHP. Myslím, že když čtete tento článek, není třeba se znovu pozastavovat nad tím, co to je, zvláště když na toto téma již bylo mnoho dobrých článků. No, pojďme přestoupit.

    V první řadě chci říct, že příklady zde uvedené nezaručují 100%, že vás nikdo nenabourá, to je prostě nemožné. Vždy se najdou překážky, a to i v těch nejrozšířenějších a nejpokročilejších systémech, příkladem toho byla senzace před šesti měsíci, kdy byla na webových stránkách po celém světě nalezena hrubá chyba zvaná SQL Injection v dotazech v všeobecně uznávaném jazyce SQL (Structured Query); Jazyk). . Zároveň ale uvidíte nejčastější fatální chyby v ochraně a budete se moci dostatečně chránit před útoky nejen amatéra, ale i profesionálního hackera.

    Pro začátek si musíte pamatovat pouze jednu věc - nikdy nedůvěřujte datům přijatým od návštěvníka - koneckonců to může být škodlivý skript, který mimochodem může být buď na straně serveru, nebo na straně klienta (bude fungovat na strojích pro návštěvníky). A to samozřejmě stačí, pokud v samotných skriptech nejsou žádné kritické chyby a samotný server je nakonfigurován normálně, ale nejprve.

    První příklad, který vás napadne, je, že jste se rozhodli napsat knihu návštěv. To znamená, že potřebujete pole pro zadání jména, e-mailové adresy a samotné zprávy. PHP skript přijímá data z formuláře a ukládá je do speciálního souboru pro pozdější zobrazení při čtení knihy návštěv. Zdá se, že nejde o nic nebezpečného, ​​ale hacker si to nemyslí, pokud neexistují vhodná bezpečnostní opatření, může tento formulář použít pro své vlastní účely. No, nedáme mu šanci.

    Pro začátek by bylo dobré omezit délku jména a e-mailové adresy. Není to jen jeden z mnoha způsobů částečné ochrany, ale také ochrana proti kašpárkům, kteří si myslí, že jméno o několika stovkách postav je velmi vtipné. Zapišme tedy, řekněme, maxlength=25 do vstupního pole, například:

    Nikdo tak nebude moci do tohoto pole zadat více než 25 znaků. To však zastaví pouze virtuální nováčky vandaly, protože do adresního řádku můžete snadno napsat něco jako:

    ...guest.php?user_email=ha_ha_ha_slabaja_zashita_ha_ha_ha_tyt_bil_super_haker...

    No, zasadíme druhou ránu tím, že na úplný začátek PHP skriptu napíšeme něco takového:

    V opačném případě jej přesměrujeme na stránku pro zadání přihlašovacího jména a hesla: header ("location: index.php");

    Nyní, když známe princip autorizačních mechanismů pomocí relací, zvážíme a opravíme úzká hrdla prezentovaných skriptů. Identifikátor relace, který umožňuje přístup k samotné relaci a je uložen v prohlížeči na straně uživatele, nebude považován za úzké místo. Důvodů je mnoho - počínaje skutečností, že identifikátor je platný po krátkou dobu, zejména pokud uživatel opustí web, zavře prohlížeč nebo nebyl delší dobu aktivní, relace je zničena, a končící tím, že identifikátor je obvykle jedinečný 128bitový kód, zpravidla obtížnější než jakékoli uživatelské heslo.

    Následující body jsou potenciálně nebezpečné:

    I přes přítomnost kontroly, že data byla odeslána z formuláře, to můžete bezpečně nasimulovat a zkusit uhodnout heslo pomocí skriptu auth.php

    Skript done.php lze oklamat takto: done.php?login_user=login

    Pro eliminaci první zranitelnosti je vhodné udělat vše, co bylo popsáno v předchozím článku, tedy tvrdé přijetí proměnné pouze z pole POST, kontrola $HTTP_REFERER, kontrola a ořezání proměnné. Protože se musíme chránit před četnými útoky, můžeme zaznamenat IP návštěvníka a řekněme po 3 neúspěšných pokusech ho na 15 minut zablokovat. Nedoporučoval bych však používat blokování IP - lze jej snadno obejít a mnoho uživatelů proxy serverů tím může trpět. Mnohem rozumnější je uplatnit odklad povolení. Tito.

    Těsně před kontrolou správnosti loginu a hesla uděláme prodlevu, řekněme 1 sekundu. Uživatelé si toho s největší pravděpodobností ani nevšimnou, ale rychlost brute-force hackerů klesne pod 1 kombinaci za sekundu, což prakticky zcela eliminuje možnost brutálního vynucení hesla i pomocí speciálního slovníku. Můžete to odložit takto:

    spánek(1); //zpoždění o 1 sekundu



    
    Horní