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