張甫華
(四川大學(xué)計算機學(xué)院,成都610065)
近年來,人機界面在各種系統(tǒng)中占比越來越大,在一些系統(tǒng)中用戶界面設(shè)計甚至占據(jù)整個系統(tǒng)開發(fā)量的一半以上[1]。由此可見,對于用戶來說用戶界面就是整個軟件系統(tǒng)[2],用戶界面設(shè)計的質(zhì)量會直接影響產(chǎn)品的用戶體驗。而在人機交互界面設(shè)計當(dāng)中對輸入數(shù)據(jù)進行驗證占據(jù)著重要的一環(huán)。軟件能夠正常工作的關(guān)鍵就是要求數(shù)據(jù)的潔凈[3],在處理數(shù)據(jù)的輸入輸出時,開發(fā)人員會依照一定的規(guī)則來杜絕被污染、不干凈的數(shù)據(jù)進入到程序之中。如此,開發(fā)人員便會在交互界面中設(shè)置一定的門檻,以使得不符合規(guī)范的數(shù)據(jù)不能進入系統(tǒng),也就不會破壞數(shù)據(jù)的完整性。
當(dāng)前應(yīng)用程序的開發(fā)為了符合“高內(nèi)聚,低耦合”的思想,將各功能模塊分為三層體系結(jié)構(gòu),包括客戶端代碼、服務(wù)器端代碼和后端數(shù)據(jù)庫。近年來,為提高應(yīng)用的效率和可用性,Web 應(yīng)用開始將許多的計算任務(wù)遷移到客戶端進行處理。通過這樣的方式來減少客戶端向服務(wù)器發(fā)送請求并等待響應(yīng)的時間,從而提高應(yīng)用的響應(yīng)性。因此,在客戶端對數(shù)據(jù)輸入進行驗證也越來越普遍。
任何數(shù)據(jù)在進入軟件系統(tǒng)之前,都需要對其進行必要的過濾。應(yīng)用程序必須對不良數(shù)據(jù)保持高度的警惕,否則很容易受到來自外部系統(tǒng)的網(wǎng)絡(luò)攻擊,因此所有數(shù)據(jù)在輸入時都要受到檢查。只有在經(jīng)過嚴格的驗證之后,進入到程序中的數(shù)據(jù)才是純凈的。這樣做的好處就是一旦數(shù)據(jù)持久化到數(shù)據(jù)庫中,代碼就無需反復(fù)檢查數(shù)據(jù)是否有效或適當(dāng)。因此無論是在前端頁面進行輸入驗證,還是在服務(wù)器后端對輸入驗證。兩者對輸入驗證的正確執(zhí)行都提出了較高的要求。
輸入驗證器通常是保護Web 以及移動應(yīng)用免受應(yīng)用程序級攻擊的第一道屏障,例如緩沖區(qū)溢出、SQL 注入和跨站點腳本[4]。當(dāng)攻擊者通過向應(yīng)用發(fā)送惡意輸入來發(fā)起此類攻擊時,這些輸入都將被輸入驗證器識別和過濾。如果驗證器存在缺陷,勢必會造成一些帶有惡意的輸入被漏掉使得應(yīng)用底層容易受到攻擊。因此需要對Web 應(yīng)用的輸入驗證函數(shù)的正確性進行檢查。
Offutt 等人提出了兩種測試輸入驗證的技術(shù),這兩種技術(shù)都試圖在設(shè)計測試用例時違反輸入規(guī)則來檢查輸入驗證函數(shù)。文獻[5]中提出的技術(shù)是用于輸入驗證分析和系統(tǒng)測試。在文獻[6]中提出的旁路測試方法為Web 應(yīng)用程序創(chuàng)建客戶端測試,并故意違反對用戶輸入的顯式和隱式檢查。雖然所提出的方法達到了用這些技術(shù)來驗證和測試輸入驗證函數(shù)的目的,但它們解決問題的方法與所提出的方法存在著很大的不同。所提出的方法通過分析處理輸入函數(shù)的CFG 來驗證輸入驗證特性并生成測試用例來測試這些特,因而將其定義為一種自動化的方法。然而這兩種技術(shù)是完全基于對輸入結(jié)構(gòu)和語法的分析,并不是完全自動化的。Nuo Li 等人則提出了一種基于擾動的交互式用戶輸入驗證測試(PIUIVT)[7],它將每個輸入字段與一個正則表達式進行關(guān)聯(lián),并且該正則表達式是有效的輸入約束。PIUIVT 接下來擾動正則表達式來生成無效的測試輸入,從而通過違反驗證函數(shù)所指定的策略以達到測試驗證函數(shù)的目的。
對于檢測應(yīng)用程序中輸入驗證漏洞的開發(fā)人員來說,還沒有在源碼級別找到一種合理的解決辦法。對此Zhejun FANG 等人提出了一種新的方法來檢測應(yīng)用程序中的輸入驗證漏洞,并實現(xiàn)了名為EasyIVD 的原型[8],該原型提供了Java 源代碼的靜態(tài)分析。EsayIVD 利用后向程序切片的方式從Java 源代碼中提取事務(wù)和約束切片。然后EasyIVD 用預(yù)定義的安全規(guī)則驗證這些切片,以此來檢測已知模式中的漏洞。為了檢測未知模式中的漏洞,EasyIVD 從復(fù)制的切片中提取隱式安全規(guī)范作為頻繁模式并驗證它們。然后EasyIVD 會半自動地確認可疑的規(guī)則違反,并將確認的規(guī)則報告為漏洞。
M. Alkhalaf 等人[9]基于自動機的字符串分析來檢查所提取驗證函數(shù)的正確性。使用確定有限自動機(DFA)來表示字符串表達式可以接受的值。通過前向符號可達性分析,計算字符串變量在每個程序節(jié)點都可以取到所有的可能值。假設(shè)每個驗證函數(shù)都以字符串作為輸入,如果輸入有效那么返回true(即驗證策略通過了當(dāng)前的輸入),否則返回false。于是便可以利用這樣的形式來自動地提取輸入驗證函數(shù)。也就是使用字符串分析計算所有可能的輸入值,使得程序能夠到達“return true”語句。然后檢查這組值是否屬于描述驗證策略的正則表達式所定義的子集。如果是,便知道應(yīng)用程序正確地實現(xiàn)了驗證策略,從而達到對輸入驗證函數(shù)的正確性進行驗證的目的。
Wassermann 和Su[10]使用Minamide[11]開發(fā)的字符串分析器來檢查PHP 應(yīng)用程序中的SQL 注入漏洞。通過計算得到可能到達SQL 熱點的CFG 語言,利用從污點分析中得到的污點值來注釋CFG 中的非終端。然后對每個非終端進行兩個檢查。首先檢查它是否在SQL 查詢中的文字字符串句法位置。如果在,那么檢查它是否與表示字符串的規(guī)則語言存在交集,如果該規(guī)則語言具有奇數(shù)個未轉(zhuǎn)義的引號,那么就認為是存在漏洞的。在文獻[12]中,Wassermann 和Su 使用了類似的方法來檢查XSS 漏洞。
差異分析技術(shù)[13]通常在找出不同代碼的差異之后就會停止,而不會試圖去修復(fù)這些差異。在NoTamper中[14]作者使用動態(tài)符號執(zhí)行方法分析客戶端腳本代碼,以生成測試用例,隨后將這些測試用例作為服務(wù)器端的輸入。由于該方法依賴于動態(tài)(黑盒)測試,所以其測試覆蓋率相當(dāng)有限。在其最近的一篇后續(xù)論文[15]中,作者又提出了WAPTEC,它使用服務(wù)器端代碼的符號執(zhí)行方法來指導(dǎo)測試用例生成過程并擴大覆蓋范圍。Kunal Taneja 等人則提出了一種的新的方法MiTV[16],它采用了多重實現(xiàn)測試來檢測驗證器。尤其是MiTV將被測驗證器的行為與其他同類型的驗證器進行比較,從而提供有效的工具支持來生成測試輸入和測試預(yù)言。MiTV 使用動態(tài)符號執(zhí)行引擎Pex[17]來測試.NET Web 應(yīng)用程序輸入驗證函數(shù)的正確性。這些函數(shù)首先根據(jù)它們驗證的輸入類型進行分類。然后通過將每個驗證函數(shù)與同一類下的函數(shù)子集進行比較來測試每個驗證函數(shù)。
一般而言,客戶端輸入驗證并不會取代服務(wù)端的驗證,而只能是增強和輔助。只有服務(wù)器后端才能保證數(shù)據(jù)輸入的合法性。隨著用戶群的增長,應(yīng)用程序的復(fù)雜性也隨之增加。因此客戶端和服務(wù)端都有著較為復(fù)雜的邏輯,驗證函數(shù)在客戶端以及服務(wù)器端之間的細微差異也會帶來一些用戶輸入漏洞。于是Muath Alkhalaf 等人就開發(fā)了ViewPoint[18],通過自動發(fā)現(xiàn)客戶端和服務(wù)端輸入驗證函數(shù)之間的不一致來識別用戶輸入的錯誤或不足。由于在客戶端和服務(wù)端所形成的檢查對用戶輸入會執(zhí)行相同的約束集,因此可以利用這些冗余的檢查來自動識別輸入驗證中的漏洞。SYM?DIFF[19]則是以一種語言不可知的方式計算兩函數(shù)之間的差異,將這兩個函數(shù)簡化為Boggie[20]中間語言,然后使用Z3SMT 求解器[21]找到它們之間的語義差異。Te?vfik Bultan 等人采用了確定有限狀態(tài)機來識別和修復(fù)輸入驗證中的安全漏洞。他們的方法[22]通過提取客戶端和服務(wù)端輸入驗證和檢查功能,使用符號定點計算將其建模為確定有限自動機(DFA),最后通過檢查與人工指定的攻擊模式相關(guān)的錯誤,或者通過客戶端和服務(wù)端在輸入驗證和檢查操作的不一致,從而識別檢查輸入驗證和校驗代碼中的錯誤。
現(xiàn)有研究主要集中在如何對輸入進行驗證,只涉及到了輸入驗證的部分工作。無論是在前端頁面對輸入數(shù)據(jù)進行驗證抑或是在后端進行驗證,對于交互設(shè)計中以什么樣的數(shù)據(jù)約束規(guī)則來進行驗證的相關(guān)研究較少。
在實際的應(yīng)用程序開發(fā)過程當(dāng)中,業(yè)務(wù)頻繁的更改以及需求文檔的缺失都會使得開發(fā)人員對于交互界面之中何處應(yīng)該存在數(shù)據(jù)約束以及存在數(shù)據(jù)約束的組件應(yīng)該添加上什么樣的約束缺乏一個客觀的判斷標(biāo)準。有時開發(fā)人員可能會遺漏某些需要添加數(shù)據(jù)約束的地方,或者加上了錯誤的約束規(guī)則。而這同樣給開發(fā)以及測試工作帶來了許多的不利影響。①增加了開發(fā)的成本。投入更多人力物力進行測試和驗證數(shù)據(jù)約束是否正確,這在一定程度上增加了開發(fā)人員和測試人員的工作量;②拖延了開發(fā)進度。開發(fā)人員需要對前端代碼進行反復(fù)修改,影響開發(fā)進度,也降低了應(yīng)用程序的開發(fā)效率;③降低了應(yīng)用的開發(fā)質(zhì)量。
設(shè)計并實現(xiàn)輸入驗證是一個具有挑戰(zhàn)性的工作,目前主要的重擔(dān)都落在了開發(fā)人員身上。而且許多已開發(fā)的且依賴用戶輸入的系統(tǒng)還需要多年的維護。在這期間,隨著業(yè)務(wù)需求的變化以及功能的擴展。需求文檔和應(yīng)用程序的源代碼都已變得更加復(fù)雜,越來越難以理解和維護。這在維護這些系統(tǒng)中實現(xiàn)的輸入驗證特性時會產(chǎn)生問題。當(dāng)輸入驗證的規(guī)則發(fā)生變化時,開發(fā)人員需要理解這些規(guī)則是怎么實現(xiàn)的,之后才能啟用這個變化。然而在大多數(shù)情況下開發(fā)文檔并不可靠,因為開發(fā)人員并不確定他們是否把所有需要更改的地方都考慮到了。另外,開發(fā)人員也沒有信心從代碼中手動恢復(fù)輸入驗證的規(guī)則。因此,可以考慮提出一種輔助方法來提示開發(fā)人員界面中哪些地方應(yīng)該有數(shù)據(jù)約束以及什么樣的約束規(guī)則。