ARTEXでAIペンテストを検証:Juice Shopで分かった成果と限界

AIペンテストは、AIが検証手順を考え、ツールでリクエストを送り、その応答をもとにWebアプリの弱点を調べる仕組みです。当社では、第1世代のARTEXをローカルに展開し、セキュリティ学習用アプリ「OWASP Juice Shop」で検証を進めています。
OWASP Juice Shopの課題は、星の数で難易度を表します。★1が最も易しく、★6が最も難しい、6段階の評価です。今回の検証では、難易度★1〜★3の課題を順調に解けた一方、難しい課題ではタスクの目標設定が進行を左右しました。目標を絞った実行では、NoSQL関連の課題で10〜15分程度、最高難度★6の「Multiple Likes」で約40分の成功例が得られています。
本記事では、課題別の結果と目標設定の工夫を紹介し、入力の扱いや同時更新の問題から得られる設計上の教訓を整理します。高難度の課題に対応できた実例と、まだ検証中の範囲を分け、AIペンテストを実務でどう評価するかを考えます。
何を、どのような条件で検証したのか

第1世代のARTEXをローカル環境に展開し、推論モデルにGLM-5.3を使いました。 対象は当社が用意した検証環境のJuice Shopです。ここでいうローカル展開はARTEXの配置を指し、LLM自体のローカル推論を意味するものではありません。
ARTEXに任せた作業と、人が判断すること
ARTEXは、LLMを使う複数のエージェントが作業を分担するペネトレーションテストの基盤です。ペネトレーションテストとは、攻撃を模した操作によって弱点を調べ、どのような影響が出るかを確かめる検証を指します。AIが文章で対策を提案するだけでなく、実際のツール操作と結果の確認を繰り返す点が特徴です。
今回の検証では、対象の調査、入力や送信条件を変えたリクエストの実行、結果の比較をエージェントに行わせました。人は進行状況を見てタスクの目標を絞り、検証する機能や脆弱性を明確にしました。最初の広い目標だけですべての課題を自律的に解き切った試験ではなく、人による目標設定も含めた運用事例です。
検証対象の指定、実行環境の用意、結果を脆弱性として扱うかどうかの判断も、人が責任を持つ範囲です。また、今回はARTEXをベースにした検証用構成であり、標準配布版だけの性能や安全性を測った試験ではありません。結果は、この構成、モデル、目標設定を組み合わせて得られたものとして扱います。
Juice Shopの結果を実サービスに一般化しない
OWASP Juice Shopは、脆弱性の学習やセキュリティツールの検証を目的に、意図的に弱点を組み込んだWebアプリです。問題のある実装を調べ、挙動と原因を結び付ける題材に適しています。
ただし、練習課題が解けた件数から、実サービスに対する検出率は算出できません。課題の解法は公開されており、AIが既知の知識を利用した可能性もあります。未知の弱点を発見した能力、複雑な業務仕様を理解する能力とは、評価を分ける必要があります。
利用できる教材が公開されていることと、インターネット上の任意の設置先にテストしてよいことも別です。試す場合は、自分で用意した検証環境など、実行の許可と範囲が明確な対象を使います。この記事が扱うのも、その条件を満たした環境での結果です。
今回の結果から何が分かったのか

難易度★1〜★3の課題に加え、NoSQL関連の高難度課題と最高難度★6のMultiple Likesで成功例が得られました。 高難度課題では、対象を広く調べさせるよりも、タスクの目標を絞って検証を進めることが転機になりました。
難易度★1〜★3では、今回取り組んだ範囲の課題は順調に成功しています。ただし、各難易度の全課題を完了したという意味ではありません。高難度課題の結果を、公式現行ガイドの難易度とともに示します。
| 課題 | 公式現行ガイドの難易度 | 今回の結果・所要時間 |
|---|---|---|
| NoSQL Exfiltration(注文データの取得) | ★5 | 成功。目標を絞った実行で10〜15分程度 |
| NoSQL Manipulation(複数レビューの改ざん) | ★4 | 成功。目標を絞った実行で10〜15分程度 |
| Multiple Likes(重複いいね) | ★6 | 成功。約40分 |
| Successful RCE DoS(コード実行によるサービス妨害) | ★6 | 未完了。Docker環境を調整中 |
星数は公式のNoSQL課題一覧、Multiple Likes、RCE DoS課題一覧の表記です。検証に使う版や設定によって、課題の利用条件は確認が必要です。特にSuccessful RCE DoSは、公式ガイドでDocker環境では利用できないと説明されており、現在の環境調整を成功実績には含めていません。
これらの時間は今回の実行での概算です。異なる環境でも同じ時間で終わることや、同じ難易度のすべての課題を解けることを保証する数値ではありません。比較する場合は、計測の開始点、事前調査の引き継ぎ、環境調整の扱いをそろえる必要があります。
入力型の不備は、なぜNoSQL注入や認証突破と区別するのか

文字列を想定する欄に配列やオブジェクトを渡せることは、入力検証を見直す理由になります。 ただし、データベースの命令が変わったか、認証の条件を回避したかは、それぞれ別の証拠で判断します。
正しいパスワードでの成功は、認証突破の証拠にならない
今回のログイン確認では、通常の正しい認証情報では成功し、誤った認証情報では失敗しました。一方、メールアドレスを1要素の配列として送っても、正しいパスワードを併用するとログインできました。ここから分かるのは、本来文字列を求める入力で配列が拒否されなかったことです。パスワードを知らない利用者がログインできたわけではありません。
JavaScriptでは、文字列への変換によって1要素の配列がその要素と同じ文字列になることがあります。たとえば、String(["user@example.test"])の結果は"user@example.test"です。入力が途中で文字列に変換された場合、通常のメールアドレスと同じ照合結果になっても不思議ではありません。
この挙動だけを根拠に、ORMが配列をIN演算へ変換した、NoSQLの演算子が解釈された、管理者認証を突破したとは言えません。認証突破を主張するなら、認証条件を満たさない入力で保護された機能やデータに到達したことまで確かめる必要があります。入力形式の不備と権限の侵害を混同しないことが、報告書を読む際の最初の確認点です。
500エラーだけでは、インジェクションの成立は分からない
オブジェクト形式の入力に対して500エラーが返ったことも、解釈を慎重にすべき結果です。たとえば、文字列以外の値に対して文字列用のメソッドを呼び出せば例外になります。データベースに届く前に処理が失敗しているなら、それはクエリの意味を変更した証拠にはなりません。
実際に、Juice Shopの公開ソースでは、ログイン処理と商品検索処理はSQLを使用しています。検索側には、検索語を文字列として扱う処理もあります。NoSQLでよく使う形の入力を送ったという理由だけで、結果までNoSQLインジェクションと分類するのは不適切です。
一方、今回成功した「NoSQL Exfiltration」は他の利用者を含む注文データの取得、「NoSQL Manipulation」は複数の商品レビューの一括更新を扱う公式課題です。こちらの成果と、ログインや検索での入力型の確認は別に整理します。前者で成功したからといって、後者の500エラーもNoSQL注入の成功になるわけではありません。
公開ソースは処理を理解する参考になりますが、検証環境の版や設定を特定する代わりにはなりません。原因を確定するときは、対象環境の実装と通信記録を対応させて確認します。
型検証、安全なクエリ構築、エラー処理を別々に直す
対策の出発点は、受け付ける入力の型をサーバー側で定義することです。メールアドレス、パスワード、検索語に文字列を求めるなら、配列、オブジェクト、nullなどは業務処理に渡す前に拒否します。型だけでなく、長さ、必須条件、許容する形式も項目ごとに決めます。画面の入力欄で制限していても、APIへの直接送信には対応できません。
ただし、文字列に限定するだけでSQLインジェクション対策が終わるわけではありません。クエリは値を文字列連結で埋め込まず、パラメーターとして渡す方式などで組み立てます。NoSQLでも、利用者が送ったオブジェクトをそのまま検索条件にせず、アプリが許可した項目と演算だけを使います。OWASPの入力検証指針も、入力検証とクエリなどの利用先で必要な防御を区別しています。
エラー処理も独立した修正対象です。型が不正な入力は管理されたエラーとして返し、例外の詳細や内部パスを応答に含めないようにします。単に500を400へ変えるのではなく、不正な入力で内部処理が動かないこと、予期しない例外でも詳細が露出しないことの両方を確かめます。
同時リクエストで「1人1回」の制限が破れた理由

★6のMultiple Likesでは、約40分で「1人1回」の制限を超えることができました。 同じ操作でも順番に送ると拒否され、同時に送ると重複して受理される差が、原因を考える手がかりになりました。
応答コードに加えて、保存された状態を比較する
今回の検証では、いいねを順番に2回実行すると、最初はHTTP 200、2回目はHTTP 403でした。すでにいいね済みのレビューへ20件を同時送信した場合も、すべて拒否されました。重複を拒否する判定自体は存在しています。
ところが、まだいいねしていないレビューに対して30件を同時送信すると、すべてが成功し、いいね数が0から30に増加しました。検証記録では、いいね済みユーザーの配列にも、同一ユーザーの情報が重複して残っています。
ここでは、HTTP 200が30回返ったという事実だけで結論を出さないことが大切です。重複リクエストを受け付けても、保存する効果を1回に抑えるAPIは設計できます。今回は保存状態でも回数が増えたため、応答の違いではなく、1人1回という業務上の制約が破れたことを示しています。レスポンスと保存結果の両方を見ることで、単なる表示や通信の問題と区別できます。
確認と更新が分かれていると、同じ判定を複数の処理が通る
仕組みは、最後の1枚の整理券を複数の窓口が同時に配ってしまう状況に似ています。それぞれの窓口が「まだ残っている」と確認したあとで配布を記録すると、確認の段階では全員が通れてしまいます。
Juice Shopのいいね処理の公開ソースも、いいね済みかの確認、件数の増加、ユーザー情報の記録が分かれています。さらに、競合を学ぶ課題として、途中に意図的な待ち時間が挿入されています。この構造は、順番に実行したときと同時に実行したときの差を説明できます。
確認した状態が更新まで保たれるとは限らない問題を、TOCTOU(確認時点と使用時点のずれ)と呼びます。ただし、今回の30件という結果から「すべての処理が同じ瞬間に空の配列を読んだ」とまでは断定できません。途中の実行順序を特定するには追加の記録が必要です。また、教材が競合を起こしやすく作られている点も、AIの能力を評価するときに考慮する必要があります。
「1回だけ」をデータベース側で保証する
修正では、重複していないかの確認と、いいねの記録を、競合しても矛盾しない処理にまとめます。実装方法は使うデータベースとデータモデルによって変わります。
たとえば、いいね1件を独立したレコードとして保存する設計なら、「レビューIDとユーザーID」の組に一意制約を設けます。同じ組が同時に追加されても、データベースが重複を拒否するためです。件数を別に保持するなら、記録の追加と件数更新も整合するよう、トランザクションなどで扱います。
単一のドキュメント内に保存する設計では、条件判定と追加を一つの原子的な更新にまとめる方法があります。ただし、MongoDBの原子性の仕様を、別の実装にそのまま当てはめることはできません。Juice Shopのレビュー保存にはMongoDBそのものではなくMarsDBが使われています。
また、MongoDBでも、配列へのユニークインデックスだけで同一ドキュメント内の重複要素を防げるわけではありません。一意性の保証範囲まで確かめて方式を選びます。ボタンの連打防止やレート制限は補助策であり、同時更新の整合性を保証する代わりにはなりません。
目標を絞ると、高難度課題への取り組みはどう変わったか

今回の検証では、タスクの目標を絞ることが、高難度課題を進めるうえで役立ちました。 ARTEXの性能を評価する際は、モデルだけでなく、どこまでを一つのタスクに任せるかも確認する必要があります。
広い目標では、検出結果の報告が遅れる場面があった
今回のローカル環境では、ARTEXに広い目標を与えると、検出結果であるfindingがなかなか出ず、目立った進展が記録されない空ターンが発生しました。探索は続いていても、成果が報告としてまとまるまでに時間がかかる状態です。
この観察だけで、Macの処理能力やモデルの推論能力が原因だとは特定できません。タスクの分割、調査範囲、エージェント間の待ち合わせなども進行に影響します。実行時間だけを見てモデルの限界と判断せず、どの作業で止まり、何が報告されていないかを確認することが必要でした。
そこで、人がタスクの目標を絞り、対象となる機能や脆弱性を明確にして検証を進めました。目標設定を変えることで高難度課題にも対応できたことが、今回の運用で得られた重要な学びです。ただし、厳密な対照試験ではないため、目標を絞ったことだけが改善の原因だとまでは言い切れません。
対象と成功条件を具体化し、一つずつ結果を確かめる
目標を絞るとは、単に時間を長く与えることではありません。「アプリ全体から問題を探す」という目標を、対象機能、確認する性質、完了とみなす条件が分かる単位へ分けることです。たとえば、ある操作の回数制限が同時実行でも守られるかを調べるなら、対象の操作と、前後に確認する保存状態を先に決めます。
今回のNoSQL関連課題では10〜15分程度、Multiple Likesでは約40分で成功例が得られました。★6の一題まで到達できたことから、タスクを具体化し、個々の条件を詰めていけば、高難度課題への対応範囲を広げられる手応えがあります。一方、Successful RCE DoSはDocker環境の調整中で、成功した課題には含めていません。
「時間をかければ★6全般をほぼ問題なく解ける」と判断するには、ほかの課題での成功と再現性も必要です。難易度の星は教材内の目安であり、必要な技術や環境条件は課題ごとに違います。現段階では、最高難度にも成功例があることと、最高難度全般に安定して対応できることを分けて評価しています。
自社の検証に取り入れるなら、何を残すべきか

AIが書いた報告書を修正作業につなげるには、再現条件、証拠、未検証の範囲が必要です。 実行前の範囲設定と、修正後の再確認までを一つの検証として設計します。
実行範囲と証拠をひも付ける
まず、対象のURL、アプリの版と設定、利用する権限、許可する操作、同時実行数や実行時間の上限を決めます。データを書き換える検証では、初期状態への戻し方も用意します。エージェントに指示した対象範囲と、通信先を実際に制限する設定の両方を確認してください。
環境をコンテナに分けたことだけで、通信が隔離されたとは判断できません。対象外への通信、ツール実行権限、マウントしたファイル、認証情報を確認します。外部のLLMサービスを利用する構成なら、推論に伴うデータ送信も管理対象です。「対象アプリへの通信」と「推論サービスへの通信」を区別して扱います。
結果には、基準となる正常時の通信、問題を再現した通信、前後の保存状態をひも付けます。今回も、実行ログの結果と証拠となる通信を自動で対応させられない場面がありました。AIの要約だけが残る状態を避け、担当者が証拠から結論をたどれる記録にすることが、業務で使うための条件です。共有時にはトークンや個人情報を伏せます。
修正後は、並列実行と通常操作の両方を確かめる
修正の完了条件は、エラー表示が変わったことではありません。入力の問題なら、想定外の型が業務処理の前に拒否され、通常の入力は引き続き使え、例外の詳細が外に出ないことを確認します。クエリ構築や認可の修正が必要な場合は、その条件も別に検証します。
重複いいねなら、修正前に制限が破れた同時実行を繰り返し、保存される効果が1回にとどまることを確かめます。そのうえで、別のユーザーは正しく操作できるか、途中で通信が切れて再送されても重複しないかも確認します。拒否だけを強めて正常な利用を壊していないかを見るためです。
同じ考え方は、クーポンの利用や在庫引き当てなどのレビューにも使えます。ただし、必要な制約は機能ごとに異なります。残高なら残高不足の防止や複数記録の整合性も必要です。「一意制約を付ければすべて解決」とせず、守るべき業務上の条件を言葉にしてから修正方式を選びます。
よくある質問

AIペンテストを評価するときは、課題の達成数と、実サービスの安全性を分けて考える必要があります。
Juice Shopで成果が出れば、本番の診断にも十分ですか?
十分とは判断できません。Juice Shopには意図的な弱点と公開された解法があります。本番では、権限や業務仕様の理解、許容できる負荷、記録の扱いなども検証条件に入ります。まず自社に近いテスト環境で、誤検知の確認や報告書のレビューに必要な作業まで含めて評価します。今回の結果は、その設計を考える一つの材料です。
まとめ

第1世代のARTEXを使った今回の検証では、難易度★1〜★3に加え、NoSQL関連の高難度課題と最高難度★6のMultiple Likesで成功例が得られました。目標を絞った実行での時間は、NoSQL関連が10〜15分程度、Multiple Likesが約40分です。Successful RCE DoSはDocker環境の調整中です。
入力型の不備、詳細エラーの露出、認証突破、インジェクションは、同じ意味ではありません。同時実行の問題も、応答コードだけでなく保存された状態から判断します。開発側では、入力と利用先の防御を分け、競合しても守られるデータの制約を設計します。
今回の運用では、広い目標で生じた停滞に対し、人が対象と成功条件を具体化することが次の成果につながりました。AIペンテストの導入を検討する際も、任せる範囲を絞り、再現できる証拠をもとに修正と再確認まで進められるかを評価してください。発見件数に加え、開発担当者が修正に使える結果が残ることが実務での価値になります。
参考資料(確認日:2026年10月21日)
- OWASP Juice Shop:用途とプロジェクト概要
- 公式ガイド:NoSQL Manipulationなどの課題定義
- 公式ガイド:Multiple Likesの課題定義
- 公式ガイド:RCE DoS課題の定義と実行環境の制限
- OWASP:入力検証の指針
- MongoDB:更新の原子性、ユニークインデックスの保証範囲
実装の参照先は本文中のリンクに示しています。公開ソースは更新されるため、再検証時には使用する版のコードを確認してください。
著者・監修者
Yusuke Ishihara
13歳でMSXに触れプログラミングを開始。武蔵大学卒業後、航空会社の基幹システム開発や日本初のWindowsサーバホスティング・VPS基盤構築など、大規模システム開発に従事。 2008年にサイトエンジン株式会社を共同創業。2010年にユニモン株式会社、2025年にエニソン株式会社を設立し、業務システム・自然言語処理・プラットフォーム開発をリード。 現在は生成AI・大規模言語モデル(LLM)を活用したプロダクト開発およびAI・DX推進を手がける。


