5/1/2011
Jeśli do zmiennej w skrypcie PHP przypiszemy następującą wartość numeryczną: 2.2250738585072011e-308, to jest spora szansa na to, że skrypt najpierw pożre 100% zasobów procesora, a potem zaliczy crasha. Błąd jest o tyle uciążliwy, że za jego pomocą można zawieszać większość internetowych webaplikacji napisanych w PHP — wystarczy przekazać powyższą liczbę w URL-u jako parametr GET.
2.2250738585072011e-308: PHP x87 FPU bug
Za DoS w PHP odpowiedzialna jest funkcja zend_strod() konwertująca liczby zmiennoprzecinkowe. Wprowadza ona systemy Linux, Windows i FreeBSD w nieskończoną pętlę. Na atak podatne są architektury wykorzystujące koprocesor FPU z zestawem instrukcji x87 (o ile PHP nie skompilowano z flagami: -mfpmath=sse lub -ffloat-store, bo tak naprawdę całemu złu winny jest bug w gcc).
Aby sprawdzić, czy twój serwer i instalacja PHP są podatne, stwórz i odpal skrypt o następującej zawartości:
<?php $d = 2.2250738585072011e-308; ?>
Warto nadmienić, że inne sposoby zapisu tej liczby również powodują ten sam błąd:
- 0.22250738585072011e-307
- 22.250738585072011e-309
- 22250738585072011e-324
Błąd wynika ze zmiennoprzecinkowej arytmetyki IA-32, 80-bit. Funkcja zend_strtod osobno przetwarza podstawę (2.225…011) oraz wykładnik (-308), stosując przybliżenie typu m*10^e o coraz większej dokładności w poszczególnych iteracjach, aż do nastąpienia błędu mniejszego od 0.5ulp. Przy tej licznie, iteracja nie polepsza przybliżenia błędu i algorytm wpada w nieskończoną pętlę. Dotyczy to 80-bit FP, ale nie 64-bit FP, ponieważ x86-64 korzysta ze zbioru instrukcji SSE2 (z 64-bit FP) zamiast przestarzałego x87 — wyjaśnia lifthasiira
Ataki na aplikacje internetowe
Najgorsze w tym wszystkim jest jednak to, że błąd występuje w wielu popularnych serwisach internetowych i webaplikacjach, np. forum phpBB:
/phpBB3/viewforum.php?f=2.2250738585072011e-308
…i zapewne w setkach innych webaplikacji, które przyjmują (traktują) parametr jako liczbę (zmiennoprzecinkową) — na myśl przychodzi mi np. wyszukiwanie produktów po cenach…
Na szczęście w większości przypadków błąd nie jest straszny — CPU podskoczy do 100%, PHP na chwilę się powiesi, a potem zostanie zrestartowane.
Jak się zabezpieczyć przed błędem w PHP?
Developerzy PHP już przygotowali poprawkę. Można też przekompilować sobie PHP z wykorzystaniem flag -mfpmath=sse lub -ffloat-store. Jeśli jednak ktoś z was chciałby się na szybko zabezpieczyć przed atakami DoS na PHP, polecamy wrzucić powyższą linijkę na początku skryptu PHP:
if (strpos(str_replace('.', '', serialize($GLOBALS)), '22250738585072011')!==false) die();
Nie jest to oczywiście jedyna metoda ochrony webaplikacji przed atakami typu DoS. Na naszych szkoleniach zdradzamy kilka innych, sprytniejszych… :-)
Aktualizacja 7.01.2011
Krzysztof Rakowski informuje, że Zend rozesłał newsletter dotyczący błędu.
No to kiszka…
[…]w większości przypadków błąd nie jest straszny[…] Ale są te inne przypadki i są one straszne :D
Debian lenny bez aktualnych poprawek nie jest podatny na atak.
PHP 5.2.6-1+lenny9 ,lighttpd-1.4.19, procesor Celeron (Mendocino).
W tym momencie zaczynam się zastanawiać, czy sprawdzić to w rzeczywistości, czy wam zaufać… :)
Na moim serwerze podziałało, leży ;-).
Błąd nie dotyczy systemów 64-bitowych.
Podobno php skompilowane bez optymalizacji w gcc jest wolne od tego bledu.
Potwierdzam – na pingwinie 64bit nic się niezwykłego nie dzieje. Ot kolejny powód, żeby 32bit wyrzucić wreszcie na śmietnik historii.
slack 13.1 32bit i nic sie nie stalo
Debian, PHP5.2.6-1 + Apache/2.2.9 – nie działa
z ciekawości sprawdziłem jak się zachowa świstak.pl. No i świstak oniemiał jak mu w GET podałem tę liczbę ;p po dłuższym czasie sieskrypt wykrzaczył ;)
Repo DotDeba też wolne od wad ;-)
Działa
Apache 2.2.6
PHP 5.2.5
Procesor:
Czestotliwość: 2500 MHz
Nazwa: Intel (R) Celeron(R) CPU 2.80GHz
Identyfikator: x86 Family 15 Model 3 Stepping 4
Debian lenny z php5 odporny… Miło.
A dlaczego manual PHP o takiej funkcji nie słyszał? http://pl.php.net/manual-lookup.php?pattern=zend_strod
Ubuntu 10.04 32bit – Apache do restartu. Dobre to, całe szczęście nie mam chęci kładzenia nie swoich komputerów.
Windows 7 Ultimate x64 PHP 5.3.1 Apache 2.2.14, AMD Athlon 260 x2 3.3Ghz przekroczono czas wykonywania skryptu. Po ustawieniu czasu wykonywania skryptu na nie skończoność proces httpd i apache ponad 90% procka
Nginx + fastcgi php5 + Debian lenny 32bit = crash
Błąd dotyczy PHP 5.3 na systemach 32bit, nie występuje wogóle w PHP 5.2
@Drewniacki funkcja zend_strod() nie jest funckją języka PHP, lecz wewnętrzną funkcją jego interpretera, czyli ZendEngine
Commodore C-64 Nie podatne :P
Po nazwie zend_strod() brzmi jak funkcja należąca do frameworka ZEND. Mylę się? Wujek G00Gle milczy.
Drewniacki: nie ma takiej funkcji bezpośrednio w PHP, ale jest w interpreterze (zapewne o to chodziło). Na szczęście mój serwer się nie wysypuje :)
Ubuntu 10.10 32-bit również nie wyrabia :).
CentOS x86 się nie daje
@Drewniacki: Bo funkcja zend_strod to wewnętrzna funkcja PHP, jakby to ująć – jest w środku ;-)
Grepnij sobie źródła PHP…
Czy tu chodzi o zabezpieczenie przed operacjami nad rachunkiem niewymiernym?
Przypomina mi to trochę scenariusz filmu “Pi” :D
jeszcze gorzej się dzieje jak wpiszesz słowo google w google.
Jak już piszecie ze Wam działa/nie działa, to podawajcie wynik poleceń php -v oraz uname -a, inaczej to nie ma sensu ;)
@gmo
Nie spodziewałem się, że ktoś jeszcze używa tych procesorów.
@PK
$ php -v
PHP 5.2.6-1+lenny9 with Suhosin-Patch 0.9.6.2 (cli) (built: Aug 4 2010 03:25:57)
Copyright (c) 1997-2008 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2008 Zend Technologies
$ uname -a
Linux 666 2.6.26-2-686 #1 SMP Thu Sep 16 19:35:51 UTC 2010 i686 GNU/Linux
;)
No dobra, tu błąd występuje:
$ php -v
PHP 5.3.2-1ubuntu4.5 with Suhosin-Patch (cli) (built: Sep 17 2010 13:41:55)
Copyright (c) 1997-2009 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2010 Zend Technologies
$ uname -a
Linux XXXXXXXX 2.6.32-27-generic #49-Ubuntu SMP Wed Dec 1 23:52:12 UTC 2010 i686 GNU/Linux
PHP 5.2.6-1+lenny9 with Suhosin-Patch 0.9.6.2 (cli) (built: Aug 4 2010 06:06:53)
Copyright (c) 1997-2008 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2008 Zend Technologies
with eAccelerator v0.9.6.1, Copyright (c) 2004-2010 eAccelerator, by eAccelerator
Linux XXXXXXXXXXXXX 2.6.34.6-xxxx-grs-ipv6-64 #3 SMP Fri Sep 17 16:06:38 UTC 2010 x86_64 GNU/Linux
tutaj brak podatności :)
PHP? A fuj! Ja tam wolę rozwiązania troszkę bardziej tradycyjne czyli skrypty CGI pisane w języku C a potem kompilowane! :)
Co to jest, Fakt? Jak juz piszesz o bledzie, to wspomnij, ze podatny to jest system 32 bitowy, tylko.
@piotr: jak już komentujesz, to przeczytaj dokładnie treść artykułu.
@Drewniacki bo to nie jest funkcja php, tylko funkcja z kodu źródłowego z php w c++
php-5.3.4/Zend/zend_strtod.c
HP 5.3.3-6 with Suhosin-Patch (cli) (built: Dec 7 2010 18:23:49)
Copyright (c) 1997-2009 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2010 Zend Technologies
with Suhosin v0.9.32.1, Copyright (c) 2007-2010, by SektionEins GmbH
Linux 2.6.32-3-686 #1 SMP Thu Feb 25 06:14:20 UTC 2010 i686 GNU/Linux
Błąd występuje, ale działanie skryptu jest przerywane po 30 s.
Przeciez jest jak byk w cytacie:
“Dotyczy to 80-bit FP, ale nie 64-bit FP, ponieważ x86-64 korzysta ze zbioru instrukcji SSE2 (z 64-bit FP) zamiast przestarzałego x87 — wyjaśnia lifthasiira”
php.net leży, ciekawe czy to tylko slashdot effect?
Heh swoją drogą ciekawe ile osób samemu sobie zawiesiło serwer.
Wybacz proszę o Autorze wiercenie dziury w brzuchu. Czy artykuł o spoofingu CallerID nie zaginął? :(
pozdrawiam, świetna strona
Źle mnie podlinkowaliście, paskudy :P Jak mam się wypozycjonować! :)
CentOS – brak podatności.
PHP 5.2.10 (cli) (built: Jun 22 2009 16:28:19)
Linux 2.6.34.6-xxxx-grs-ipv6-64 #3 SMP Fri Sep 17 16:06:38 UTC 2010 x86_64 GNU/Linux
Fatal error: Maximum execution time of 30 seconds exceeded in /mnt/hgfs/***/htdocs/test.php on line 1
Bez żadnych poprawek – nawet ostatnio updateów nie robiłem xD
$ uname -a
Linux ubuntu 2.6.35-22-generic #33-Ubuntu SMP Sun Sep 19 20:34:50 UTC 2010 i686 GNU/Linux
$ php -v
PHP 5.3.3-1ubuntu9 with Suhosin-Patch (cli) (built: Sep 20 2010 22:40:29)
Copyright (c) 1997-2009 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2010 Zend Technologies
Maszyna stoi pod VMWare Playerem – 32bit
Zapomniałem dodać, że serwer oczywiście stoi dalej i się nie przejmuje xD
NA WP powstała wtyczka: http://core.trac.wordpress.org/ticket/16097
Błąd został poprawiony, w wersjach 5.3.5 i 5.2.17 wczoraj wydanych
Czy:
> tak naprawdę całemu złu winny jest bug w gcc
oznacza, że podatne są również wszystkie aplikacje kompilowane tą wersją/z tymi opcjami gcc?
Apache/2.2.14 (Win32) (na win7 64) bit lezy i kwiczy i nawet sie nie resetuje
Dobra… to teraz zagadka. Co się stanie gdy na http://www.jakies-forum.pl wkleję obrazek
;-)
Oczywiście nie trzeba być aż tak “złośliwym”, żeby wykorzystać do atakowania jakiejś strony, tą właśnie stronę… Można to zrobić gdziekolwiek, na przykład na 4chanie… Dlatego, jeśli nie chcemy aby nasze serwery brały udział w DDoS, to mimo wszystko radzę się jakoś zabezpieczyć…
Dobra… obrazek taki:
img src=”http://www.jakies-forum.pl/index.php?f=2.225O738585072011e-308″
Moglibyście zmienić filtry.. :P
To jest bug w procesorze a nie w gcc, gcc natomiast odmawiało workaroundowania go zamiast tego po prostu dokumentując zachowanie jako naturalne. Tu jest dość dobre podsumowanie:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=323#c109
Gcc zawinilo, ale programisci php (zend) powinni pomyslec nad parsowaniem takich intow, a teraz ludzie maja zabawe crashujac procesy na serwerach :)
Hm… Dość poważna sprawa. Myślałem, że Ci lepsi programiści starają się unikać sytuacji, w której można wprowadzić aplikacje w nieskończoną pętlę. Och ironio losu.
postem też leci ? Bo na takiej jednej poleciało postem i wisi :X
@Mekk
wygląda na to, że faktycznie gcc dało ciała. Tutaj bardziej emocjonalny tekst o tym: http://blog.andreas.org/display?id=9
okazuje, się, że kuzynka Java też cierpi na identyczny problem – tam nawet kompilator się może zawiesić :) http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/
Jak komentują developerzy SUNa:
“Some day, we’ll write a stopping test that takes account of the asymmetry of the spacing of floating-point numbers below perfect powers of 2. 26 Sept 96 is not that day.”
/ http://www.docjar.com/html/api/sun/misc/FloatingDecimal.java.html linia 694 /. No i się zemściło :)
[…] się, że nie tylko PHP jest podatne na opisane przez nas niedawno ataki DoS wynikające z błędu konwersji liczby 2.2250738585072011e-308. Co więcej, Java czyni ten bug jeszcze […]