2013年7月3日 星期三

網站應用程式安全性風險與因應對策 (Web Application Security Risks and Countermeasures)

由於全球資訊網站的快速擴充成長、具有開放匿名存取以及網頁技術的快速翻新等特性,因此也造就了現今風險性最高的網路服務環境,而近年來駭客對於網站的攻擊手法已大量利用網站應用程式撰寫不當的弱點,因此保護整體網站的安全性工作將不再只是網路工程師、網站管理人員和系統工程師的職責,對於如何撰寫安全性的網站程式碼更是現代開發人員所必需具備與責無旁貸的技能 ,不過對許多程式員而言,使用擅長的程式語言開發出符合功能需求的網站應用程式可能不難,但對於撰寫安全性的程式碼的要求可能就顯得陌生而不太容易,因為大部份的傳統程式員比較少接受這個層面的訓練,作者雖研究資安領域多年,亦較少著墨於此領域的研究,近日基於教學與實務上的需求,隨手將手邊教材整理並撰寫本文用以提供程式員一個了解安全性網站應用程式的學習指引。

網站應用程式的弱點、攻擊及風險

首先,若您想要較全面性的了解目前網站應用程式所面臨的各種威脅、風險以及駭客可能利用的程式弱點及攻擊手法,建議可以參考下列三個組織所公佈、具參考價值與指標的研究報告:

  • OWASP Top 10 Most Critical Web Application Security Risks
  • CWE/SANS Top 25 Most Dangerous Software Errors
  • WASC Threat Classification Enumeration View

底下將這三份研究報告所提出的應用程式弱點或常見的攻擊手法綜合總整如下表所示:

OWASP Top 10 Most Critical Web Application Security Risks OWASP (Open Web Application Security Project)是一個非營利性質的開放社群組織,成立主旨在於研究、協助並制定網頁應用程式的安全標準、工具與技術文件,OWASP機構並根據威脅來源(Threat agent)、弱點的普及性、技術面以及營運面的影響衝擊等多項因素評估並發布 OWASP Top 10。目前許多檢測工具都已經將 OWASP Top 10 列為基本的檢測項目
  1. 注入攻擊 (Injection)
  2. 失效的驗證與連線階段管理 (Broken Authentication and Session Management)
  3. 跨網站指令碼攻擊(Cross-Site Scripting;XSS)
  4. 不安全的物件參考(Insecure Direct Object Reference)
  5. 不當的安全性組態設定 (Security Misconfiguration)
  6. 敏感性資料外洩 (Sensitive Data Exposure)
  7. 遺失功能層級存取控制 (Missing Function Level Access Control)
  8. 跨網站偽造請求 (Cross-Site Request Forgery ;CSRF)
  9. 使用已知弱點的元件 (Using Known Vulnerable Components)
  10. 未驗證的重新導向與轉發 (Unvalidated Redirects and Forwards)
CWE/SANS Top 25 Most Dangerous Software Errors CWE (Common Weakness Enumeration) 是由MITRE組織所資助的軟體社群專案,專案目的在建立軟體弱點的類別與目錄並藉以建立自動工具來協助辨識、修補和避免產生這些弱點,而SANS (SysAdmin, Audit, Networking, and Security) 則是另一個資訊安全教育訓練、認證的研究性組織,而CWE/SANS Top 25 Most Dangerous Software Errors就是由 MITRE 和 SANS 這二個組織合作所共同發布的全球最常見可招致嚴重弱點的軟體錯誤。
  1. 元件間不安全的互動(Insecure Interaction Between Components):使用不夠安全的方式在不同元件、模組或程序間傳遞資料:
    SQL注入
    OS 命令注入
    跨網站指令碼
    ◆ 沒有限制危險類型的檔案上傳
    ◆ 跨網站偽造請求 (Cross-Site Request Forgery ;CSRF)
    ◆ URL重新導向至非信賴的網站
  2. 有風險的資源管理 (Risky Resource Management):軟體沒有正確的管理重要系統資源(如CPU、記憶體)的配置、使用、傳遞與釋放而導致的弱點 :
    ◆ 緩衝區溢位 (buffer overflow)
    ◆ 瀏覽與造訪路徑 (Path Traversal)
    ◆ 下載程式碼時未做完整性檢查
    ◆  網頁內包含了非信任及非控制範圍的功能
    ◆  使用有潛在有危險性的函式
    ◆  緩衝區大小的計算不正確
    ◆  未控制字串的格式
    ◆  整數溢位或越界繞回 (Overflow or Wraparound)
  3. 可滲透的防禦 (Porous Defenses):誤用、濫用與輕忽防禦技術所導致的弱點
    ◆  重要功能缺少了驗證
    ◆  缺少存取控制或授權
    ◆  將驗證的機密性資料直接寫入在程式碼內(Hard-coded Credentials )
    ◆  敏感性資料未加密處理
    ◆ 
    使用不可信任的用戶輸入
    ◆  允許未經授權的執行
    ◆  不正確的存取控制或授權

    ◆  使用的瑕疵不夠安全的的加密演算法
    ◆  沒有適當的限制不斷的驗證企圖
    ◆  雜湊加密時未加上salt搗亂(Hash without a Salt)
WASC Threat Classification Enumeration View WASC (Web Application Security Consortium) 由許多資訊安全的專業人員及公司所組成的專門研究網站安全的聯盟,其將網站的安全威脅進行分類,共分成 34 種攻擊威脅。 攻擊方法:
  • 功能的濫用(Abuse of Functionality)
  • 暴力破解攻擊 (Brute Force Attack)
  • 緩衝區溢位 (buffer overflow)
  • 內容欺騙(內容欺騙)
  • 認證與工作階段辨識碼的預測(Credential/Session Prediction )
  • 跨網站指令碼攻擊(Cross-Site Scripting)
  • 跨網站偽造請求 (Cross-Site Request Forgery)
  • 阻絕服務 (Denial of Service)
  • 指紋 (Fingerprinting)-探索與辨識
  • 格式化字串攻擊 (Format string)
  • HTTP回應偷渡(HTTP Response Smuggling)
  • HTTP回應分割攻擊(HTTP response splitting)
  • HTTP請求偷渡(•HTTP Request Smuggling)
  • HTTP請求分割攻擊(HTTP request splitting)
  • 整數溢位 (Integer Overflows)
  • LDAP注入攻擊(LDAP Injection)
  • 郵件命令注入 (Mail Command Injection)
  • 空字元注入(null byte injection)
  • 未經授權執行OS命令 (OS Commanding)
  • 瀏覽與造訪路徑 (Path Traversal)
  • 重新轉送資源位置 (Redirectable Resource Location)
  • 遠端檔案含入(Remote file inclusion)
  • 路由迂迴攻擊 (routing detour attack)
  • Session固定攻擊 (session fixation)
  • SOAP  陣列濫用 (SOAP Array Abuse)
  • SSI 注入攻擊 (Server-side Include Injection)
  • SQL 注入攻擊 (SQL Injection)
  • URL Redirector Abuse (URL重定導向濫用)
  • XPath 注入攻擊
  • XML屬性爆毀 (XML Attribute Blowup)
  • XML 外部實體攻擊 (XML External Entities)
  • XML 實體擴展 (XML Entity Expansion)
  • XML注入攻擊 (XML Injection)
  • XQuery 注入攻擊 (XQuery Injection)

脆弱點 (Weakness):

  • 應用程式組態設定不當(Application Misconfiguration)
  • 目錄索引 (Directory Indexing)
  • 不當的檔案系統使用權限(Improper Filesystem Permissions)
  • 不當的輸入處理 (Improper Input Handling)
  • 不當的輸出處理(Improper Output Handling)
  • 資訊外洩 (Information Leakage)
  • 不安全的索引 (Insecure Indexing)
  • 應用程式不足以因應自動化攻擊(Insufficient Anti-automation)
  • 驗證不足 (Insufficient Authentication)
  • 授權不足 (Insufficient Authorization)
  • 密碼還原機制不夠安全 (Insufficient Password Recovery)
  • 應用程式流程驗證與控制不足 (Insufficient Process Validation)
  • Session 過期弱點(Insufficient Session Expiration)
  • 傳輸層保護不足(Insufficient Transport Layer Protection)
  • 伺服器設定不當 (Server Misconfiguration)

 

上面三份研究報告的分類或歸類方法雖是不同、但許多揭露出來的軟體安全性問題卻是如出一撤,若仔細分析,許多網頁應用程式的弱點與風險並非獨立,可能互為因果或強化之關聯性,而現代的駭客也經常能夠整合數項弱點而形成另一可攻擊利用之途徑,另外,值得留意之處為網站應用程式風險並非全然是開發人員的責任,系統維護人員、資料庫管理人員、網路工程師在不同的風險項目中均需擔負著不同的責任。

本文整合並比對上述三篇報告之共通性與衝擊性之後,針對目前最廣泛為駭客所利用的網站應用程式弱點之攻擊方法,逐一說明其發生的成因、影響範圍並提供基本的因應對策:

  1. 注入問題 (Injection)
  2. 跨網站指令碼攻擊(Cross-Site Scripting;XSS)
  3. 跨網站偽造請求 (Cross-Site Request Forgery ;CSRF)
  4. Session 使用及管理的疏漏
  5. 重新導向的安全性問題
  6. 驗證與授權的安全問題

壹. 注入攻擊問題 (Injection Attack)

注入攻擊可說是目前最普遍的網站應用程式的攻擊手法,此類型的攻擊發生在有心人士將惡意企圖的指令碼送至某特定直譯器或剖析器以作為命令或查詢的一部分,並且能夠成功欺騙直譯器來執行未經授權的命令以達成其竊取、篡改或破壞資料的目的,若進一步探討注入攻擊之所以會發生的原因通常在於原本預設為「資料」的位置,被它人使用「分隔符號」或「結尾符號」來改變字串結構而導致可以執行未經授權的指令,這些常被駭客利用來做為注入攻擊的分隔、結尾或串接符號如下表所示,

注入類型 利用介面 攻擊方法 分隔、結尾或串接符號
SQL 敘述注入 SQL 安插SQL命令 -- '
OS 命令注入 OS Shell 執行系統命令 ;| &
HTTP 注入 HTTP HTTP回應標頭 換行符號
跨網站指令碼 HTML 插入JavaScript程式碼 < "
郵件命令注入 SMTP格式訊息或命令 注入非法的郵件標頭或本文 換行符號
XPATH注入 XPATH 注入XPATH查詢命令 '

網站應用程式的注入攻擊可能發生在SQL、OS 、 HTTP、XML、XPATH、LDAP、郵件命令等服務或協定層面上,而其中又以SQL和OS 命令的注入攻擊最值得留意,因此底下特別針對此二項注入攻擊來詳加說明。

一. SQL 注入攻擊

SQL Injection是發生在應用程式資料庫層級的安全性漏洞攻擊,其發生原因是在使用者輸入的字串之中夾帶了SQL指令,並且在設計不良的程式中忽略了字串檢查,因此夾帶進去的指令就會被資料庫伺服器誤認為是正常的SQL指令而執行,而招致資料外洩、竄改或刪除等破壞行為。

SQL_inj1

SQL 注入攻擊的範例與影響

底下舉三個例子來說明SQL攻擊的情境、做法及可能產生的衝擊,這些SQL注入攻擊成功後導致的影響層面可謂相當廣泛,包括了:

  • 規避身份驗證機制
  • 資料庫資料外洩
  • 篡改資料庫內容
  • 執行未經授權的程式

第一個範例說明了駭客在登入驗證畫面輸入時利用了一些SQL敘述的特殊字串(')和合法命令(OR)以規避正常的驗證過程而導致能夠非法登入成功。

SQL_inj2

其次,SQL 注入攻擊亦可能在資料庫權限與存取控制不當的漏洞也存在時導致更嚴重的後果,例如資料可能會被不當刪除或非法執行惡意指令,譬如下圖顯示了SQL注入攻擊可能導致被它人刪除資料庫表格:

SQL_inj3

最後,第三個範例則讓它人在搜尋輸入欄位中執行預存程序xp_cmdshell而招致arp下毒攻擊的發生。

SQL_inj4

由上面三個範例可知,如果網站應用程式存在SQL注入上的弱點,則可能導致資料洩漏、遭竄改刪除、驗證授權失效等各種結果,其影響衝擊之範疇廣泛而嚴重,是屬於高風險的弱點,必需謹慎加以因應。

SQL 注入攻擊因應策略

由上述的例子已知,SQL注入攻擊可以洩漏、修改或刪除資料庫內的資料,因此是非常危險的威脅,一旦開發人員撰寫網站程式碼的資料庫連線或呼叫方式不當時,即可能被駭客利用來攻擊,若再加以資料庫結構資訊外洩或授權不當更可能引發嚴重的後果。

探求SQL 注入攻擊之所以會發生的主要原因在於有心人士扭曲了開發者原意設計之外的形式而蓄意改變了SQL敘述句來產生額外的攻擊效果,因此程式員為了避免程式遭受SQL注入攻擊,其首要的因應原則應該是撰寫安全性的程式碼,亦即沒有SQL注入攻擊可利用之程式碼。

1. 撰寫安全性程式碼

  • 採參數化查詢(Parameterized Queries )、占位置(Placeholder)、繫結變數 (Bind variable)方式建立SQL敘述句
    這種方法在資料庫引擎將值予以綁定,保留的位置只會儲存給定型態的值而非任意SQL片斷敘述,因此SQL注入攻擊將會被視為一個奇特或無效的參數值而不會被執行。 換言之,這種預備的SQL敘述 (Prepared statement)可以視為SQL敘述的範本(template for SQL statement),許多語言使用疑問符號(?)來做為SQL敘述中將被插入真正值的位置,下圖為靜態佔位置的綁定做法,首先是將加上PlaceHolder的SQL敘述送至資料庫引擎編譯準備完成,然後再將綁定值送入已編譯準備好的SQL敘述來執行。
    SQL_inj5
    底下則示範了php程式碼的placeholder撰寫例子,如果有心人士於二個輸入欄位分別輸入 admin'  or 1=1--和test,則查詢的結果將成為較安全的SQL敘述如下,其中二個綁定位置的輸入值均是無害的字串而不會存在可執行命令:
    SELECT * FROM Users WHERE Username = 'admin'' or 1=1--' AND password = 'test'
    <form method="post" action="injection.php" enctype="multipart/form-data" >
    Username:<input type="text" name="Username" id="Username"/></br>
    Password:<input type="text" name="Password" id="Password"/></br>
    <input type="submit" name="submit" value="Submit" />
    </form>
    <?php
    $params = array($_POST['Username'], $_POST['Password']);

    $server = "MyServer\sqlexpress";
    $options = array("Database"=>"MyDB", "UID"=>"MyUID", "PWD"=>"MyPWD");
    $conn = sqlsrv_connect($server, $options);
    $sql = "SELECT * FROM Users WHERE Username = ? and Password = ?";
    $stmt = sqlsrv_query($conn, $sql, $params);

    if(sqlsrv_has_rows($stmt))
    {
    echo "Welcome.";
    }
    else
    {
    echo "Invalid password.";
    }
    ?>
     
  • 輸入資料檢查(input validation)
    程式員對於用戶端輸入的資料均須視為不可信賴、不能直接接受使用,因此需做好所有資料輸入的檢查,即執行輸入的篩選過濾工作,而輸入篩選方式有二:
    白名單: 過濾輸入字串時檢查是否均是「只允許」的清單字元,禁止清單中不存在的字元出現。一般程式語言只要熟悉並利用正規表達(Regular Expression)方式就可簡單的建立輸入白名單檢查機制。
    黑名單: 過濾輸入字串時檢查是否存在「不允許的」的字元以杜絕非法字元或關鍵字。 SQL Injection的黑名單主要排除有風險的字元和SQL關鍵詞(如:' - ; select insert drop delete AND OR ….)。
    特別值得留意的是這項檢查工作應該放在伺服端執行,而非用戶端,否則可能會被駭客繞過而沒有執行。
  • 程式碼需進行黑箱與白箱測試
    網站應用程式之風險性較高,因此程式撰寫後應實施安全性測試,這包括了黑箱(blackbox)與白箱(whitebox)測試,這原應該屬於開發測試階段的一環,而程式員本身亦可利用一些簡易的工具來替自己撰寫的程式做一初步的掃描檢測是否在SQL 注入的漏洞,例如Firefox 的 "SQL Injection ME"附加元件就很適合一般程式員小程式的檢測使用。

最度強調:撰寫安全性程式碼無非是防範各種注入攻擊手法最有效的根本策略與原則,最為重要,不過若能搭配底下的因應原則有助於更進一步降低SQL 注入攻擊的風險,並且在軟體本身有問題時可減輕被攻擊的損害,所以建議應該做為輔助的因應策略。

2. 嚴格限制應用程式存取資料庫的權限並定期檢視權限設計是否符合最低權限賦予(least privilege)原則。

3. 關閉或自訂伺服器與資料庫的錯訊息通知,抑止詳細的錯誤訊息,避免洩露可被它人利用入侵的資訊。

二. OS 命令注入攻擊

幾乎所有用來開發網站應 用程式的語言均提供了透過Shell呼叫OS指令的功能,一旦呼叫Shell的功能用法不夠謹慎,就可能讓非預期的OS指令能夠被執行,這就形成了OS命令注入攻擊的原因, 因為攻擊者會企圖非法植入並執行任何系統指令,甚至可從外部下載工具執行之,因此這也是種非常危險的攻擊方式,開發網站程式時絕對要避免產生OS命令注入的弱點。

例如下列的php程式碼乃是使用shell_exec函數,透過系統shell來執行cat指令與GET取得的參數並顯示字串輸出,用戶可利用下列URL存取此網頁-- "http://……../filecontent.php?filename=myfile.txt" URL:

<?php
echo shell_exec('cat '.$_GET['filename']);
?>

上述的程式碼最易遭受OS命令注入攻擊,因為攻擊者只要簡單的加上分號(;)並尾隨另一個UNIX命令即可產生攻擊,例如利用下列URL即可能可以顯示未經授權的訊息:

"http://……../filecontent.php?filename=myfile.txt;ls;ifconfig"

由上面的例子和經驗,大抵可推論出滿足OS命令注入攻擊的條件通常有三項,因此只要能夠避免這三項潛在的弱點即可避開命令注入攻擊:

  1. 程式中利用Shell呼叫功能的函數(例如 system、exec)
  2. 把參數交給Shell呼叫功能的函數
  3. 透過Shell呼叫OS指令時,沒有跳脫Shell 上具有跳脫意義的字元(例 & ; | )

OS 命令注入攻擊因應策略

由上述的說明已經得知,網站應用程式中若使用直接到呼叫OS命令的函數,而此種類的呼叫參數又沒有經過完整檢查,就容易造成OS命令注入的攻擊,所以避免發生此種類型的攻擊,其主要的因應對策如下表所示:

  • 避免程式中使用具有Shell呼叫功能的函數
例如 php語言的 system()、exec()與 passthru();Perl語言的exec()和system()函數
  • 禁止將來自外部的參數交給具有Shell呼叫功能的函數
當一定要使用透過Shell呼叫功能的函數時,只要避免直接將參數交給Shell指令列就可以避免OS命令注入弱點。
  • 利用安全的函數來跳脫交給OS指令的參數或是驗證參數
如果上述二種對策均無法使用時,此時就需要跳脫傳遞給Shell函數的參數,例如php可以使用escapeshellarg,另一個較好的方式為對於來自外部的輸入值均行參數驗證。
  • 設定應用程式執行者使用最低的權限
由於命令指令的執行權限就是網站應用程式所擁有的權限,因此只要限制程式只能擁有最低執行權限或範圍即可以將損害降至最低,因為對於特權才能執行的命令將會被拒絕執行。

貳. 跨網站指令碼攻擊 (Cross-Site Scripting;XSS)

跨網站指令碼攻擊通常簡稱為XSS,不使用簡稱CSS是為了避免與層疊樣式表(Cascading Style Sheets;CSS)產生混淆。

XSS攻擊乃是駭客企圖傳送未經驗證的資料到網路瀏覽器而導致瀏覽器執行了惡意的程式碼。換言之,XSS攻擊利用了動態網頁的特性以及開發人員未能夠嚴格限制使用者輸入,也沒有過濾使用者輸入與查詢字串,以致於讓所用戶輸入的惡意指令碼得以在其它使用者的瀏覽器上執行而造成權益受損。 XSS的弱點是由HTTP回應中包含未經驗證資料的程式碼所引起的

XSS 類型

若根據攻擊用的指令碼之位置的不同可將XSS的攻擊類型分成反射型(Reflected XSS)和儲存型(Stored XSS)二種,此外,還有另一種針對DOM(Document object model)技術使用時未能夠有效的輸入驗證之弱點所進行的XSS攻擊。

反射型(Reflected XSS)
  • 又稱為非持續性(Non-persistent),為最普遍的XSS攻擊類型 ,當攻擊用的指令碼並非在目標網站本身內而是在攻擊目標網站之外的其它位置(如陷阱網站或郵件URL)就屬於本類型的XSS攻擊。
  • 反射型 XSS案例中,不可信賴的來源通常為網頁要求,亦即常來自於受害用戶端使用了一個有問題的URI (例如HTTP的查詢參數或HTML的表格提交)所導致 ,因此攻擊發生在受害者開啟了別人發送帶有惡意程式碼參數的URL,而讓特有的惡意程式碼參數被HTML解析並執行之。
  • 它的特點是非持久化,必須用戶端點擊了帶有特定參數的連接才能引起。
持續型(persistent) XSS
  • 又稱為儲存性 XSS (Stored XSS)攻擊,因為注入的程式碼會被儲存在網站的伺服器(如資料庫)
  • Stored XSS案例中,不可信賴的來源通常為資料庫或其他後端資料儲存區。
  • 當其他用戶正常瀏覽網頁時,網站從資料庫中讀取了非法用戶存入的非法資料,惡意程式碼因此被執行
  • 這種攻擊類型常在留言板等地方出現
DOM 為基礎的 XSS  (DOM-based) 網頁程式本身包含一些DOM(document object model)對象的操作,如果未對輸入的參數進行處理,可能會導致執行惡意腳本

下圖則顯示了持續型XSS攻擊的流程與情境,攻擊者在網頁輸入欄位內(如留言板)刻意安插指令碼,由於網站應用程式存在弱點所以將此輸入儲存在伺服器內,日後當其它用戶瀏覽到這個存有惡意指令碼的頁面時,就可能在瀏覽器執行指令碼而受害。

xss2

XSS攻擊因應策略

由上面的範例與說明可知,造成XSS弱點的主要原因在於產生HTML時並沒有正確操作在HTML語法上具有特殊涵義的符號字元,因此為了避免開發人員原意之外的指令或標籤被注入,而改變了HTML的原意形式而形成了XSS的攻擊,您 必需進行特殊字元與符號的跳脫或編碼處理。再者以白名單方式的過濾輸入字串亦是另一個編碼外的額外保險策,有效的XSS攻擊防範策略說明如下表:

HTML需以跳脫或編碼機制做為XSS的基本對策
  • HTML在元素內容插入未可信賴的資料之前,需先進行跳脫編碼,如此一來,來自於使用者輸入的字串或其它可疑來源字串將轉換成為單純的文字,不會包含可於瀏覽器上執行script程式
  • 實務上,元素內容內的『<』、『&』符號一定要跳脫而還原字元涵意,其餘如『>』、『"』、『'』、『/』字元符號也建議實施跳脫。
    &  ---> &amp;
    <
      --->  &lt;
    >  --->  &gt;
    "  --->  &quot;
    '  --->  &#x27;    
    /  --->  &#x2F;
  • 屬性值必需以雙引號加以框住。
  • 實務上,許多網頁程式語言提供了函數可以協助處理跳脫或編碼,如php語言可以利用htmlspecialchars函數,perl語言可以利用CGI.pm的escapeHTML方法、ASP的Server.HTMLEncode()以及ASP.NET的Server.HtmlEncode()均屬之
輸入值的驗證(Input Validation) 雖然對於輸入值的驗證也可做為XSS的一種對策,但通常只有在輸入值限定為英數字元的情況下可為有效的對策,若是自由格式的輸入欄位並不適合以此法做為主要對策,因為會有太多漏洞。
cookies設定HttpOnly屬性 這個屬性將會禁止以Javascript讀取cookies,這將有功於防範常見的Cookie hijacking 這種類型的 XSS 攻擊手法
採用可避開XSS攻擊的程式庫或應用程式框架 較著名的包括了 Microsoft's Anti-XSS library、 the OWASP ESAPI Encoding module或 Apache Wicket。

總之,XSS防範基本策略應先針對用戶輸入進行跳脫編碼,以便讓可能造成危害的資料變成無害資料,再對輸入的資料予以過濾以針對可疑的資料進行防範,如此一來,XSS攻擊將無法生效。

參. 跨網站偽造請求 (Cross-Site Request Forgery ;CSRF)

跨網站冒名請求通常是由網路的使用者在成功登入網站後,在不知情的情況下,被有心人士誘騙而向其連線網站傳送一個未經授權的命令而導致權益受損,入侵者實施CSRF攻擊手法主要是用以假冒它人名義來向其信任的網站執行不被許可及未經認可的指令動作。 CSRF這種攻擊主要有三個步驟,首先,受害者成功登入某特定的網站,其次,攻擊者攻擊者必需產生一個惡意的請求來並誘使受害使用者執行,通常可能是利用預先設計好的陷阱網站讓用戶點擊CSRF連結,最後,由於網站沒有重新確認此偽造的請求是否是由合格的用戶所送出,因此網站接受此冒名未授權的請求而導致意外。

 

csrf1

CSRF攻擊的衝擊與影響

CSRF攻擊可能帶來的傷害與影響包括了:

  • 假冒使用者身份在網站上購物、下單
  • 假冒使用者身份在留言板上發文
  • 假冒使用者身份進行帳戶處理
  • 變更使用者會員資料(如密碼或電子郵件位址)
  • 在網路銀行上進行授權的冒名交易

CSRF 攻擊因應策略

為了防範CSRF攻擊,網站必需在進行重要處理與交易的請求之前確認請求是否來自於合格的用戶,因此,原則上需先區分並列出需要CSRF對策的網頁程式,再針對這些程式頁面實作確認的工作,而判斷與確認是否為合格用戶的請求之具體方法以及降低CSRF攻擊的方法有下列數種:

嵌入機密資訊 (Token)
  • 使用者每一次請求時,都必須要傳回一個經由網站系統所雜湊出來的亂數,以作為確認是否為合格的用戶請求。
  • Token最簡單且安全的實作方式就是使用Session ID做為Token
  • 接受token的請求必需使用POST方式傳送
  • 下列為嵌入及確認Token的php簡單程式片斷:
    ==============================================
    <form action="transfer.php" method="post">
    <input type="hidden" name="token"
    value="<?php echo htmlspecialchars(session_id(),ENT_COMPAT,'UTF-8'); ?>">
    .......
    </form>
    ==============================================
    session_start();
    if (session_id() !== $_POST['token']) { ERROR}
    ==============================================
交易前要求重新輸入密碼 每次重要交易前要求使用者重新輸入密碼來確認是否真的為合格的用戶請求
檢查 Referer值
  • 由於合格用戶真正請求和CSRF請求的Referer欄位內容會不一樣,因此藉由檢查Referer可判斷是否為合格的用戶之請求。
  • 檢查Referer時需要檢查URL絕對網址,連同名稱後面的斜線一併檢查,才不會產生漏洞。
  • 有些用戶可能設定停止傳送Referer(例如利用防火牆或瀏覽器附元件)或有些手機的瀏覽器原本就不會傳送Referer,這將造成無法有效的執行請求,即使他們是合格的用戶請求。
在執行重要交易後寄送通知郵件給用戶所登錄的郵件位址 這種方法雖然無法避免CSRF攻擊,但至少可以讓使用者有機會儘早查覺是否已遭受到CSRF攻擊,可以降低損失。

肆. HTTP Session 使用及管理的疏漏

網站應用程式通常使用Session 管理機制來維護目前程式的各種狀態,例如HTTP的工作階段(Session)乃是透過Session ID來加以辨識,而一個SessionID其實是一個執行時期所產生的虛擬隨機數,Session ID通常可以儲存在cookies、表格欄位或URL 。

若有心人士得以取得使用者連線網站的session ID時,該使用者的身份即可能就冒用,而造成各種嚴重後果,衝擊包括可以瀏覽使用者的重要資料、執行具有使用者才有的權限動作、利用使用者ID傳送郵件、留言或變更設定等。

根據近年來的資安經驗顯示,有心人士欲取得使用者Session ID的手法主要有三:

推測 SessionID Session ID的產生方式不適當時,就可能被有心的第三方推估得知,而能夠進行Session 劫持。
竊取 Session ID 竊取 Session ID 的可能手法:
◎ 從網路上竊聽 Session ID
利用XSS的弱點
Session ID 若存放在URL時,可由Referer標頭洩漏
產生Cookie時由於屬性疏漏弱點而洩漏
強制固定 Session ID 駭客誘使某用戶登入並使用所指定的Session ID於網站上有效的使用

Session ID 保護策略

因此,就網站開發人員而言,為了避免有心人士取得SessionID的各種手法,安全的使用Session ID之條件和因應策略為:

第三者無法推測session ID 建議儘量使用各種開發架構(J2EE、ASP.NET、PHP)所提供的內建Session ID產生管理方式,而不要自己產生Session ID ,因為這些內建的Session ID具隨機性和相足夠長度而不易被推測。
第三者無法竊取session ID
  • 避免將Session ID嵌入到URL中,因為可能經由Referer標頭而讓SessionID洩漏 (

  • 只將Session ID儲存在Cookies中。

  • 設定正確的Cookies安全性相關屬性

    • Secure:只在SSL下傳送Cookie
    • HttpOnly:所指定的Cookie將無法被JavaScript存取。
    • Expires:指定Cookie值的有效期限
    • Domain:原則上不建議設定Cookie的Domain值。
第三者無法強制Session ID (Avoid Session Fixation Attack)
  • 程式需要在登入驗證後立即變更Session ID,讓攻擊者無法知道登入後的Session ID。

伍. 重新導向(Redirection)的弱點問題

許多網站應用程式均會利用重新導向連結到外部的網址,但是如果網站應用程式可以接受使用者控制輸入,而此輸入是用以連結到外部的URL,這恐將導致許多不同類型的攻擊,因為攻擊者將有機會設計並引誘使用者導向一個有惡意企圖的網址,譬如聲名狼藉釣魚網址(phishing)的攻擊即是惡用網址重新導向的例子。

下圖說明了一個利用電子郵件假造連結的釣魚網址,藉以誘騙用戶點擊以導向至此有問題的網站。

redirect2

一般網站應用程式會產生開放性重新導向(導向任意網域)的弱點主要原因有二點:

  1. 可以接受從外部指定重新導向的URL
  2. 沒有檢查重新導向目地的之網址

重新導向弱點之因應策略

重新導向弱點最大的風險在於能夠讓攻擊者可將受害用戶導向至釣魚網站或惡意網站,因此基本防範策略為:
  • 如果網頁能避免使用redirect或forward,那就盡量少用
  • 若一定需要使用,則盡可能不要將使用者輸入的參數作為要導向或前往頁面的URL值。
    原則是儘量固定重新導向標的URL,下圖顯示了程式中如何固定導向的URL值之撰寫方式以取代有潛在重新導向弱點的程式碼。
    redirect1
  • 另一個有效避免導向弱點的方法是維護一份所有重新導向的有效URL之清單,因此若需要轉向時不再傳遞目的URL做為導向參數,而是傳遞清單內正確URL的索引值,如此亦可避免它人指定任意的URL,消除了開放式重新導向的弱點,此種做法也實現了重新導向的白名單做法,而將信任URL或網域排除在外。
  • 若無法避免此種不安全的轉向方式,則必需驗證與檢查使用者輸入的參數。
    檢查所有要導向或前往的頁面的URL,而這些值是根據外來的參數作為其值,例如用GET方式傳遞參數。 不過檢查轉送的URL容易出現漏洞,所以通常只做為輔助策略,而非唯一或主要因應策略。
  • 所有轉向網址之前均需強制通知用戶其瀏覽器即將離開目前網站,並提供用戶確認功能 。

陸. 驗證與授權的安全問題

從OWASPTop10、CWE/SANS Top 25 或WASC Threat Classification 三份研究報告中,有許多安全性問題均是牽涉到網站資源的驗證(Authentication)與授權(Authorization)安全性功能之缺乏、不足或不正確而導致的安全性問題。

身份驗證在於確認您是誰(who are you),登入者是是否真的為其所宣稱之ID(使用者名稱或郵件位址),而授權(存取控制)則是確認已身份驗證者是否可以存取哪些資源以及如何存取(what you are authorized to do),而為數不少的網站資安意外導源於驗證與授權機制之設計實作錯誤、不足與疏忽所導致。

常見的網站程式授權失效的例子包括:

  1. 變更資源的ID就能夠存取設計者意料之外的資源
    在URL列中使用資源的ID為參數參考特定資源是常見的實作方式,但有時候只要程式撰寫或資源控制稍有疏忽就可能讓有心人士僅需變更資源的ID就可能瀏覽到其它未經授權的資源。
  2. 只依賴操作介面的顯示/隱藏功能來進行存取控制
    另一種常見的授權失效例子則是應用程式僅靠介面上的顯示或隱藏選單項目或連結方式來控制存取亦會導致問題,因為只要有心人士能夠成功推測所隱藏的連接或選單項目名稱,則不論是採用GET查詢字串或POST方式來請求均可能遭到未經授權存取的資安意外。
  3. 在hidden參數或cookie中儲存權限資訊
    授權控制不當的例子還常發生在程式中透過hidden參數或cookie來儲存與記錄權限資訊,例如只要在cookie中記錄role=admin即可存取管理員專屬的頁面資料與功能,因此若再加上cookie的產生與維護不當,就可能產生惡用授權的例子。

網站產生了驗證與授權的弱點之原因和責任歸屬經常牽涉到多種不同層級的人員,因此唯有從系統人員管控好檔案系統安全性、伺服器管理員設定正確的網頁資源存取權限、資料庫管理人員設定正確的資料庫表格、欄位、預存程序的存取權限,再加上程式人員撰寫所有特權功能的驗證與授權檢查程式碼才能夠儘量降低這一個層面的風險,根據CWE/SANS的建議之基本因應原則包括:

  1. 為了防止只要變更URL、hidden參數或cookie就能夠不當的惡用權限,因此必需將權限資訊儲存在session變數中以防止被改寫,並且在處理與顯示資料之前確認身份與權限。
  2. 所有網站資源(檔案、目錄、資料庫)應做好最低權限授予原則(Least Privilege)的權限控管並定期重新檢視其正確性。
  3. 大型網站建議將網站應用程式依其力功能性分成匿名(anonymous)、正常(normal)、特權(privileged)和管理等不同的功能區域,並且在提供功能函數前務必先進行角色為基礎(Role-based)的驗證與授權檢查。

網站應用程式防火牆 (Web Application Firewall;WAF)

教育並要求開發人員撰寫安全性程式碼絶對是避免應用程式弱點被利用的最佳實務策略,因為如果撰寫的應用程式無可被利用之弱點,自然就不會發生此等類型的攻擊,但如何撰寫安全性的程式碼並不是件容易的工作,因為大部份的程式員可能都沒有完整的受過如何撰寫安全性程式碼的訓練,再加上許多公司目前可能已經存在為數眾多有瑕疵的網頁,要程式員回頭一一檢視修改先前有安全性問題的網頁恐曠日費時而事倍功半,因此另一個防範程式弱點被惡用的策略即是部署網站應用程式防火牆(Web Application Firewall;WAF)。

顧名思義,網站應用程式防火牆就是一種用來保護網站應用程式不被它人惡用其存在之弱點,而招致網站入侵的防火牆類型。WAF實務上可能是一部硬體裝置、也可能是伺服器附加元件或篩選器,透過一群預先建立好的規則來對HTTP的請求進行篩選動作,將有問題(特別是攻擊性)的網站請求予以辨識並過濾掉,因此WAF通常需要部署在網站應用程式接受連入之前,如此對於任何存取應用程式之請求,可經由它來進行分析、辨識與過濾工作,一旦確認這個存取動作是正常合法而無惡意企圖者才會放行,因此WAF的部署透過適當的規則或特徵偵測比對,將可以阻擋SQL Injection 、跨網站指令碼以及各種輸入竄改、HTTP標頭竄改等針對網頁應用程式弱點的攻擊,即使在網頁應用程式無暇修改的情況下,WAF也能做好把關的動作,確認80埠進來的動作是合法而安全的。

waf1

不過商業性的WAF產品(Fortinet、F5、Barracuda)通常價格昂價,對許多中小企業而言其購置之成本負荷過高,而新版本的網站服務為了防範網頁應用程式弱點的攻擊,大多已經開始提供類似WAF的篩選機制,重要者如IIS 7/8的要求篩選(Request Filtering)元件以及 Apache網站的 mod_security 模組,所以若基於成本上的考量,可以直接在網站服務上安裝並設定要求篩選或mod_security模組的規則,將有效的提供網站應用程式安全性的另一層保護。

底下二張圖分別簡單的示範了如何在IIS上建立適當的要求篩選規則來過濾含有SQL 注入攻擊風險的HTTP請求以及如何使用mod_security 模組防範XSS攻擊。

requestfilter

mod_security

結語

全球資訊網服務的攻勢手法可能利用自網路傳輸、系統上或網站伺服器本身的弱點,但毫無疑問,網站應用程式的弱點才是目前最廣泛為駭客利用藉以攻擊的主要來源,因此企業組織為了降低網站的網路存取風險並且確保網站的安全性,已不單是網路工程師或系統管理員的責任,網站程式相關的開發相關人員,包括規劃人員、程式撰寫者及測試人員也需要在安全性上擔負更關鍵與積極的角色與責任,換言之,應用程式開發需從設計階段開始即已著重安全性的設計(Security by Design)、要求程式人員撰寫安全性的程式碼(code security),而測試人員亦需要針對應用程式進行安全性的黑箱測試與白箱測試,亦即整個開發的生命週期均需導入安全性的思維及控管機制,如此一來才能夠降低網站應用程式的使用風險。

最後,為了確保企業網站的整體安全性,更需有效的整合各種網路防禦技術(如防火牆、入侵防禦系統、TLS/SSL)、系統安全性技術(驗證、授權、稽核記錄、有效更新)、資料庫安全性技術並要求撰寫安全性程式碼才能達成降低網站整體風險至可接受程度的目標。