在此章節將會介紹本論文研究的基本背景知識與技術描述,可以分為兩大部分。
首先,我們會介紹常見的網頁應用程式弱點,並以資料庫注入(SQL Injection)和 跨網站腳本攻擊(XSS)這兩個最具代表性的例子說明。接著介紹相關的分析方法,
包含汙染資料流分析、測試案例產生以及剖面導向程式語言的技術。
2-2-1 常見網頁應用程式弱點介紹
下列為 2010 年 OWASP [13] 統計資料顯示前 10 名網頁應用程式的弱點,常見的 弱點都是與未經驗證的使用者輸入有關,以下將介紹前兩個最出名攻擊手法。
A1: Injection
A2: Cross-Site Scripting (XSS)
A3: Broken Authentication and Session Management
A4: Insecure Direct Object References
A5: Cross-Site Request Forgery (CSRF)
A6: Security Misconfiguration
A7: Insecure Cryptographic Storage
A8: Failure to Restrict URL Access
A9: Insufficient Transport Layer Protection
$cmd = “SELECT COUNT(*)” FROM user WHERE name = ‘’ OR 1 = 1 ; AND passwd = ‘’ OR 1 = 1 ;
A10: Unvalidated Redirects and Forwards 2-2-1-1 注入缺失(Injection Flaw)
在此最具代表性的注入缺失為資料庫注入(SQL Injection),以此為例做說明。SQL Injection 的發生在於不被信任的使用者輸入構成了 SQL 的指令,而惡意的輸入 會改變 SQL 指令的原來要做的工作。像是常見的竊取資料庫的機密資訊,或是 毀壞資料庫的內容,下面舉一個 PHP 建立的 SQL 指令。
其中 $name 和 $pwd 這兩個變數的值是由使用者所提供的。正常的 SQL 指 令會比對使用者的輸入是否符合,符合的話就會回傳 1 否則回傳 0。但今天惡 意的攻擊者在$name 和$pwd 的都輸入‘ OR 1 = 1,SQL 指令結果如下。
於是回傳結果為 1 ,攻擊者就成功的竊取所有資料庫的資訊。常見的 SQL Injection 攻擊方法還有像是輸入兩個 hyphen -- 符號,這在 SQL 語法中是作註解 用的,所以攻擊者就可以藉此達到成功的攻擊。
目前用來偵測 SQL Injection 的方法就是去辨別使用者的輸入是否包含有特 殊字元、或是含有 SQL 語法,再做過濾或阻擋的動作。
2-2-1-2 跨網站腳本攻擊(Cross-Site Scripting , XSS)
網頁通常有很多表單欄位處允許使用者輸入資料,再根據這些資料動態地產生新 的網頁。使用者輸入的表單資訊若沒有進一步檢查,就可能因為攻擊者利用惡意 的 script 當作輸入資料而造成 XSS 的發生。假設 <script>alert('Vulnerable')</script>
被當成使用者輸入的資料,沒有過濾的話就會自動地執行 script 語法。在此就會 造成網頁一直跳出”Vulnerable”的警告標示。
$cmd = “SELECT COUNT(*)” FROM user WHERE name = ‘” . $name . “’ ; AND passwd = ‘ “ . $pwd . “’ ;
http://www.trustedsite.com/searchdoc.cgi?file=<script>
windows.open(“http://www.attacker.com/malicious_script.js”)</script>
而 XSS 又可分為兩種形式,舉例來說,第一種 Stored XSS : 就是像是在留 言板或是論壇中輸入 script 的語法的惡意程式碼。如果 server 端沒有過濾過使用 者輸入的內容,就會直接執行攻擊者想要做的事;第二種,Reflected XSS : 在瀏 覽網站時(使用者 log-in 且 cookie 已經被記錄了),此時收到一封 mail(受到 attacker 破壞的 link),點開時會經過使用者將連結傳給伺服器,伺服器以為是使用者傳 入的訊息,而導向 attacker 的惡意網站。下列舉例說明 :
當不知情的使用者點下此 URL,就會執行攻擊者惡意的 script 語法,開啟一 個惡意的 JavaScript。XSS 的攻擊常造成不知情的使用者 Cookie 被竊取的狀況,
攻擊者就能假冒使用者然後直接登入成為合法使用者。
目前 XSS 的偵測方式是檢查使用者輸入是否含有<script>的 tag,或是利用 encoding 的方式,將字元‘<’ encode 成 ‘<’來避免惡意 scripting 的執行。
2-2-2 分析方法
2-2-2-1 汙染資料流分析(Taint Analysis)
網頁中需要使用者輸入的資料是目前造成網頁應用的安全出現漏洞的主要原因,
因此只要是使用者的輸入資料,都視為被汙染資料(Tainted Data )。接著如何紀錄 以及後續的追蹤汙染,就是所謂汙染資料流分析,簡單來說就是在整個網頁應用 程式中追蹤使用者輸入的資料。
Figure 2.9 為說明汙染資料流分析的程式範例。其中主要分成由三個主角,
一、程式來源端(Source),代表接收使用者輸入的函式。只要是從來源端來的使 用者輸入資料都視為被汙染(Tainted)。在此第 2 行 req.getParameter(“name”)就是 一個程式來源端;二、程式接收端(Sink),例如會輸出資料的函式(eg. println)或 是會進入資料庫的函式(eg. SQL query)。在第 11 行 writer.println(s6)為一個程式接
收端;三、傳遞過程(Propagation),負責紀錄程式中間汙染資料流的傳遞過程。
例如資料流動的過程可能經過函式的操作或是 Assignment 動作而造成汙染的傳 遞。如第 2 行來自來源端的汙染資料 assign 給變數 s1,因此變數 s1 被傳遞成為 汙染資料,第 3 行汙染資料 s1 又傳遞給 s2,以此類推。
程式接收端如果包含汙染資料,在輸出到網頁或是進入資料庫內部後,可能 造成網頁應用程式被攻擊或是被竊取資訊。因此,對汙染資料流分析來說,當程 式接收端的資料是被汙染的,代表來源端的汙染資料在經傳遞後到達了接收端。
在此範例中第 11 行接收端的引數變數 s6 為汙染資料,因為變數 s6 是從來源端 的汙染資料所傳遞而來,將此定義為一個網頁應用程式安全弱點。而弱點定義的 精確度跟對程式汙染傳遞分析的能力有關,如果能夠精確判斷傳遞過程,就能做 越精確的弱點定義。目前汙染資料流分析可以分成靜態分析方法[6]與動態分析 方法[4]、[18]兩種類別,無論是靜態或動態在判斷弱點的準確度部分以及涵蓋率 各有其優缺點。
Figure 2.9 An Example for describing Tainted Dataflow Analysis
01 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { 02 String s1 = req.getParameter("name");
03 String s2 = s1;
04 String s3 = s2;
05 String s4 = s3;
06 StringBuffer b1 = new StringBuffer(s4);
07 StringBuffer b3 = b1;
08 String s5 = b3.toString();
09 String s6 = s5;
10 PrintWriter writer = resp.getWriter();
11 writer.println(s6);
12}
Source
Sink Propagation
2-2-2-2 測試為基礎的分析方法
在目前測試方法中,廣泛用來做網頁應用程式弱點驗證為滲透測試方法。產生惡 意的攻擊測試案例,封裝成 Http Request 傳送到網頁應用程式。策是案例攻擊成 功代表造成真正的弱點,就會造成像是整個網頁應用程式癱瘓。測試方法基本上 分成測試案例產生與測試案例執行兩部分,能夠做到自動化產生測試案例並執行 作弱點驗證。但對測試為基礎的方法來說,困難點在於當測試案例產生不夠完整 時,就無法保證測試出程式中所有潛在的弱點。
由於本論文研究與測試案例產生有關,是屬於測試為基礎的方法中白箱測試 的方法。白箱測試擁有程式源碼的資訊,可以利用靜態分析技術找出程式中所有 可執行路徑。再利用自動化產生測試案例的技巧符號化執行(Symbolic Execution),
將程式路徑上真的變數都替換成符號化變數(Symbolic Variable)。以抽象執行取代 實際執行程式的概念蒐集路徑上的限制(Constraint),在配合限制解決(Constraint Solving)解出限制,自動地產生測試案例。
在此說明利用靜態分析產生測試案例所需的背景知識。靜態分析原本為程式 分析中的一種技巧,常見於編譯器用來作程式的優化,在不需要執行程式的前提 下分析程式碼進而取得需要的資訊。其中資料流分析是靜態分析中使用到很重要 分析概念,要做資料流分析我們需要知道程式的邏輯順序。因此,靜態分析以控 制流程圖(Control Flow Graph, CFG)來記錄整個程式中路徑分支的關係。其中控 制流程圖中的節點代表一個基本分析區塊(Basic Block),例如以一個程式語句 (Statement)為單位,節點跟節點之間就代表執行的路徑。根據控制流程圖資訊輔 助,我們能夠藉此對程式進行資料流分析。
控制流程圖是以函式為單位,所以只是分析函式內部控制流程圖,稱為程序 內的分析(Intraprocedural Analysis)。隨著想要得到的資訊不同,分析進行的方向 又可分為 Forward 分析和 Backward 分析。假設我們想要知道在某個程式進入點 的變數是否已經被定義過,我們需要靠 Forward 分析。反之我們想要知道此變數 在未來是否會被重新定義,我們則需要 Backward 分析。至於函式跟函式之間的
資 料 流 分 析 , 我 們 需 要 程 式 呼 叫 圖 (Call Graph) 的 輔 助 以 達 成 跨 程 序 分 析 (Interprocedural Analysis)。有了這些概念後,對於測試案例產生,我們需要利用 資料流分析來找出路徑,才能再進一步的分析無論是程序內部的路徑或是跨程序 的路徑,並進行路徑限制蒐集與解決。
2-2-2-3 剖面導向程式設計(Aspect-Oriented Programming)
剖面導向程式設計是專門處理橫跨性關注(Crosscutting concerns)議題的技術。在 網路應用安全研究中,使用者輸入的資料來源以及接收點在網頁應用程式中可能 分散在各處,要追蹤他們之間的關係其實就屬於一種橫跨性關注的應用。
剖面導向程式設計中最重要的機制就是 Pointcut and Advice 機制,我們利用 Figure 2.10 的例子說明剖面導向程式的 pointcut and advice 機制。其中 pointcut 是用來描述程式中橫跨性關注的所在,在此描述為在 myTest class 下所有呼叫 findMe()的程式所在點(Join Point)。advice 則是當找到符合 pointcut 的程式所在點 就執行我們想要做的事。pointcut and advice 機制在此例子首先找到符合 debugF pointcut 所有的 findMe()函式,由於 advice 是 after 的類型,所以將會在執行呼叫 findMe()之後再去執行 Print 的動作。
Pointcut
Advice
Pointcut debugF() : Call(* *findMe(..))
&&within(myTest.*.*);
after():debugF(){
Print(findMe());
}
void f(){
……
findMe();
……
}
void g(){
findMe();
……
……
}
Join Point
Figure 2.10 AOP pointcut and advice mechanism