カスタム・スクリプト
カスタム・スクリプトを使用すると、DAST スキャンをより動的に実行できます。JavaScript を追加することで、スキャン中に HTTP 要求と応答を操作することができます。これは、要求がサーバーに送信される前、または応答が受信された後のいずれかに行うことができます。
概説
カスタム・スクリプトは AppScan 内で実行され、メモリー内の要求および応答モデルで動作します。これにより、拡張機能を構築したりプロキシを使用したりすることなく、プログラムによって要求を調整したり、応答を検査したりすることができます。
概要
要求前: アプリケーションに送信される前に HTTP 要求を変更するスクリプトを実行します (ヘッダーの追加/削除、データの暗号化、トークンの処理など)。
応答後: アプリケーションから受信した HTTP 応答を処理します (コンテンツの復号化、値の抽出など)。
パラメーター: JavaScript のみを使用して、マルチステップ操作とフォーム・フィラーの値を生成します。
この機能を適切に使用して、スキャンの効率および有効性を高めてください。ライブ・デプロイメントの前に、制御された環境でスクリプトをテストして、スクリプトが期待どおりに機能することを確認します。
サンプル・テンプレートのパス: C:\Program Files (x86)\HCL\AppScan Standard\Templates。
- 認証スクリプト - 必要なセキュリティー資格情報またはトークンを動的に計算、生成、および追加します:
- 基本
- Basic HTTP 認証 - ユーザー名とパスワードを Base64 文字列にエンコードし、要求ヘッダーに挿入します。
- 資格情報
- 資格情報の追加 - ユーザー名とパスワードを JSON オブジェクトとして書式設定し、POST 要求の本文内に含めます。
- ヘッダーの挿入 - HTTP 要求に "Authorization" フィールドを手動で挿入します。
- 応答の解析 - サーバーの応答本文をチェックして認可トークンを抽出します。
- 基本
- 暗号化 - 要求ペイロードまたはヘッダーに暗号化アルゴリズムやハッシュ・アルゴリズムを適用します。
- HMAC
- HMACSHA512 - SHA-512 を使用して、鍵付きハッシュ・メッセージ認証コードを生成します。
- SHA
- SHA256_RSA - SHA-256 でデータをハッシュし、RSA 秘密鍵で暗号化することにより、デジタル署名を作成します。
- SHA512 - 非常に安全な 512 ビット固定長の暗号化ハッシュを生成します。
- SHA256 - 標準的な 256 ビット・ハッシュを生成します。
- HMAC
カスタム・スクリプトの追加
- 構成設定の「詳細」セクションの「カスタム・スクリプト」を選択します。
- 「+ 追加」ボタンをクリックします。
- 必要に応じて、事前入力された「名前」フィールドを編集します。
- スクリプトに適した「実行コンテキスト」を選択します: :
- 要求を送信する前にスクリプトを実行するための「事前要求」。
- 応答を受信した後にスクリプトを実行するための「事後応答」。
- 複数の手順やフォームへの入力を伴うタスクの「パラメーター」。このコンテキストを
setResultValueメソッドと組み合わせて使用すると、スクリプトが AppScan に結果を返すことができます。
- JavaScript フィールド (コードエディター) に JavaScript を入力し、AppScan 環境内で自動補完候補を表示するには Ctrl+Space を使用します。
- 「追加」をクリックしてスクリプトを保存します。スクリプトがリストに追加され、デフォルトで有効になります。
- 「有効」チェックボックスを使用して、カスタム・スクリプトのリストからスクリプトを有効または無効にすることができます。
- 「有効」チェックボックスを使用するか、スクリプト・リストでスクリプトを編集、削除、または並べ替えて、スクリプトを管理します。

- 「フル・スキャンの開始」をクリックして、スキャンを実行します。
- 結果: 有効なスクリプトが、要求または応答ごとに実行されます。「データ」 > 「要求」タブ > 「要求/応答」から、スクリプトの詳細を表示できます。
構文の正確性および AppScan でサポートされている JavaScript バージョンとの互換性について、スクリプトを検証します。詳細なガイドラインについては、「JavaScript コード」を参照してください。
注:- カスタム・スクリプトはスキャン構成ファイルに保存され、テンプレートを使用してエクスポートできます。これらはスキャン結果には含まれません。
- デフォルトでは、カスタム・スクリプトはテンプレートにエクスポートされるときに暗号化されます。
カスタム・スクリプトのアクティブ化
カスタム・スクリプトはデフォルトで有効になっており、記録およびスキャン中にすべての HTTP 要求および応答で実行されます。
スクリプトの実行を無効にするには、「ツール」 > 「オプション」 > 「詳細」タブに移動し、「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); }パラメーター
- このコンテキストで使用できるデータ・オブジェクト (request または response) はありません。使用すると null が返されます。
- setResultValue(value) を使用して値を返します。
フォーム・フィラーでは、「値のソース」 > 「カスタム・スクリプト」を選択すると、実行コンテキストがパラメーターであるスクリプトのみがリストに表示されます。
// 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")){ ... }
Parameter コンテキスト - フル
API// Update the result back to AppScan
setResultValue("ABC-" + Date.now());Environment データ
短期データは、スキャンの一時停止、停止、または完了、ログイン、あるいは手動テストの終了など、タスクが終了するまでの間のみ利用できます。これは、新しいスキャンまたは再スキャンの開始時にクリアされます。
- グローバル変数: グローバル変数データは、ユーザー固有のデータ・ペアを格納するために設計されたキー - 値データ構造です。キーは一意 (2 つの要素が同じキーを持つことはできませんが、複数の要素が同じ値を共有することはできます) であり、実行中のスクリプト間でデータを共有するのに便利です。
- スキャンステータス: 現在のスキャンに関する情報を含んでいます。
// Check the status of the scan environment.status.isInExplore(); environment.status.isInTest();
Logging - フル API
スクリプトのロギングを有効にして、デバッグやトラブルシューティングに役立てます。この環境では、標準の console.log コマンドはサポートされていません。代わりに、引用符で囲んだメッセージを指定して log 関数を使用してください。例: log("メッセージをここに入力します")。JavaScript の構文や使用法に関係しないエンジンの操作中にランタイム エラーが発生した場合は、さらなる分析のためにエンジン トレース ログに記録されます。
ログは、AppScan のログ フォルダー内の UserScript.log ファイルに書き込まれます。
既定のフォルダーは [UserDataFolder]\AppData\Roaming\HCL\AppScan Standard\logs です。
制約と実行制限
- 使用禁止の関数:
eval、Function(コンストラクター)、setTimeout、setlnterval。これらのいずれかを使用すると、スクリプトは失敗します。 - 制限: 最大実行時間: 5 秒、メモリー制限: 64 MB。これらの制限を超えると、スクリプトは失敗します。
失敗した場合、スキャンは一時停止し、詳細が UserScript.log に記録されます。
サポートされる JavaScript バージョン
- ES6: ジェネレーター、末尾呼び出し
- ES8: 共有メモリとアトミック機能
- ES15: Atomics.waitAsync, Regex flag \v
オートコンプリートで使用可能なオブジェクト
これらのオブジェクトは、スクリプト エディターのオートコンプリート候補に表示されるため、簡単に見つけて使用できます:
- キーワード
- 配列
- 日付
- オブジェクト
- String
- 正規表現(R)
- JSON
- マップ
- 演算
これらのオブジェクトは、スクリプト エンジンで完全にサポートされていますが、オートコンプリート一覧には表示されません。ただし、エディターで名前を直接入力すれば使用できます:
- ArrayBuffer
- BigInt
- ブール値
- DataView
- エラー
- Iterator
- 番号
- Promise
- プロキシー
- Reflect
- SharedArrayBuffer
- シンボル
-
TypedArray
-
WeakMap
-
WeakRef
-
WeakSet
注:「オートコンプリートには表示されない」とは、エディターがこれらの項目を自動的に提案しないことを意味します。ただし、オブジェクトは標準の JavaScript とまったく同じように実装され、動作します。
トラブルシューティング
- スクリプトの失敗: エラーの詳細については、ログ フォルダー(既定: [UserDataFolder]\AppData\Roaming\HCL\AppScan Standard\logs)を確認してください。未処理の例外が発生した場合は、コードを try...catch ブロックで囲み、適切に処理してください。
- スクリプトが実行されない: 設定でスクリプトが有効になっていることを確認してください。
問題がログイン/認証に関連している場合は、Configuration→ Advanced Configuration → Security Package Order から negotiate 値を削除し、AppScan がこれらの認証を自動的に処理しないようにすることを検討してください。
フル API の要求
| メンバー | タイプ | 説明 | 例 |
|---|---|---|---|
| header | オブジェクト | 現在の HTTP 要求のヘッダーをカプセル化するオブジェクト。ヘッダーを動的に追加、更新、取得、または削除するメソッドを提供し、要求'のメタデータを正確に制御できます。 | request.headers.set("Authorization","Bearer ...") |
| 本文 | string | 現在の HTTP 要求の本文。 | request.body = JSON.stringify({ user:"jsmith" }) |
| パス | string |
読み取り専用🔒 現在の HTTP 要求の相対パス。 |
if (request.path.startsWith("/api/v1/")) { ... } |
| クエリ | オブジェクト | 現在の HTTP 要求でクエリー・パラメーターを追加、更新、または削除するさまざまなメソッドを含むオブジェクト。これにより、クエリー文字列を動的に操作できます。 | request.query.addOrUpdate("lang","en") request.query.remove("debug") |
| メソッド | string |
読み取り専用🔒 現在の HTTP 要求のメソッド。 |
if (request.method == "GET") {{ ... }} |
| メンバー | タイプ | 説明 | 例 |
|---|---|---|---|
|
(name: string, value: string) |
void | クエリー文字列に新しい値を追加するか、既存の値を更新します。 | request.query.addOrUpdate("appscan","appscanvalue") |
getQueryString() |
string |
すべてのパラメーターとその値を含む、現在の HTTP 要求の完全なクエリー文字列を返します。 |
request.query.getQueryString() |
|
(name: string) |
boolean |
現在の HTTP 要求に特定のクエリー・パラメーターが存在するかどうかを確認します。 パラメーターが存在する場合は true を返し、存在しない場合は false を返します。 |
request.query.contains("lang") |
|
(name: string) |
boolean |
現在の HTTP 要求から特定のクエリー・パラメーターを削除します。 パラメーターが削除された場合は true を返し、削除されなかった場合は false を返します。 |
request.query.remove("lang") |
clear() |
void |
現在の HTTP 要求からすべてのクエリー・パラメーターを削除します。 |
request.query.clear() |
Response - フル API
| メンバー | タイプ | 説明 | 例 |
|---|---|---|---|
| header | オブジェクト | 現在の HTTP 応答のヘッダーをカプセル化するオブジェクト。ヘッダーを動的に追加、更新、取得、または削除するメソッドを提供し、応答のメタデータを正確に制御できます。 | response.headers.set("Authorization","Bearer ...") |
| 本文 | string | 現在の HTTP 応答の本文。 | response.body = JSON.stringify({ user:"jsmith" }) |
| パス | string |
読み取り専用🔒 現在の HTTP 応答の相対パス。 |
if (response.path.startsWith("/api/v1/")) { ... } |
| ステータス | オブジェクト | ステータス・コードおよびステータス・メッセージのプロパティを含む、現在の HTTP 応答のステータスを表すオブジェクト。 | if (response.status.code == 200) { ... } |
| 要求 | オブジェクト | 応答を開始した要求を表すオブジェクト。要求データは読み取り専用で、前述の request オブジェクトで定義されたすべてのプロパティが含まれます。 | if (response.request.path) { ... } |
| メンバー | タイプ | 説明 | 例 |
|---|---|---|---|
| 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" |
パラメーター フル API
| メンバー | タイプ | 説明 | 例 |
|---|---|---|---|
|
(value: string) |
void | 現在のパラメーター・コンテキストのスクリプトの結果値を設定します。 | setResultValue("ABC-" + Date.now()) |
共通オブジェクト
| メンバー | タイプ | 説明 | 例 |
|---|---|---|---|
| 項目 | 配列 |
読み取り専用🔒 現在の HTTP 要求内のすべてのヘッダーの配列。 |
|
| メンバー | タイプ | 説明 | 例 |
|---|---|---|---|
追加(name: string, value: string) |
void |
現在の HTTP 要求に新しいヘッダーを追加します。同じ名前と値を持つヘッダーがすでに存在する場合、そのヘッダーは再度追加されません。 |
|
セット(name: string, value: string) |
void | 現在の HTTP 要求でヘッダーを設定します。ヘッダーがすでに存在している場合には、その値が置き換えられます。 |
|
|
(name: string) |
void | 現在の HTTP 要求からヘッダーを削除します。 | request.headers.remove("Authorization")response.headers.remove("Authorization") |
| [name: string] | string | 特定のヘッダーの値を名前で取得します。ヘッダーが存在しない場合は null を返します。 |
|
Environment データ
| メンバー | タイプ | 説明 | 例 |
|---|---|---|---|
| globalVariables | オブジェクト | ユーザー固有のデータ ペアを保存するためのキー値データ構造。キーは一意で、重複しないようにする必要がありますが、値は複数のキーで共有できます。この構造により、実行中のスクリプト間でのデータ共有が容易になります。 | environment.globalVariables.addOrUpdate(key, value) |
| ステータス | オブジェクト | スキャンの現在のステータスに関する情報。 | environment.status.isInExplore() |
| メンバー | タイプ | 説明 | 例 |
|---|---|---|---|
|
(key: string, value: string) |
void | 新しいキーと値のペアをグローバル変数に追加するか、既存のキーの値を更新します。 | environment.globalVariables.addOrUpdate("mycoolkey", "testValue") |
|
(key: string) |
boolean | グローバル変数からキーと値のペアを削除します。キーが見つかって削除された場合は true を返し、それ以外の場合は false を返します。 | environment.globalVariables.remove("mycoolkey") |
get(key: string) |
string | グローバル変数から特定のキーの値を取得します。キーが存在しない場合は、空の文字列を返します。 | environment.globalVariables.get("mycoolkey") |
| メソッド | タイプ | 説明 | 例 |
|---|---|---|---|
isInExplore() |
boolean | スキャンが現在探索フェーズにあるかどうかを確認します。 | environment.status.isInExplore() |
isInTest() |
boolean | スキャンが現在テスト・フェーズにあるかどうかを確認します。 | environment.status.isInTest() |
ログ
| メンバー | タイプ | 説明 | 例 |
|---|---|---|---|
log(message: string)
log(message: string, source: string) |
void | 指定したメッセージと省略可能なソースを含む新しいログエントリーを追加します。 | log("これはログメッセージです")
|