2011-02-03 58 views
8

我繼承了一個充滿代碼的Web服務器,需要register_globals才能打開。其中大部分是由隨機人員編寫的自定義代碼,這些人隨着時間的流逝而變化。我已經將它的大部分內容解決了我所知道的腳本,但是我的問題是找到我不知道的腳本。查找需要register_globals的PHP腳本

我正在考慮編寫一個應用程序來掃描Web服務器上的每個目錄,以識別需要register_globals的PHP腳本。有這樣做的好策略嗎?

我考慮過的一種方法涉及強迫PHP報告所有錯誤,執行腳本並檢查未定義的變量通知。我可以構建一個讀取STDERR流的應用程序。

有沒有更好的方法可以想到?

+3

+1不是簡單地使用`提取物()`讓蹩腳的代碼的工作,但實際上將其固定 – ThiefMaster 2011-02-03 18:41:07

回答

6

大多數IDE會向你顯示未定義的變量,例如PHPStorm。你可以讓它掃描你所有的源文件,並且你將會在你的所有代碼中收到未定義變量的通知,實際執行它。

這可能是最簡單和無痛的變體。或者,您可以明顯使用Tokenizer編寫自己的腳本,並確定所有T_VARIABLE,這些文件以前未使用T_VARIABLEexpr構造來初始化。但這會更容易出錯。使用IDE可能會以更少的努力爲您提供更好的結果。

+0

謝謝,我不瞭解PHPStorm。今天晚些時候我會試一試。我也可以看看Tokenizer。那條路線對我來說可能是過火,但也許我會用它來構建一些東西,然後發佈給其他人使用。 – Brad 2011-02-03 20:05:10

3

假設單個文件總是使用register_globals爲打開或關閉,您可以創建它們提交給腳本,然後如果它使用$fieldname不含$_REQUEST['fieldname'](或$_POST檢查該腳本中的所有表單元素名稱的列表,$_GET陣列)。

如果您在執行這些檢查時可以保證非常高的代碼覆蓋率(以確保您不會錯過任何東西 - 那麼必須手動檢查未覆蓋的部分),您可以「檢查通知」方法。

+0

麻煩的是,我不知道什麼被提交到腳本的方式。我不是在討論幾個頁面,甚至包含應用程序......但是有200,000多個網頁和PHP腳本。很多這些腳本引用其他腳本,並且一些腳本處理來自其他服務器/站點的帖子。關於可能的代碼路徑的好處。我假定PHP爲代碼中的任何位置生成了一個`E_NOTICE`,但是直到它使用引用執行代碼時才意識到這是不可能的。 – Brad 2011-02-03 19:59:44

2

雖然檢查您的日誌以瞭解寫入期望全局變量的腳本的症狀可能會有所幫助,但通過代碼閱讀是真正做到這一點的唯一方法。如果你想自動化這個,你需要建立或依靠一個PHP解釋器;否則你註定會錯過嵌套條件內的東西,潛在的evals等。

+0

感謝您的意見。我希望找到一種方法來依賴於PHP.exe,但正如您已經指出的那樣,僅僅執行它就會錯過條件語句中的項目。看起來像手動方法可能是一條路,如果某些PHP IDE無法幫助我識別它們。 – Brad 2011-02-03 20:04:15

1

有一種方法可以找到使用註冊全局變量,它們是運行代碼中的字符串。您可以創建以下腳本,並使用ini選項將其添加到現有代碼中。

<?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... 
} 

對於你需要修補你的PHP整數等:與成千上萬的文件https://gist.github.com/ircmaxell/1966809

1

我就遇到了這個問題,我自己在一個巨大的代碼庫。受@sschueller發佈的解決方案的啓發,我測試了此auto_prepend_file代碼,該代碼記錄了調查發生的事件。此方法還應與解析/標記化一起使用以捕獲所有事件。

<?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"); 
    } 
}