Nebezpečné preg_replace a zlý nebezpečný nginx

10.05.2014 | 16:45 | Mirecove dristy | Miroslav Bendík

Po hacknutí 2 PHP-čkových webov som bol dokopaný k bezpečnostnému auditu. Našiel som množstvo potecniálnych bezpečnostných rizík. V tomto blogu sa pozrieme na dva, ktoré ma zaujali.

 Null byte injection v preg_replace

Mnoho programátorov považuje volanie funkcií preg_replace bez escapovania za bezpečné. Veď čo by sa mohlo stať pri kóde, ktorý vyzerá nasledovne:

preg_replace('/'.$_GET['replace'].'/i', $_GET['with'], $str);

Vskutočnosti tento zápis umožňuje spustenie ľubovoľného PHP kódu! Možné je to "vďaka" niekoľkým na vysokoúrovňový jazyk dosť neštandardným vlastnostiam.

Prvým problémom je, že PHP väčšinou obaľuje C funkcie. C-čkári určite vedia, čo znamená null terminated string. Po vložení null znaku do parametru replace môžme regulárny výraz kdekoľvek ukončiť a zapísať vlastné flagy.

Druhým problémom je zápis flagov priamo do regulárneho výrazu. Ak by PHP malo flagy ako samostatný parameter preg_replace nemohlo by dôjsť k žiadnemu bezpečnostnému problému.

Posledným a azda najzávažnejším problémom je flag e, ktorý umožňuje spustiť výsledok regulárneho výrazu ako PHP kód. Nasledovným requestom je možné zobraziť phpinfo.

http://www.example.com/subor.php?replace=||/e%00&with=phpinfo();

Takže všade, kde preg_replace umožňuje zadať parametre používaľom je potrebné parametre obaliť do preg_quote. Viacej info napr. tu. Krásny príklad použitia si môžte pozrieť na tomto odkaze.

Zraniteľnosť cgi v spolupráci s nginx

location ~* \.php$ {
  fastcgi_pass php_cgi;
  ...
}

Toto je krásna ukážka diery, pomocou ktorej môže útočník na serveri spustiť ľubovoľný PHP kód. Postačí na server prepašovať súbor obsahujúci PHP kód (napr. avatar obsahujúci <?php ... ?>). Potom stačí do prehliadača zadať nasledujúcu adresu a jpg súbor sa vykoná ako PHP skript.

http://www.example.com/avatars/123.jpg/file.php

Ako je to teda možné? Zapísané pravidlo v nginx nám hovorí, že všetky požiadavky končiace sa na .php nasmeruje na PHP CGI. To funguje správne.

V defaultnej konfigurácii však PHP skúsi nájsť súbor avatars/123.jpg/file.php. Ak neexistuje pokúsi sa nájsť súbor s podobnou cestou (v tomto prípade avatars/123.jpg) a vykoná ho ako PHP skript.

Riešením problému je rôzny tuning nginx, alebo nastavenie cgi.fix_pathinfo=0 v php.ini.

Zopár informácií o probléme tu, alebo priamo vo wiki k nginx.

    • RE: Nebezpečné preg_replace a zlý nebezpečný nginx 12.05.2014 | 15:34
      Avatar bedňa antiX, Devuan, LegacyIce  Administrátor

      Tak najprv som sa pozrel či som náhodou niekde takúto prasačinu s regex niekde nespravil, ale našťastie nie :) To budú potom asi postihnuté všetky regex príkazy, nie?

      To s Nginx je ťažká diera, prečo je vôbec možnosť mať nastavenú takú bíkovinu? Jako pod heslom, spusti hocičo, len nech to nevráti 404.

      Táto správa neobsahuje vírus, pretože nepoužívam MS Windows. http://kernelultras.org
      • RE: Nebezpečné preg_replace a zlý nebezpečný nginx 13.05.2014 | 19:11
        Avatar Miroslav Bendík Gentoo  Administrátor

        Ono sa to netýka len nginx, ale každého webserveru, ktorý podporuje CGI. Zraniteľnosť je v PHP a je tam z pre mňa nepochopiteľných dôvodov.