安全性

跨站腳本攻擊的防範

跨站腳本攻擊 (簡稱 XSS),即 Web 應用程式從使用者收集使用者資料。 通常,攻擊者向脆弱的 Web 應用程式注入 JavaScript,VBScript,ActiveX,HTML 或 Flash 來欺瞞使用者以收集存取者的訊息。 舉個例子,一個未經良好設計的論壇系統可能不經檢查就顯示使用者所輸入的內容。 攻擊者可以在文章內容中注入一段惡意的 JavaScript 程式碼。 這樣,當其他訪客在閱讀這個文章的時候,這些 JavaScript 程式碼就可以在訪客的電腦上運行了。

一個防範 XSS 攻擊的最重要的措施之一就是:在顯示使用者輸入的內容之前進行內容檢查。 比如,你可以對內容中的 HTML 進行編碼處理。但是在某些情況下這種方法就不可取了,因為這種方法禁用了所有的 HTML 標籤。

Yii 整合了 HTMLPurifier 並且為開發者提供了一個很有用的元件 CHtmlPurifier, 這個元件封裝了 HTMLPurifier 類別。它可以將通過有效的審查、安全和白名單功能來把所審核的內容中的所有的惡意程式碼清除掉,並且確保篩選之後的內容篩選符合標準。

CHtmlPurifier 元件可以作為一個 小工具 或者 篩選器 來使用。 當作為一個小工具來使用的時候,CHtmlPurifier可以對在視圖中顯示的內容進行安全篩選。 以下是程式碼範例:

<?php $this->beginWidget('CHtmlPurifier'); ?>
//...這裡顯示使用者輸入的內容...
<?php $this->endWidget(); ?>

跨站冒名請求攻擊的防範

跨站冒名請求 (簡稱CSRF) 攻擊,即攻擊者在使用者瀏覽器在存取惡意網站的時候,讓使用者的瀏覽器向一個受信任的網站發起攻擊者指定的請求。 舉個例子,一個惡意網站有一個圖片,這個圖片的 src 地址指向一個銀行網站: http://bank.example/withdraw?transfer=10000&to=someone。 如果使用者在登入銀行的網站之後存取了這個惡意網頁,那麼使用者的瀏覽器會向銀行網站發送一個指令,這個指令的內容可能是「向攻擊者的帳號轉賬 10000 元」。 跨站攻擊方式利用使用者信任的某個特定網站,而 CSRF 攻擊正相反,它利用使用者在某個網站中的特定使用者身份。

要防範 CSRF 攻擊,必須謹記一條:GET請求只允許檢索資料而不能修改伺服器上的任何資料。 而 POST 請求應當含有一些可以被伺服器識別的隨機數值,用來保證表單資料的來源和運行結果發送的去向是相同的。

Yii 實現了一個 CSRF 防範機制,用來幫助防範基於 POST 的攻擊。 這個機制的核心就是在 cookie 中設定一個隨機資料,然後把它同表單提交的 POST 資料中的相應值進行比較。

預設情況下,CSRF 防範是禁用的。如果你要啟用它,可以編輯 應用程式配置 中的元件中的 CHttpRequest 部分。

程式碼範例:

return array(
    'components'=>array(
        'request'=>array(
            'enableCsrfValidation'=>true,
        ),
    ),
);

要顯示一個表單,請使用 CHtml::form 而不要自己寫HTML程式碼。因為 CHtml::form 可以自動地在表單中嵌入一個隱藏項,這個隱藏項儲存著驗證所需的隨機資料,這些資料可在表單提交的時候發送到伺服器進行驗證。

Cookie 攻擊的防範

保護 Cookie 免受攻擊是非常重要的。因為 Session ID 通常儲存在 Cookie 中。 如果攻擊者竊取到了一個有效的 Session ID,他就可以使用這個 Session ID 對應的 Session訊息。

這裡有幾條防範對策:

Yii 實現了一個 Cookie 驗證機制,可以防止 Cookie 被修改。啟用之後可以對 Cookie 的值進行 HMAC 檢查。

Cookie 驗證在預設情況下是禁用的。如果你要啟用它,可以編輯 應用程式配置 中的元件中的 CHttpRequest 部分。

程式碼範例:

return array(
    'components'=>array(
        'request'=>array(
            'enableCookieValidation'=>true,
        ),
    ),
);

一定要使用經過 Yii 驗證過的 Cookie 資料。使用 Yii 內建的 cookies 元件來進行 Cookie 操作,不要使用$_COOKIES

// 取出一個名為 $name的cookie 值
$cookie=Yii::app()->request->cookies[$name];
$value=$cookie->value;
......
// 設置一個 cookie
$cookie=new CHttpCookie($name,$value);
Yii::app()->request->cookies[$name]=$cookie;
$Id$