這篇討論的不是 PHP Web 的安全相關議題,而是 Web server 管理者應該考量的系統安全議題。XSS、SQL 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。
很無奈.. 但卻是一針見效。