自訂 Script
自訂 Script 可讓您進行更動態化的 DAST 掃描。您可以在掃描期間新增 JavaScript,以在要求送出至伺服器之前或收到回應之後操作 HTTP 要求與回應。
概觀
自訂 Script 會在 AppScan 內執行,並操作記憶體中的要求與回應模型,讓您能以程式化方式調整要求與檢查回應,而無需建立擴充功能或使用 Proxy。
概覽
要求前:在要求送出至您的應用程式之前執行 Script,以修改 HTTP 要求(新增或移除標頭、加密資料、處理記號等)。
回應後:在收到應用程式回應後處理 HTTP 回應(解密內容、擷取值等)。
參數:僅使用 JavaScript 產生多步驟作業與表單填寫器的值。
睿智運用此功能,便可提升掃描效率和效益。在上線部署前,先於控制環境中測試 Script,以確保如預期運作。
範例範本路徑 C:\Program Files (x86)\HCL\AppScan Standard\Templates.
自訂 Script 範例:GitHub 儲存庫。
新增自訂 Script
- 選擇配置設定的「進階」區段下的「自訂 Script」。
- 按一下 + 新增按鈕。
- 視需要,編輯預先填入的「名稱」欄位。
- 為 Script 選擇合適的「執行環境定義」::
- 「要求前」適用於在傳送要求前執行的 Script。
- 「回應後」適用於在接收回應後執行的 Script。
- 「參數」適用於需要多步驟或填寫表單的作業。您可以搭配
setResultValue方法使用此環境定義,讓 Script 傳回結果至 AppScan。
- 在 JavaScript 欄位(程式碼編輯器)輸入 JavaScript,並在 AppScan 環境中使用 Ctrl+Space 以取得自動完成的建議。
- 按一下新增以儲存 Script。Script 會新增至清單且預設為啟用。
- 您可利用啟用勾選框,從自訂 Script 清單選擇啟用或停用 Script。
- 使用「啟用」勾選框管理 Script,或在 Script 清單中編輯、刪除或重新排序。

- 按一下開始完整掃描以執行掃描。
- 結果:每項要求或回應都會執行啟用的 Script。您可以從資料 > 要求標籤 > 要求/回應,檢視 Script 的詳細資料。
驗證 Script 的語法是否準確,以及是否與 AppScan 支援的 JavaScript 版本相容。如需詳細指南,請參閱 JavaScript 程式碼。
註:- 自訂 Script 會儲存在掃描配置檔中,並可與範本一併匯出。它們不會包含在掃描結果中。
- 自訂 Script 在匯出至範本時會預設加密。若要停用加密,請在掃描配置中將「一般」>「加密機密資料」設定為 False。
啟用自訂 Script
自訂 Script 預設為已啟用,並會在錄製與掃描期間隨每個 HTTP 要求與回應執行。
若要停用 Script 執行,請前往工具 > 選項 > 進階標籤,並將 CustomScripts.Enable 設定為「False」。
執行內容
要求前
目的:修改傳出的 HTTP 要求。
// Attach Authorization from stored global variable var token = environment.globalVariables.get("Authorization"); if (token) request.headers.set("Authorization", token);
回應後
用途:檢查回應並保留值。
// Capture token from JSON response and store it for reuse
try {
var result = JSON.parse(response.body);
if (result && result.Authorization) {
environment.globalVariables.addOrUpdate("Authorization", result.Authorization);
}
} catch(e) { log(e); }參數
- 此內容沒有可用的資料物件(要求或回應);若使用,將傳回空值。
- 使用 setResultValue(value) 傳回值。
在表單填寫器中,當您選取值來源 > 自訂 Script時,清單僅會顯示執行內容為參數的 Script。
// Example: Return a unique email for registration flows
function random(n) { return Math.random().toString(36).slice(2, 2+n); }
var email = "test_" + Date.now() + "_" + random(6) + "@example.test";
setResultValue(email);API 參照
// Examples: // Handle headers request.headers.set("Authorization", "Bearer"); request.headers.add("X-Trace", "abc"); // Manipulate body request.body = JSON.stringify( { user:"admin" }); if(request.body.includes("admin") { ... } // Read path if (request.path.startsWith("/api/v1")) { ... } // Edit query request.query.addOrUpdate("lang","en") request.query.remove("debug") request.query.getQueryString() // Read method if (request.method == "GET") { ... }
// Examples: // Handle headers response.headers.set("Authorization", "Bearer"); response.headers.add("X-Trace", "abc"); // Read body (since it's read only) var j = JSON.parse(response.body); // Read path if (response.path.startsWith("/api/v1")) { ... } // Read response if (response.status.statusCode == 200) { ... } // Read parent request if (response.request.path.startsWith("/api/v1")) { ... }參數內容-完整 API
// Update the result back to AppScan
setResultValue("ABC-" + Date.now());環境資料
短期資料物件僅在任務結束前可用,例如在您暫停、停止或完成掃描、登入或結束手動測試時。每次開始新掃描或重新掃描時,系統會清除該資料。
- 廣域變數:廣域變數資料具有金鑰-值資料結構,專為儲存使用者特有的資料配對而設計。金鑰為獨一無二(表示兩個元素不會有相同金鑰,但多重元素可共用相同值),這一點對於在執行 Script 之間共用資料而言非常實用。
- 掃描狀態:包含現行掃描的相關資訊。
// Check the status of the scan environment.status.isInExplore(); environment.status.isInTest();
記錄-完整 API
在 Script 中啟用記錄功能,以協助除錯與疑難排解。此環境不支援標準的 console.log 指令。請改用 log 函式並搭配引號訊息,例如:log("Your message here")。若在執行期間發生與 JavaScript 語法或使用無關的執行階段錯誤,該錯誤將記錄於引擎追蹤記錄中以供進一步分析。
記錄會寫入 AppScan 記錄資料夾中的 UserScript.log 檔案。
預設資料夾位置為 [UserDataFolder]\AppData\Roaming\HCL\AppScan Standard\logs。
限制與執行上限
- 受限函式:
eval, Function (constructor), setTimeout, setlnterval。若使用其中任一函式,Script 將執行失敗。 - 限制:執行時間上限:5 秒;記憶體限制:64 MB。超出此限制都會導致 Script 失敗。
當發生錯誤時,掃描將暫停,詳細資訊會記錄在 UserScript.log 中。
支援的 JavaScript 版本
- ES6:產生器、尾呼叫
- ES8:共享記憶體與 Atomic
- ES15:Atomics.waitAsync、正規表示式旗標 \v
自動完成中可用的物件
這些物件會出現在 Script 編輯器的自動完成建議中,方便搜尋與使用:
- 關鍵字
- 陣列
- 日期
- 物件
- 字串
- RegExp
- JSON
- 對映
- Math
這些物件已完全受 Script 引擎支援,但不會出現在自動完成清單中。您仍可在編輯器中直接輸入名稱來使用它們:
- ArrayBuffer
- BigInt
- Boolean
- DataView
- Error
- Iterator
- Number
- Promise
- Proxy
- Reflect
- SharedArrayBuffer
- Symbol
-
TypedArray
-
WeakMap
-
WeakRef
-
WeakSet
註: 「不在自動完成中」表示編輯器不會自動建議這些項目,但這些物件仍已實作,且行為與標準 JavaScript 完全相同。
疑難排解
- Script 失敗:請檢查日誌資料夾(預設位置:[UserDataFolder]\AppData\Roaming\HCL\AppScan Standard\logs)以取得錯誤詳細資訊。若遇到未處理的例外,請使用 try...catch 區塊包覆程式碼,以妥善處理錯誤。
- Script 未執行:請確認已在配置設定中啟用 Script。
若問題與登入或授權相關,請考慮從配置 → 進階配置 → 安全性套件順序中移除 negotiate 值,防止 AppScan 自動處理這些鑑別。
要求完整 API
| 成員 | 類型 | 說明 | 範例 |
|---|---|---|---|
| 標頭 | 物件 | 封裝目前 HTTP 要求標頭的物件,提供新增、更新、擷取或移除標頭的方法,讓您能動態且精確地控制要求的中繼資料。 | request.headers.set("Authorization","Bearer ...") |
| 主體 | 字串 | 目前 HTTP 要求的本文。 | request.body = JSON.stringify({ user:"jsmith" }) |
| 路徑 | 字串 |
唯讀🔒 目前 HTTP 要求的相對路徑。 |
if (request.path.startsWith("/api/v1/")) { ... } |
| 查詢 | 物件 | 包含多種方法可在目前的 HTTP 要求中新增、更新或移除查詢參數的物件,讓您能動態操作查詢字串。 | request.query.addOrUpdate("lang","en") request.query.remove("debug") |
| 方法 | 字串 |
唯讀🔒 目前 HTTP 要求的方法。 |
if (request.method == "GET") {{ ... }} |
| 成員 | 類型 | 說明 | 範例 |
|---|---|---|---|
|
(name: string, value: string) |
void | 在查詢字串中新增值或更新現有值。 | request.query.addOrUpdate("appscan","appscanvalue") |
getQueryString() |
字串 |
傳回目前 HTTP 要求的完整查詢字串,其中包含所有參數及其值。 |
request.query.getQueryString() |
|
(name: string) |
布林 |
檢查目前 HTTP 要求中是否存在指定的查詢參數。 若參數存在則傳回 true,否則傳回 false。 |
request.query.contains("lang") |
|
(name: string) |
布林 |
從目前的 HTTP 要求中移除特定查詢參數。 若成功移除參數則傳回 true,若未移除則傳回 false。 |
request.query.remove("lang") |
clear() |
void |
從目前的 HTTP 要求中移除所有查詢參數。 |
request.query.clear() |
回應完整 API
| 成員 | 類型 | 說明 | 範例 |
|---|---|---|---|
| 標頭 | 物件 | 封裝目前 HTTP 回應標頭的物件,提供新增、更新、擷取或移除標頭的方法,讓您能動態且精確地控制回應的中繼資料。 | response.headers.set("Authorization","Bearer ...") |
| 主體 | 字串 | 目前 HTTP 回應的本文。 | response.body = JSON.stringify({ user:"jsmith" }) |
| 路徑 | 字串 |
唯讀🔒 目前 HTTP 回應的相對路徑。 |
if (response.path.startsWith("/api/v1/")) { ... } |
| 狀態 | 物件 | 表示目前 HTTP 回應狀態的物件,包含狀態碼與狀態訊息等屬性。 | if (response.status.code == 200) { ... } |
| 要求 | 物件 | 表示觸發此回應的要求物件。要求資料為唯讀,且包含先前所述要求物件中定義的所有屬性。 | if (response.request.path) { ... } |
| 成員 | 類型 | 說明 | 範例 |
|---|---|---|---|
| statusCode | 數字 |
唯讀🔒 目前回應的 HTTP 狀態碼。 |
response.status.statusCode = 200 |
| statusDescription | 字串 |
唯讀🔒 目前回應的 HTTP 狀態訊息。 |
response.status.statusDescription = "OK" |
| statusLine | 字串 |
唯讀🔒 目前回應的 HTTP 狀態行。 |
response.status.statusLine = "HTTP/1.1 200 OK" |
參數完整 API
| 成員 | 類型 | 說明 | 範例 |
|---|---|---|---|
|
(value: string) |
void | 設定目前的參數內容 Script 結果值。 | setResultValue("ABC-" + Date.now()) |
常見物件
| 成員 | 類型 | 說明 | 範例 |
|---|---|---|---|
| 項目 | 陣列 |
唯讀🔒 目前 HTTP 要求中所有標頭的陣列。 |
|
| 成員 | 類型 | 說明 | 範例 |
|---|---|---|---|
add(name: string, value: string) |
void |
在目前的 HTTP 要求中新增一個標頭。若已存在相同名稱與值的標頭,則不會再次新增。 |
|
set(name: string, value: string) |
void | 設定目前的 HTTP 要求中的一個標頭。若該標頭已存在,將以新值取代舊值。 |
|
|
(name: string) |
void | 從目前的 HTTP 要求中移除一個標頭。 | request.headers.remove("Authorization")response.headers.remove("Authorization") |
| [name: string] | 字串 | 依標頭名稱擷取特定標頭的值。若該標頭不存在,則傳回空值。 |
|
環境資料
| 成員 | 類型 | 說明 | 範例 |
|---|---|---|---|
| globalVariables | 物件 | 用於儲存使用者特定資料配對的鍵值資料結構。鍵必須唯一,確保不重複,而值可在多個鍵之間共用。此結構可促進執行中 Script 之間的資料共用。 | environment.globalVariables.addOrUpdate(key, value) |
| 狀態 | 物件 | 關於目前掃描狀態的資訊。 | environment.status.isInExplore() |
| 成員 | 類型 | 說明 | 範例 |
|---|---|---|---|
|
(key: string, value: string) |
void | 新增一組鍵值配對至廣域變數,或更新現有鍵的值。 | environment.globalVariables.addOrUpdate("mycoolkey", "testValue") |
|
(key: string) |
布林 | 從廣域變數中移除一組鍵值配對。若找到並成功移除鍵則傳回 true,否則傳回 false。 | environment.globalVariables.remove("mycoolkey") |
get(key: string) |
字串 | 從廣域變數中擷取特定鍵的值。若該鍵不存在,則傳回空字串。 | environment.globalVariables.get("mycoolkey") |
| 方法 | 類型 | 說明 | 範例 |
|---|---|---|---|
isInExplore() |
布林 | 檢查掃描目前是否處於探索階段。 | environment.status.isInExplore() |
isInTest() |
布林 | 檢查掃描目前是否處於測試階段。 | environment.status.isInTest() |
記錄
| 成員 | 類型 | 說明 | 範例 |
|---|---|---|---|
log(message: string) log(message: string, source: string) |
void | 新增一筆包含指定訊息與可選來源的日誌項目。 | log("This is a log message")
|