AppScan 在 API 安全測試中的實例介紹
在本項目中,API 遵循標准的的 REST 架構和背端服務器進行通信。針對 API 的功能測試由兩部分組成:一部分是用一個 Web 的測試頁面直接實現的,另一部分,由於 Web 頁面的局限性(比如不能任意修改 HTTP header),所以是通過 Shell 腳本調用 curl 實現的。 並且這個 API 的測試環境沒有固定的域名和 IP 地址。針對 Web 應用的安全測試采用 AppScan Standard。項目實施過程中面臨這樣幾個問題:
- 針對 Web 頁面的非 REST API 測試,AppScan Standard 可以很好的勝任工作,但對於 API 部分,由於瀏覽器下的頁面的 HTTP 請求的局限性,API 測試頁面本身的對 API 的覆蓋率就不夠。所以通過 AppScan 掃描調用 API 的頁面,也難以保證覆蓋率。
- 系統沒有固定的域名或 IP 地址, 導致每次要重新錄制和創建測試任務。一個掃描后的 scan 文件內 Starting URL 也是一個只讀屬性如圖 1 所示。
圖 1 .導出 Starting URL
在開始介紹解決方法之前,先介紹一下 AppScan 的錄制文件。用戶通過普通的 Web 程序進行 AppScan 的測試,可以通過 Manual Explorer 錄制收集信息。 這樣會生成一個 manualExplore_1.exd 的文件在 AppScan 的掃描文件.scan 壓縮包里,scan 文件是通過 Deflate 壓縮打包的,所以您可以使用一個解壓工具查看 scan 文件里的結構和文件。在這里用戶可以通過點擊菜單欄中的 File-> Export -> Recorded Manual Explore 可以把 manualExplore_1.exd 文件導出,如圖 2 所示。
圖 2 .導出 manualExplore_1.exd 文件
而當需要時可以通過重新導入這個文件,將之前錄制的信息重新導入一個新的 scan 任務。而當測試者要測試某個同樣的 Web 實例時,當實例的域名或 IP 各不相同,並且測試者已經對其中一個進行了錄制,這樣就可以通過簡單修改這個 exd 文件然后分別 import 到不同的測試實例中。
這個文件本身是一個 XML 文件,這個文件大體結構,如清單 1。
清單 1 .exd 文件結構
<?xml version="1.0" encoding="utf-16"?> <!--Automatically created by AppScan at 1/16/2014 11:20:26 AM--> <!--Do NOT Edit!--> <requests> <request> ... </request> ... </requests> <!--Number of Requests in file = 100-->
從注釋中我們也可以看出,這個文件是 AppScan 自動產生的文件,因此修改時要特別注意,因為錯誤的修改可能使 AppScan 會無法識別錄制的 HTTP 請求,或者錯誤的識別 HTTP 的請求。最后一行的注釋表明里這里記錄了多少個 HTTP 的請求。
這些請求會都放在<requests>里,一個 request 的錄制信息結構,如清單 2。
清單 2 .request 的錄制結構
<request scheme="https" host="www.ibm.com" path="/" port="443" method="GET" SessionRequestType="Login" ordinal="15"> <raw encoding="none"> </raw> <cookie name="JSESSIONID" value="XXX" path="/" domain="www.ibm.com" secure="False" expires="1/1/0001 12:00:00 AM" /> <parameter name="XXX" captureIndex="0" value="" type="QUERY" linkParamType="simplelink" separator="&" operator="=" reportName="XXX" /> <sessionCookies> <cookie name="JSESSIONID" value="XXX path="/" domain="www.ibm.com" secure="False" expires="1/1/0001 12:00:00 AM" /> </sessionCookies> </request>
其中<raw>部分是原始的請求數據,包括 HTTP Header 和 body 部分的全部數據。 而其他的是從這個原始數據中結構化出來的一些數據,熟悉的 HTTP 的應該對這個結構化的數據並不陌生。比如 scheme 是請求的協議,session 是 HTTP header 里的 session 部分,parameter 是 URL 里的參數。在這里 ordinal 是對 request 在這個錄制文件內的一個計數。
熟悉了文件的結構我們就可以對其進行修改或添加自己的 HTTP 錄制的信息。來提高測試的覆蓋率。
下面介紹一下如何解決前面提到的兩個問題。
針對問題一,這里舉一個簡單的例子:現有一個針對數據庫查詢的請求,有兩個參數分別是 parm1 和 parm2,並且已經有對這個 API 的掃描的 exd 文件如下:
清單 3 .已有的錄制信息
<request scheme="https" host="www.site1.com" path="/test/API1" port="443" method="POST" SessionRequestType="Login" ordinal="146"> <raw encoding="none">POST /test/API1 HTTP/1.1 Host: www.site1.com User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:17.0) Gecko/20100101 Firefox/17.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-us,en;q=0.7,ja;q=0.3 Connection: keep-alive Content-Type: application/x-www-form-urlencoded; charset=UTF-8 X-Requested-With: XMLHttpRequest Referer: https://www.site1.com/ Content-Length: 83 Cookie: JSESSIONID=0000F7u3iiCtkF0SIR4G9viBIQr:156f4da9-0cc6-4460-9ac9-f791e0aac903 Pragma: no-cache Cache-Control: no-cache parm1=test1&parm2=test2</raw> <cookie name="JSESSIONID" value="0000F7u3iiCtkF0SIR4G9viBIQr:156f4da9-0cc6-4460-9ac9-f791e0aac903" path="/" domain="www.site1.com" secure="False" expires="1/1/0001 12:00:00 AM" /> <parameter name="parm1" captureIndex="0" value="test1" type="BODY" linkParamType="simplelink" separator="&" operator="=" reportName="parm1" /> <parameter name="parm2" captureIndex="0" value="test2" type="BODY" linkParamType="simplelink" separator="&" operator="=" reportName="parm2" /> <sessionCookies> <cookie name="JSESSIONID" value="0000F7u3iiCtkF0SIR4G9viBIQr:156f4da9-0cc6-4460-9ac9-f791e0aac903" path="/" domain="www.site1.com" secure="False" expires="1/1/0001 12:00:00 AM" /> </sessionCookies> </request>
現在由於接口的更改,其中一個參數的 name 由原來的 parm1 改為新的 newparm。如果按照常規的流程,我們還需要對整個結構的測試頁面進行掃描。而其實我們只用改掉文檔里相應的部分,將原來的 exd 的參數部分改成如清單 4。
清單 4 .修改后的 exd 文件
<request scheme="https" host="www.site1.com" path="/test/API1" port="443" method="POST" SessionRequestType="Login" ordinal="146"> <raw encoding="none">POST /test/API1 HTTP/1.1 ... Content-Length: 23 newparm=test1&parm2=test2</raw> ... <parameter name="newparm" captureIndex="0" value="test1" type="BODY" linkParamType="simplelink" separator="&" operator="=" reportName="newparm" /> ... </request>
針對第二個問題,使用上面提到的方法,將 exd 文件導出,並修改補充后存檔備份。當有新的不同域名或 IP 的任務時,可以通過新建 scan 任務,完成任務配置后,復制一份已經存檔的 exd 文件,將文件里所有的域名或 IP 替換成新的域名或 IP 並保存,然后再新建的 scan 文件內導入這個錄制文件就可以了。
通過上面的方法,項目的問題很好的得到了解決,即保證了測試覆蓋率,又確保了測試靈活性。
回頁首
總結
隨着 API 的廣泛應用,API 安全測試變得越來越重要,本文介紹的 AppScan Standard 在 API 安全測試中的應用方法,是一個簡單而有效的方法,可以很好的提高 API 安全測試效率,提高測試覆蓋率。