カスタムスクリプト

カスタム・スクリプトを使用すると、DAST スキャンをより動的に実行できます。JavaScript を追加することで、スキャン中に HTTP 要求と応答を操作することができます。これは、要求がサーバーに送信される前、または応答が受信された後のいずれかに行うことができます。

概要

カスタム・スクリプトは、AppScan 内で実行され、メモリー内の要求および応答モデルで動作します。これにより、拡張機能を構築したりプロキシを使用したりすることなく、プログラムによって要求を調整したり、応答を検査したりすることができます。

概要

要求前: アプリケーションに送信される前に HTTP 要求を変更するスクリプトを実行します (ヘッダーの追加/削除、データの暗号化、トークンの処理など)。

応答後: アプリケーションから受信した HTTP 応答を処理します (コンテンツの復号化、値の抽出など)。

パラメーター: JavaScript のみを使用して、マルチステップ操作フォーム・フィラーの値を生成します。

この機能を適切に使用して、スキャンの効率および有効性を高めてください。ライブ・デプロイメントの前に、制御された環境でスクリプトをテストして、スクリプトが期待どおりに機能することを確認します。

テンプレート・パスの例: C:\Program Files (x86)\HCL\AppScan Standard\Templates.

カスタム・スクリプトの例: GitHub リポジトリー

カスタム・スクリプトの追加

次のように、カスタム JavaScript を DAST スキャンに追加します。
  1. 構成設定の「詳細」セクションの「カスタム・スクリプト」を選択します。
  2. 「+ 追加」ボタンをクリックします。
  3. 必要に応じて、事前入力された「名前」フィールドを編集します。
  4. スクリプトに適した「実行コンテキスト」を選択します。:
    1. 要求を送信する前にスクリプトを実行するための「事前要求」
    2. 応答を受信した後にスクリプトを実行するための「事後応答」
    3. 複数の手順やフォームへの入力を伴うタスクの「パラメーター」。このコンテキストを setResultValue メソッドと組み合わせて使用すると、スクリプトが AppScan に結果を返すことができます。
  5. JavaScript フィールド (コードエディター) に JavaScript を入力し、AppScan 環境内で自動補完候補を表示するには Ctrl+Space を使用します。
  6. 「追加」をクリックしてスクリプトを保存します。スクリプトがリストに追加され、デフォルトで有効になります。
  7. 「有効」チェックボックスを使用して、カスタム・スクリプトのリストからスクリプトを有効または無効にすることができます。
  8. 「有効」チェックボックスを使用するか、スクリプト・リストでスクリプトを編集、削除、または並べ替えて、スクリプトを管理します。 オプション・メニュー
  9. 「フル・スキャンの開始」をクリックして、スキャンを実行します。
  10. 結果: 有効なスクリプトが、要求または応答ごとに実行されます。「データ」 > 「要求」タブ > 「要求/応答」から、スクリプトの詳細を表示できます。

    構文の正確性および AppScan でサポートされている JavaScript バージョンとの互換性について、スクリプトを検証します。詳細なガイドラインについては、「JavaScript コード」を参照してください。

    注:
    • カスタム・スクリプトはスキャン構成ファイルに保存され、テンプレートを使用してエクスポートできます。これらはスキャン結果には含まれません。
    • デフォルトでは、カスタム・スクリプトはテンプレートにエクスポートされるときに暗号化されます。暗号化を無効にするには、スキャン構成で、「全般: 機密データを暗号化」設定を「False」に設定します。

カスタム・スクリプトのアクティブ化

カスタム・スクリプトはデフォルトで有効になっており、記録およびスキャン中にすべての HTTP 要求および応答で実行されます。

スクリプトの実行を無効にするには、「ツール」 > 「オプション」 > 「詳細」タブに移動し、「CustomScripts.Enable」設定を「False」に設定します。

実行コンテキスト

要求前

目的: 送信する HTTP 要求に変更を加える。

データ: request オブジェクトと environment オブジェクトのみが使用可能で、他のオブジェクトは null になります。
// Attach Authorization from stored global variable
var token = environment.globalVariables.get("Authorization");
if (token) request.headers.set("Authorization", token);

応答後

目的: 応答を検査し、値を維持する。

データ: response オブジェクトおよび environment オブジェクトのみが使用可能です。他のオブジェクトは null になります。
// 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); }

パラメーター

目的: マルチステップ操作およびフォーム・フィラーの値を生成する。
  • このコンテキストで使用できるデータ・オブジェクト (request または response) はありません。使用すると null が返されます。
  • setResultValue(value) を使用して値を返します。

フォーム・フィラーでは、「値のソース」 > 「カスタム・スクリプト」を選択すると、実行コンテキストがパラメーターであるスクリプトのみがリストに表示されます。

マルチステップ操作では、Parameter スクリプトを使用してダイナミック値を指定することもできます。
// 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 リファレンス

Request オブジェクト (要求前のコンテキスト) - フル 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") { ... }
注意: スクリプトは要求ごとに複数回実行される可能性があるため、set メソッドを使用して新しいヘッダーを追加し、それにより既存のヘッダーを置き換えて重複を防ぐことを推奨します。同じ名前で異なる値を持つ複数のヘッダーが必要な場合にのみ、add メソッドを使用します。同じ名前と値を持つヘッダーが既に存在する場合、add メソッドはヘッダーを追加しません。ヘッダーが重複しないように注意してください。エラーが発生する可能性があります。
Response オブジェクト (応答後のコンテキスト) - フル API
// 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());

環境データ

短期データは、スキャンの一時停止、停止、または完了、ログイン、あるいは手動テストの終了など、タスクが終了するまでの間のみ利用できます。これは、新しいスキャンまたは再スキャンの開始時にクリアされます。

  1. グローバル変数: グローバル変数データは、ユーザー固有のデータ・ペアを格納するために設計されたキー - 値データ構造です。キーは一意 (2 つの要素が同じキーを持つことはできませんが、複数の要素が同じ値を共有することはできます) であり、実行中のスクリプト間でデータを共有するのに便利です。
  2. スキャン状況: 現在のスキャンに関する情報を含んでいます。
    // Check the status of the scan
    environment.status.isInExplore();
    environment.status.isInTest();

Logging - フル API

スクリプトのロギングを有効にして、デバッグやトラブルシューティングに役立てます。この環境では、標準の console.log コマンドはサポートされていません。代わりに、引用符付きのメッセージを加えた log 関数を使用します。例: log("Your message here")。JavaScript の構文または使用法に関係しないエンジンの操作中にランタイム・エラーが発生した場合は、エンジン・トレース・ログに記録され、さらに分析されます。

ログは、AppScan ログ・フォルダーの UserScript.log ファイルに書き込まれます。

デフォルトのフォルダーは [UserDataFolder]\AppData\Roaming\HCL\AppScan Standard\logs です。

制約と実行の制限

  • 制限される機能: eval, Function (constructor), setTimeout, setlnterval。これらのいずれかを使用すると、スクリプトは失敗します。
  • 制限: 最大実行時間: 5 seconds、メモリー制限: 64 MB.これらの制限を超えると、スクリプトは失敗します。

    失敗した場合、スキャンは一時停止し、詳細が UserScript.log に記録されます。

サポートされる JavaScript バージョン

ECMAScript ES6 (2015) ~ ES15 (2024) (例外あり):
  • ES6: ジェネレーター、末尾呼び出し
  • ES8: 共有メモリとアトミック機能
  • ES15: Atomics.waitAsync、正規表現フラグ \v

オートコンプリートで使用可能なオブジェクト

これらのオブジェクトは、スクリプト・エディターのオートコンプリート提案に表示されるため、簡単に検索して使用できます。

  • キーワード
  • 配列
  • 日付
  • オブジェクト
  • 文字列
  • 正規表現
  • JSON
  • マップ
  • 演算
サポート対象だがオートコンプリートには表示されないオブジェクト

これらのオブジェクトは、スクリプト・エンジンで完全にサポートされていますが、オートコンプリート・リストには表示されません。ただし、エディターで直接名前を入力することで使用できます。

  • ArrayBuffer
  • BigInt
  • Boolean
  • DataView
  • Error
  • Iterator
  • Number
  • Promise
  • Proxy
  • Reflect
  • SharedArrayBuffer
  • Symbol
  • TypedArray

  • WeakMap

  • WeakRef

  • WeakSet

    注: 「オートコンプリートには表示されない」とは、エディターがこれらの項目を自動的に提案しないことを意味します。ただし、オブジェクトは標準の JavaScript とまったく同じように実装され、動作します。

トラブルシューティング

一般的な問題と解決策:
  1. スクリプト・エラー: ログ・フォルダー(デフォルト: [UserDataFolder]\AppData\Roaming\HCL\AppScan Standard\logs) でエラーの詳細について確認します。未処理の例外が発生した場合は、コードを try...catch ブロックで囲み、適切に処理します。
  2. スクリプトが実行されない: スクリプトが設定で有効になっていることを確認します。

    問題がログイン/認証に関連している場合は、「構成」→ 「詳細構成」 → 「セキュリティー・パッケージ順序」からネゴシエート値を削除し、AppScan がこれらの認証を自動的に処理しないようにします。

フル API の要求

1. Request オブジェクト - プロパティ
メンバー タイプ 説明
header object 現在の HTTP 要求のヘッダーをカプセル化するオブジェクト。ヘッダーを動的に追加、更新、取得、または削除するメソッドを提供し、要求のメタデータを正確に制御できます。 request.headers.set("Authorization","Bearer ...")
body string 現在の HTTP 要求の本文。 request.body = JSON.stringify({ user:"jsmith" })
パス string

読み取り専用🔒

現在の HTTP 要求の相対パス。

if (request.path.startsWith("/api/v1/")) { ... }
query object 現在の HTTP 要求でクエリー・パラメーターを追加、更新、または削除するさまざまなメソッドを含むオブジェクト。これにより、クエリー文字列を動的に操作できます。 request.query.addOrUpdate("lang","en") request.query.remove("debug")
method string

読み取り専用🔒

現在の HTTP 要求のメソッド。

if (request.method == "GET") {{ ... }}
2. Query オブジェクト - メソッド
メンバー タイプ 説明

addOrUpdate

(name: string、value: string)

void クエリー文字列に新しい値を追加するか、既存の値を更新します。 request.query.addOrUpdate("appscan","appscanvalue")
getQueryString() string

すべてのパラメーターとその値を含む、現在の HTTP 要求の完全なクエリー文字列を返します。

request.query.getQueryString()

contains

(name: string)

boolean

現在の HTTP 要求に特定のクエリー・パラメーターが存在するかどうかを確認します。

パラメーターが存在する場合は true を返し、存在しない場合は false を返します。

request.query.contains("lang")

remove

(name: string)

boolean

現在の HTTP 要求から特定のクエリー・パラメーターを削除します。

パラメーターが削除された場合は true を返し、削除されなかった場合は false を返します。

request.query.remove("lang")
clear() void

現在の HTTP 要求からすべてのクエリー・パラメーターを削除します。

request.query.clear()

Response - フル API

3. Response objectStatus オブジェクト
メンバー タイプ 説明
header object 現在の HTTP 応答のヘッダーをカプセル化するオブジェクト。ヘッダーを動的に追加、更新、取得、または削除するメソッドを提供し、応答のメタデータを正確に制御できます。 response.headers.set("Authorization","Bearer ...")
body string 現在の HTTP 応答の本文。 response.body = JSON.stringify({ user:"jsmith" })
パス string

読み取り専用🔒

現在の HTTP 応答の相対パス。

if (response.path.startsWith("/api/v1/")) { ... }
status object ステータス・コードおよびステータス・メッセージのプロパティを含む、現在の HTTP 応答のステータスを表すオブジェクト。 if (response.status.code == 200) { ... }
request object 応答を開始した要求を表すオブジェクト。要求データは読み取り専用で、前述の request オブジェクトで定義されたすべてのプロパティが含まれます。 if (response.request.path) { ... }
4. プロパティ
メンバー タイプ 説明
statusCode number

読み取り専用🔒

現在の応答の HTTP ステータス・コード。

response.status.statusCode = 200
statusDescription string

読み取り専用🔒

現在の応答の HTTP ステータス・メッセージ。

response.status.statusDescription = "OK"
statusLine string

読み取り専用🔒

現在の応答の HTTP ステータス行。

response.status.statusLine = "HTTP/1.1 200 OK"

Parameter - フル API

5. Parameter オブジェクト
メンバー タイプ 説明

setResultValue

(value: string)

void 現在のパラメーター・コンテキストのスクリプトの結果値を設定します。 setResultValue("ABC-" + Date.now())

共通オブジェクト

6. Header オブジェクト - プロパティ
メンバー タイプ 説明
items array

読み取り専用🔒

現在の HTTP 要求内のすべてのヘッダーの配列。

if (request.headers.items.length > 0) { ... }

if (response.headers.items.length > 0) { ... }

7. Headers オブジェクト - メソッド
メンバー タイプ 説明
add

(name: string、value: string)

void

現在の HTTP 要求に新しいヘッダーを追加します。同じ名前と値を持つヘッダーがすでに存在する場合、そのヘッダーは再度追加されません。

request.headers.add("Authorization", "MyCoolApiKey")

response.headers.add("Authorization",MyCoolApiKey")

set

(name: string、value: string)

void 現行の HTTP 要求でヘッダーを設定します。ヘッダーがすでに存在している場合には、その値が置き換えられます。

request.headers.set("Authorization", "SecondApiKey")

response.headers.set("Authorization","SecondApiKey")

remove

(name: string)

void 現在の HTTP 要求からヘッダーを削除します。 request.headers.remove("Authorization")response.headers.remove("Authorization")
[name: string] string 特定のヘッダーの値を名前で取得します。ヘッダーが存在しない場合は null を返します。

request.headers['Authorization'] = "myapikey3"

response.headers['Authorization'] = "myapikey3"

環境データ

8. Environment オブジェクト - プロパティ
メンバー タイプ 説明
globalVariables object ユーザー固有のデータ・ペアを保存するためのキー値データ構造。キーは一意で、重複しないようにする必要がありますが、値は複数のキーで共有できます。この構造により、実行中のスクリプト間でのデータ共有が容易になります。 environment.globalVariables.addOrUpdate(key, value)
status object スキャンの現在のステータスに関する情報。 environment.status.isInExplore()
9. Global variables オブジェクト - メソッド
メンバー タイプ 説明

addOrUpdate

(key: string, value:

string)

void 新しいキーと値のペアをグローバル変数に追加するか、既存のキーの値を更新します。 environment.globalVariables.addOrUpdate("mycoolkey", "testValue")

remove

(key: string)

boolean グローバル変数からキーと値のペアを削除します。キーが見つかって削除された場合は true を返し、見つからなかった場合は false を返します。 environment.globalVariables.remove("mycoolkey")
get

(key: string)

string グローバル変数から特定のキーの値を取得します。キーが存在しない場合は、空の文字列を返します。 environment.globalVariables.get("mycoolkey")
10. Status オブジェクト - メソッド
メソッド タイプ 説明
isInExplore() boolean スキャンが現在探索フェーズにあるかどうかを確認します。 environment.status.isInExplore()
isInTest() boolean スキャンが現在テスト・フェーズにあるかどうかを確認します。 environment.status.isInTest()

Logging

11. メソッド
メンバー タイプ 説明
log(message: string) log(message: string, source: string) void 指定したメッセージとオプションのソースを含む新しいログ・エントリーを追加します。 log("This is a log message")

log("This is a log message", "mySource")