PHP 讓人詬病的系統安全性

這篇討論的不是 PHP Web 的安全相關議題,而是 Web server 管理者應該考量的系統安全議題。XSSSQL injection 屬於前者,防禦的對象是網頁的瀏覽者;而這篇討論的防禦對象是經常被忽略的 PHP 網頁系統開發人員。

很多人都知道,PHP 屬直譯語言。因為不需要編譯,所以程式碼幾乎可以說是裸露的;除非用 ionCube PHP Encoder 這類的產品作加密,否則,開發人員只要有程式檔案的存取權,就可以看到程式碼。
現今,幾乎所有的 PHP 網頁系統都使用了後端資料庫,而資料庫存取的設定也都是寫在 PHP 程式碼裡面,類似以下這樣:

define( 'DB_SERVER' ,		'localhost' );
define( 'DB_SERVER_USERNAME' ,	'db_username' );
define( 'DB_SERVER_PASSWORD' ,	'db_password' );
define( 'DB_DATABASE' ,		'db_name' );

再透過 require()require_once()incluce()include_once() 等設定檔引入。
如果這個設定檔的路徑沒有在 include_path 系統變數中,引入的方法大概會是這樣:

require_once( '/SOME/WHERE/DB_SETTING.php' );

這樣的系統意味著,有心的程式開發人員可以透過以下這一行程式,輕易取得資料庫存取設定:

echo file_get_contents( '/SOME/WHERE/DB_SETTING.php' );

若是 /SOME/WHERE 被放入 include_path 系統變數,程式開發人員可以透過以下的程式碼引入資料庫存取設定:

require_once( 'DB_SETTING.php' );

雖然以下的程式碼已經無法取出資料庫存取設定:

echo file_get_contents( 'DB_SETTING.php' );

但遇到以下這種程式碼依然是破功:

$paths = explode( ':' , ini_get( 'include_path' ) );

foreach ( $paths as $path ) {
  $file_str = $path . DIRECTORY_SEPARATOR . 'DB_SETTING.php';

  if ( file_exists( $file_str ) ) {
    echo file_get_contents( $file_str );
  }
}

即使設定 auto_prepend_file(之前的文章有提過),或是採用 Autoloading classes,這種問題依然存在。

根本的解決方法就是用 ionCube PHP Encoder 這類的產品作加密,或是用 C 語言撰寫 PHP extension。
很無奈.. 但卻是一針見效。 :-P