2011-02-03 10 views
8

Posiadam serwer WWW wypełniony kodem, który wymaga, aby register_globals był włączony. Większość to niestandardowy kod napisany przez przypadkowych ludzi, którzy pojawili się i zniknęli z biegiem lat. Naprawiłem większość tego w skryptach, o których wiem, ale moim problemem jest znalezienie tych, o których nie wiem.Znajdowanie skryptów PHP wymagających register_globals

Rozważam napisanie aplikacji, aby przejrzeć każdy katalog na serwerze sieciowym, aby zidentyfikować skrypty PHP, które wymagają register_globals. Czy istnieje dobra strategia na zrobienie tego?

Jedna z rozważanych przeze mnie metod polega na zmuszeniu PHP do zgłaszania wszystkich błędów, wykonywania skryptów i sprawdzania niezdefiniowanych zmiennych. Mógłbym zbudować aplikację, która odczyta strumień STDERR.

Czy są jakieś lepsze metody, które można wymyślić?

+3

+1 za nie po prostu za pomocą 'ekstrakt()', aby uzyskać kod brzydko roboczy, ale faktycznie go naprawić – ThiefMaster

Odpowiedz

6

Większość IDE pokaże Ci niezdefiniowane zmienne, na przykład PHPStorm. Możesz pozwolić mu przeskanować wszystkie pliki źródłowe, a będziesz otrzymywać powiadomienia o niezdefiniowanych zmiennych we wszystkich swoich kodach, a faktycznie wykonasz je.

To prawdopodobnie najbardziej prosty i bezbolesny wariant. Ewentualnie można oczywiście napisać własny skrypt z wykorzystaniem Tokenizer i zidentyfikować wszystkie, które nie zostały wcześniej zainicjowane przy użyciu konstruktu. Ale będzie to bardziej podatne na błędy. Korzystanie z IDE prawdopodobnie da lepsze wyniki przy mniejszym wysiłku.

+0

Dzięki, nie wiedziałem o PHPStorm. Dziś spróbuję tego spróbować. Mogę też rzucić okiem na Tokenizera. Ta trasa prawdopodobnie byłaby przesadą dla mnie, ale być może coś z nią zbuduję i wypuszczę ją dla innych. – Brad

+0

@Brad: Czy używałeś PHPStorm? A może sam coś napisałeś? – NikiC

+0

Czekam na PHPStorm, aby uzyskać informacje o mojej bezpłatnej licencji edukacyjnej. Wydaje się, że mają ręczny proces zatwierdzania. Jednak patrząc na to, wierzę, że wykona to zadanie lub przynajmniej znacząco mu pomoże. – Brad

3

Zakładając pojedyncze pliki są zawsze przy użyciu register_globals będąc włączyć lub wyłączyć, można utworzyć listę wszystkich nazw elementów formularza, które są złożone do skryptu, a następnie sprawdzić ten skrypt, czy to za pomocą $fieldname bez zawierający $_REQUEST['fieldname'] (lub $_POST, $_GET tablice).

Twoja metoda "sprawdzania zawiadomień" byłaby w porządku, jeśli możesz zagwarantować bardzo wysoki zasięg kodu podczas wykonywania tych kontroli (aby upewnić się, że niczego nie przegapiłeś - niepokryte części należy następnie sprawdzić ręcznie).

+0

Kłopot w tym, że nie ma możliwości dowiedzenia się, co jest złożone do skryptu.Nie mówię tu o kilku stronach, ani nawet o zawartych aplikacjach ... ale o 200 000 stron internetowych i skryptach PHP. Wiele z tych skryptów odwołuje się do innych skryptów, a niektóre skrypty obsługują posty z innych serwerów/witryn. Dobry punkt na temat możliwych ścieżek kodu. Zakładałem, że PHP wygenerowało 'E_NOTICE' dla tego gdziekolwiek w kodzie, ale dopiero uświadomiłem sobie, że nie byłoby to możliwe, dopóki nie wykonałby kodu używając referencji. – Brad

2

Podczas sprawdzania dzienników pod kątem symptomów skryptów napisanych w oczekiwaniu na globalne znaki, pomocne może być przeczytanie kodu. Jeśli chcesz zautomatyzować to, musisz zbudować lub polegać na interprerze PHP; w przeciwnym razie nie możesz przegapić rzeczy zagnieżdżonych w warunkach, potencjalnych zadaniach itp.

+0

Dzięki za komentarze. Miałem nadzieję, że znajdę sposób, aby polegać na PHP.exe, ale jak już zauważyłeś, po prostu wykonanie go spowoduje pominięcie elementów w instrukcjach warunkowych. Wygląda na to, że metoda ręczna może być rozwiązaniem, jeśli niektóre IDE PHP nie pomogą mi go zidentyfikować. – Brad

1

Istnieje sposób na zlokalizowanie zastosowań rejestrów globalnych, które są ciągami w uruchomionym kodzie. Możesz utworzyć poniższy skrypt i użyć opcji PHP INI auto_prepend_file, aby dodać go do istniejącego kodu.

<?php 

class revealGlobalsUsage { 

    public $globalName; 
    public $globalVal; 

    public function __construct($name, $val) 
    { 
     $this->globalName = $name; 
     $this->globalVal = $val; 
    } 

    public function __toString() 
    { 
     $backtrace = debug_backtrace(); 

     // log backtrace here... 

     return $this->globalVal; 
    } 
} 

// overwrite globals that have been set from GET and POST requests 
foreach ($_REQUEST as $name => $val) { 
    // Strings that are cast to integers will fail as there 
    // is no __toString equivalent for integers/bool/float etc. 
    if (is_string($val) && !is_numeric($val)) { 
     $GLOBALS[$name] = new revealGlobalsUsage($name, $val); 
    } 

    // You can log all GET/POST requests here... 
} 

Dla liczb itd. Trzeba by załatać swój PHP: https://gist.github.com/ircmaxell/1966809

1

wpadłem na ten problem sam w ogromnym kodzie z tysiącami plików. Zainspirowany rozwiązaniem opublikowanym przez @sschueller, przetestowałem ten kod auto_prepend_file, który rejestruje wystąpienia do zbadania. Ta metoda powinna być również używana w połączeniu z parsowaniem/tokenizacją, aby wychwycić wszystkie wystąpienia.

<?php 

$vars = get_defined_vars(); 

foreach ($vars as $var => $value) { 
    if (in_array($var, array('$_SERVER', '$_REQUEST', '$_GET', '$_POST', '$_COOKIE', '$_SESSION', '$_FILES', '$_ENV'))) { 
     // only examine the local symbols, not superglobals 
     continue; 
    } 

    if (array_key_exists($var, $_REQUEST) && $value == $_REQUEST[$var]) { 
     error_log(sprintf("register_globals reliance detected in %s for variable %s=%s", $_SERVER['SCRIPT_FILENAME'], $var, $value), 3, "/var/tmp/register_globals.log"); 
    } 
} 
Powiązane problemy