自訂 Script

自訂 Script 可讓您進行更動態化的 DAST 掃描。您可新增 JavaScript 以在掃描期間操作 HTTP 要求或回應。這項操作可在傳送要求至伺服器前或收到回應後進行。

如何啟用 AppScan 的自訂 Script

自訂 Script 預設為啟用(CustomScripts.Enable 設定已設為 True)。

若要停用 Script:

  1. 移至工具 > 選項 > 進階標籤
  2. CustomScripts.Enable 設定設為 "False"。

如何為 DAST 掃描新增和啟用自訂 Script

您可以透過下列方式,將自訂 JavaScript 新增至 DAST 掃描:
  1. 導覽至配置設定的進階區段下的自訂 Script
  2. 按一下 + 新增按鈕。
  3. 名稱欄位會預先填入建立 Script 的日期與時間。您可以視需要變更名稱。
  4. 執行環境定義下拉式清單中,根據您希望 Script 執行的時間,選取要求前回應後
  5. JavaScript 欄位中,輸入 JavaScript 程式碼。若要接收 AppScan 環境中 JavaScript 程式碼的建議,請按 Ctrl+Space

    請確定程式碼毫無語法錯誤,並與 AppScan 支援的 JavaScript 版本相容。如需相關規則及程式碼編寫方式的詳細資訊,請參閱 JavaScript 程式碼

    範例 1:將登入詳細資料自動新增至您的要求(不使用登入管理配置)。

    // Before each request
    if(request.method == "POST") {
        request.body = JSON.stringify({
            "username": "jsmith",
            "password": "demo1234"
        })
    }

    範例 2:檢查回應是否包含 API 金鑰,並將其儲存於廣域變數。

    // After each response
    try {
            var result = JSON.parse(response.body)
            log(`parsing: ${JSON.parse(response.body).Authorization}`)
            if(result.Authorization) {
                environment.globalVariables.addOrUpdate("Authorization", result.Authorization)
                log(`key = ${result.Authorization}`)
            }
    }
    catch (error) {
            log(error)
    }

    範例 3:若有授權 API 金鑰,請將其設為標頭。

    // Before each request
    var authorization = environment.globalVariables.get("Authorization")
        if(authorization) {
            request.headers.set("Authorization", authorization)
            log(`authorization is ${authorization}`)
        }
  6. 按一下新增以儲存 Script。Script 會新增至清單且預設為啟用。
    Note: 在 DAST 掃描期間,每個 HTTP 要求或回應都會執行您新增的 Script。
    睿智運用此功能,便可提升掃描效率和效益。在即時掃描中部署您的 Script 之前,請務必先在控制環境中進行測試,以避免發生任何非預期的行為或結果。
  7. 您可利用啟用勾選框,從自訂 Script 清單選擇啟用或停用 Script。
  8. 您可以修改、刪除或變更 Script 的執行順序。在 Script 的右下角按一下 垂直的三點功能表 並選取以下選項:
    • 編輯
    • 刪除
    • 上移
    • 下移
  9. 按一下開始完整掃描以執行掃描。
  10. 結果:每項要求或回應都會執行啟用的 Script。您可以從資料 > 要求標籤 > 要求/回應,檢視 Script 的詳細資料。
    Note: 當您匯出範本中的自訂 Script 時,其預設為加密。若要手動停用此加密,請從掃描配置設定移至進階配置,然後將一般:加密機密資料設為 False

JavaScript 程式碼

環境定義

要求:您可以先閱讀或修改要求資料後,再將該資料傳送到伺服器。每項要求都由要求物件表示,其中具有下列內容:
  1. 標頭:包含所有要求標頭。您可新增、移除或修改預設標頭以外的任何標頭。
    // Add header
    request.headers.add(key, value)
    // Override header if exist
    request.headers.set(key, value)
    Note: 使用「新增」而非「設定」可能會導致要求中出現多個標頭實例。因此,使用「設定」比「新增」更好。
    // Remove header
    request.headers.remove(key)
    // Modify header
    request.headers[key]
    // Examples
    request.headers.add("Authorization", "MyCoolApiKey")
    request.headers.set("Authorization", "SecondApiKey")
    request.headers.remove("Authorization")
    request.headers['Authorization'] = "myapikey3"
    預設標頭(不分大小寫):這些標頭為唯讀且無法修改。
    • 主機:識別傳送要求至的主機。
    • 內容長度:計算要求大小,並將此資訊傳送至伺服器。
  2. 內文:包含要求內文的相關資訊。內文屬於「字串」類型。
    // Access body
    request.body
    // Example
    request.body = "{ "username":"user" }"
  3. 路徑:包含要求預定所用端點的相關資訊。端點格式排除基本 URL(例如 /api/v1/test)。此內容為唯讀;即使您嘗試在執行 Script 前對其進行變更,該內容仍與第一次設定時相同。
    // Access url path
    request.path
    // Example
    if (request.path.startsWith("api/v1/test"))
  4. 查詢:包含現行要求的查詢字串和參數(若有的話)。您可以從此物件新增或移除查詢參數。每個值都視為單一物件處理,例如 'key=value'。您使用 'getQueryString' 時,系統會給您一個字串,該字串會以 '&' 符號串連所有項目。此字串是項目的複本,因此若您變更字串,也只會變更查詢的複本。
    Note: 如果查詢參數為空白,AppScan 不會傳送查詢定界字元 (‘?’)
    // Retrieve the current query string
    request.query.getQueryString()
    
    // Example
    // Add new value (or update existing one)
    request.query.addOrUpdate("appscan","appscanvalue")
    // Check if value exist
    request.query.contains("appscan") // for key only check
    request.query.contains("appscan=appscanvalue") // for key and value check
    // Remove an item
    request.query.remove("appscan") // for key only check
    request.query.remove("appscan=appscanvalue") // for key and value check
    request.query.clear() // remove all values
  5. 方法:要求的方法(例如 GET/POST/etc)。此內容為唯讀;即使您嘗試在執行 Script 前對其進行變更,該內容仍與第一次設定時相同。
    // Access to the method
    request.method
    // Example
    if (request.method == "GET")
回應:包含回應資料和相關上層要求的物件。您可擷取資訊、修改或儲存回應資料。每項回應都由回應物件表示,其中具有下列內容:
  1. 內文:包含要求的回應內文。回應採用字串格式,因此您必須視需要手動轉換(例如轉換至 JSON)。
    // Access body
    response.body
    // Example
    let json = JSON.parse(config.response)
  2. 路徑:包含回應端點的相關資訊。
    // Access to the relative url
    response.path
    // Example
    if (response.path.startsWith("api/v1/test"))
  3. 狀態:儲存回應狀態的詳細資料。狀態是具有以下內容的物件:
    // Access status
    response.status.statusCode // A numeric representation of the status
    response.status.statusDescription // The description of the status code
    response.status.statusLine //the whole status line including the http version
    // Example
    if (response.status.statusCode == 200) // check only the number
    if (response.status.statusDescription == "OK") // Check only the description
    if (response.status.statusLine == "HTTP1.1 200 OK") // Full line
  4. 標頭:包含所有回應標頭。您可新增、移除或修改預設標頭以外的任何標頭。
    // Add header
    response.headers.add(key, value)
    // Override header if exist
    response.headers.set(key, value)
    // Remove header
    response.headers.remove(key)
    // Modify header
    response.headers[key]
    // Examples
    response.headers.add("Authorization", "MyCoolApiKey")
    response.headers.set("Authorization", "SecondApiKey")
    response.headers.remove("Authorization")
    response.headers['Authorization'] = "myapikey3"
  5. 上層要求:包含在回應前所傳送要求的物件。要求資料為唯讀。要求具有先前用於定義要求物件的所有內容。
    // Example
    response.request.path //- access to the path from the request

環境資料

短期資料物件會儲存重要資訊,直到作業結束為止,例如在您暫停、停止或完成掃描、登入或執行手動測試時。

  1. 廣域變數:廣域變數資料具有金鑰-值資料結構,專為儲存使用者特有的資料配對而設計。金鑰為獨一無二(表示兩個元素不會有相同金鑰,但多重元素可共用相同值),這一點對於在執行 Script 之間共用資料而言非常實用。

    每次完成新掃描或重新掃描時,即會清除此資料。

    // Add data to the globals or update existing one
    environment.globalVariables.addOrUpdate(key, value)
    // Remove key data from the globals
    environment.globalVariables.remove(key)
    // Read data - retrieves the value for the current key (without removing it)
    environment.globalVariables.get(key)
  2. 掃描狀態:包含現行掃描的相關資訊。
    // determine if the current phase is explore phase
    environment.status.isInExplore()
    // determine if the current phase is test phase
    environment.status.isInTest()

記載

啟用 Script 的記載功能,以協助除錯和識別問題。'console.log' 指令在此處無法運作。請改用 'log' 這個字,後面接續著引號中的訊息。此外,如果在引擎運作期間,發生無關 JavaScript 語法或使用的錯誤,該錯誤會記載在引擎追蹤日誌中。

// Log message to file
log("my cool logging")

// Log message with custom source
log("message", "my-cool-source")

限制

請勿在 Script 環境定義中使用下列方法:
  • eval
  • 函數(建構子)
  • setTimeout
  • setInterval
若使用上述任一方法,將導致 Script 失敗且產生錯誤

錯誤處理

如果 Script 使用任何受限功能,並發生錯誤或異常狀況,則會停止運作。此失敗會暫停目前的掃描,並將錯誤詳細資料記錄在「UserScript.log」檔案中以供進一步檢閱。

載入以 Script 配置的範本

您可以載入透過已啟用 Script 進行配置的範本來開始掃描。使用 Script 預先配置 demo.testfire 說明檔的範例範本,可在 Program Files (x86)\HCL\AppScan Standard\Templates 取得。

AppScan 支援的 JavaScript 版本

目前支援從 ES6 (2015) 至 ES15 (2024) 的 ECMAScript 版本,但以下功能除外:
  • ES6 (2015)
    • 產生器
    • 尾呼叫
  • ES8 (2017)
    • 共享記憶體與 Atomic
  • ES15 (2024)
    • Atomics.waitAsync
    • 正規表示式標誌 \v