標籤:style class blog http tar ext
跨站指令碼
在媒體的協助下,跨站指令碼(XSS)成為了大家關注的焦點,當然它是絕對應當關注的。XSS 是 web 應用中最常見的安全隱患,許多流行的開放原始碼的 PHP 應用程式受到 XSS 隱患的困擾。
XSS 攻擊發生在下面的情況下:
對於可獲得使用者信任的特定網站。
使用者沒有必要用很高的等級信任任何網站,但是瀏覽器需要。例如,當瀏覽器在請求中發送 cookie,則意味著信任目標網站。對於不同的網站,使用者可能有不同的瀏覽行為或者不同的安全防範等級。
通常包含顯示外部資料的網站。
有高風險的應用程式套件含論壇、web 郵件以及任何會顯示出來的彙總內容(如 RSS feeds)。
攻擊者可控制的內容注入。
當外部資料沒有很好的過濾時,可能會顯示攻擊者需要的內容。這意味著攻擊者可以更改伺服器上的代碼。
這是如何發生的?如果顯示一個從外部獲得的沒有很好過濾的內容,則會產生 XSS 安全隱患。外來資料不僅限於用戶端的資料。同時也包含顯示在 web 郵件上的電子郵件、廣告條、彙總 blog 以及類似的東西。任何從外部獲得的,不在代碼中的資訊都是外部資料,這意味著多數資料都是外部資料。
偽造跨站請求
忽略名字上的相似程度,偽造跨站請求(CSRF)是幾乎完全相反的攻擊方式。XSS 是利用使用者對網站的信任展開攻擊;CSRF 是利用網站對使用者的信任展開攻擊。CSRF 攻擊更加危險,更少遇到(意味著對於開發人員沒有更多資料),並且比起 XSS 攻擊更加難以防禦。
CSRF 攻擊發生在下面的情況下:
對於可獲得網站信任的特定使用者。
多數使用者可能不被信任,但是 web 應用向使用者提供特定的許可權以便其登入進入應用程式是很普遍的。擁有很高的特權的使用者往往都是受害者(事實上在自己不知道的情況下成為了同謀)。
通常網站信任使用者的身份標識。使用者的身份標識擁有著重要的地位。但是即便有安全的會話管理機制,CSRF 攻擊仍然能夠成功。而且事實上,對於這種情況 CSRF 攻擊更加有效。
攻擊者可隨心所欲的執行 HTTP 要求。
在 CSRF 所有攻擊方式中包含攻擊者偽造一個看起來是其他使用者發起的 HTTP 要求(事實上,跟蹤一個使用者發送的 HTTP 要求才是攻擊者的目的)。有一部分技術可以用來完成這個,後面會示範一個使用特別技術的例子。
由於 CSRF 攻擊包含偽造 HTTP 要求,熟悉底層 HTTP 協議就變得非常重要。
偽造跨站請求介紹
偽造跨站請求比較難以防範,而且危害巨大,攻擊者可以通過這種方式惡作劇,發spam資訊,刪除資料等等。這種攻擊常見的表現形式有:
偽造連結,引誘使用者點擊,或是讓使用者在不知情的情況下訪問
偽造表單,引誘使用者提交。表單可以是隱藏的,用圖片或連結的形式偽裝。
比較常見而且也很廉價的防範手段是在所有可能涉及使用者寫操作的表單中加入一個隨機且變換頻繁的字串,然後在處理表單的時候對這個字串進行檢查。這個隨機字串如果和目前使用者身份相關聯的話,那麼攻擊者偽造請求會比較麻煩。
yahoo對付偽造跨站請求的辦法是在表單裡加入一個叫.crumb的隨機串 ;而facebook也有類似的解決辦法,它的表單裡常常會有post_form_id和fb_dtsg。
執行個體:
Php代碼
- <?php
-
- class Crumb {
-
- CONST SALT = "your-secret-salt";
-
- static $ttl = 7200;
-
- static public function challenge($data) {
- return hash_hmac(‘md5‘, $data, self::SALT);
- }
-
- static public function issueCrumb($uid, $action = -1) {
- $i = ceil(time() / self::$ttl);
- return substr(self::challenge($i . $action . $uid), -12, 10);
- }
-
- static public function verifyCrumb($uid, $crumb, $action = -1) {
- $i = ceil(time() / self::$ttl);
-
- if(substr(self::challenge($i . $action . $uid), -12, 10) == $crumb || substr(self::challenge(($i - 1) . $action . $uid), -12, 10) == $crumb) return true;
- return false;
- }
-
- }
-
- $uid = 112;
- if($_POST[‘submit‘] == ‘submit‘) echo Crumb::verifyCrumb($uid, $_POST[‘crumb‘]) ? ‘good‘ : ‘bad‘;
-
- ?>
- <form method="post">
- <input type="hidden" name="crumb" value="<?php echo Crumb::issueCrumb($uid)?>">
- <input type="text" name="content">
- <input type="submit" name="submit" value="submit">
- </form>