今回は、生成AIを使ってセキュリティの検査作業を自動化できるオープンソースのツール「PentAGI」を紹介します。PentAGIでできることや、利用時に確認すべきポイントなどを記載します。
注意
本ブログは、ツールの仕組みを理解し、防御に役立てることを目的としています。本ブログで紹介するツールを試すときは、ご自身で管理する環境か、管理者から明示的に許可を得た環境だけで行ってください。内容は筆者が独自に調査したものですが、すべてが正確・最新であることを保証するものではありません。本ブログの内容を使用したことによって生じた不利益等について、筆者および所属組織は一切の責任を負いません。
PentAGIとは
PentAGIは、生成AIを使ってペネトレーションテストを自動で進めることができるオープンソースソフトウェア(OSS)です[1]。セキュリティ企業のVXControl[2]が開発し、GitHubでMITライセンスのもと公開されています[3]。
テストの対象と目的を言葉で伝えると、複数のAIエージェントが役割を分担し、次のような流れでテストを自律的に進めてくれます。
- 情報収集:どんなサーバか、どのポートが開いているかを調べる
- 調査:弱点の候補を探す
- 確認:本当に悪用できる弱点かを確かめる
- 報告:結果をレポートにまとめる
商用のEnterprise版もあり、報告書のテンプレート、DOCX形式での出力機能、商用サポートなどが追加されるようです[4]。
PentAGIの主な特徴を以下に記載します。
- エージェントの分業:指揮役のエージェントが、調査・コード作成・ツール実行などを専門のエージェントに振り分ける。作業が行き詰まると助言役が介入する
- 記憶:過去の結果や成功した手順をknowledgeとして保存し、次の検査に活かすことができる
- 専門ツールを隔離された環境で実行:Nmap[5]など20以上のツールが全てDockerコンテナの中で動くため、自身の端末に影響が出にくい
- LLMを選べる:OpenAI、Anthropic、Google Geminiなどの各種モデルを選択して使用できる。Ollama[6]を使えば手元の端末で動くローカルモデルも使用できる
- Web検索:検索エンジンや内蔵ブラウザで、最新の脆弱性情報を自律的に集めることができる
- レポート出力:検査結果をMarkdownやPDFで出力できる
PentAGIのインストール
Dockerを用いてインストールする手順を紹介します。
動作要件は次の通りです[7]。
- インストール先が2つ以上のvCPU、4GB以上のRAM、20GB以上の空きディスク容量を有していること
- インストール先でdockerコマンドおよびdocker composeコマンドが使えること
- インターネットに接続できる環境であること(イメージの取得とLLMへのアクセスに使用)
- 認証可能なLLMプロバイダが1つ以上存在すること(例えば、OpenAI、Anthropic、Gemini、AWS Bedrockのモデルを利用できること、またはOllama/OpenAI互換のバックエンドを利用できること)
動作検証で使用した環境は次の通りです。
なお、本記事でインストールするPentAGIのバージョンは v2.2.0-ce です。
Docker EngineとDocker Composeが利用できる状態を前提とします。Docker自体の導入は、Ubuntu向けの公式手順を参照してください[8]。
公式には対話形式のインストーラも用意されていますが、内部構造、設定ファイルなどを含め全体を把握しながら進めたいと考えて、Docker Composeによる手動導入を行うことにしました。
次の手順でPentAGIをインストール・起動することができます。
dockerコマンドの実行について
以降sudoコマンドなしで docker コマンドを実行していますが、実行するには、dockerコマンドを実行するユーザを予めdocker グループに追加しておく必要があります。
1. PentAGIのソースコードを取得します。
cd pentagi
2. 標準のComposeファイルが参照する設定ファイルを用意します。使わないプロバイダの分も含め、3つとも配置が必要になります。
cp examples/configs/ollama-llama318b.provider.yml example.ollama.provider.yml
cp examples/configs/bedrock.provider.yml example.bedrock.provider.yml
3. 設定ファイルを配置します。
4. 設定ファイル.env を編集します。このファイルには、接続先や認証情報を記述します。主に確認する項目は次のとおりです[7]。
一旦、LLMプロバイダの設定を次の通り行います。
OPEN_AI_SERVER_URL=https://api.openai.com/v1
(省略)
OLLAMA_SERVER_URL=http://192.168.1.48:11434
OLLAMA_SERVER_API_KEY=ollama
OLLAMA_SERVER_MODEL=gpt-oss-20b-64k:latest
※ OLLAMA_SERVER_MODELとして指定しているgpt-oss-20b-64kは、gpt-oss:20bのコンテキスト長をOllamaで64kに拡張したモデルです。 Ollamaはホスト側(192.168.1.48)で動かしています。適宜環境に合わせてIPアドレス部分を変更してください。外部から接続できるようにするため、Ollamaの起動時に環境変数OLLAMA_HOST=0.0.0.0やOLLAMA_ORIGINS=172.17.0.* を設定しています。Ollamaには認証機能がないため、信頼できるネットワーク内だけで使うようにしてください。
あわせて、推測されやすい初期値になっている以下の項目も、初回起動の前に変更しておきます。ランダムな文字列は、たとえばコマンド `openssl rand -hex 32` で作れます。
- COOKIE_SIGNING_SALT=(ランダムな文字列)
- PENTAGI_POSTGRES_PASSWORD=(ランダムな文字列)
- NEO4J_PASSWORD=(ランダムな文字列)
データベースのパスワードは初回起動時に保存されるため、起動後に変更しても反映されない点に注意してください。その他の項目はデフォルト値のまま進めます。
5. 手順4での設定後、次のコマンドでコンテナを起動して状態を確認します。
docker compose ps
コマンド`docker compose ps` で、各コンテナの STATUS が Up(または healthy)になっていれば起動に成功しています。
6. Webブラウザを起動して https://localhost:8443にアクセスします。
自己署名証明書を使っているため、ブラウザに警告が表示されます。自分で起動したサーバであれば、そのまま進めていただいて問題ありません。ログイン画面にアクセスできたら起動成功です。
7. 初期アカウント「admin@pentagi.com」、初期パスワード「admin」でログインして、最初にパスワードを変更します。
次のコマンドで設定を反映できます。設定が変わったコンテナのみが自動で作り直されます。
docker compose up -d
標準の docker-compose.yml では、主に次のコンテナがホストにポートを公開します。いずれも既定では 127.0.0.1(localhost)にバインドされます。
検証用やられサーバの起動
「やられサーバ」とは、攻撃手法・防御手法を学ぶために、意図的に脆弱性を持たせたシステムのことです。PentAGIがこれらの弱点を見つけられるかを試します。
今回は、次の4つの問題を順番につなげて侵入できる「やられサーバ」を用意しました。侵入後に管理者権限まで奪える、という流れを再現しています。
想定する攻撃の流れは次のとおりです。
(b) SNMPでプロセス一覧(a)を取得する
↓
認証情報 testuser/testuser が漏れる
↓
(c)取得した認証情報を基にSSHでログインする
↓
(d)sudo /usr/bin/tar を悪用して root ユーザ権限を奪取する
サーバの作り方は記事末尾の [Appendix-1] にまとめました。次のコマンドで起動できます。
$ docker run -d --name vuln-target --rm vuln-target
起動後、やられサーバのIPアドレスを、例えば次のコマンドで確認しておきます。
$ docker inspect vuln-target | grep '"IPAddress"'
"IPAddress": "172.17.0.3",
このサーバは意図的に脆弱です。インターネットから直接接続できないクローズドなネットワークで起動してください。
PentAGIの使用方法
PentAGIでは、一連の作業を「Flow」として管理します[9]。WebUIのFlowsメニューを開き、画面右上の「+ New Flow」ボタンをクリックします。
表示される新規Flowの作成画面(図3)でモデルと作業内容を指定します。
最初は対象を一つに絞り、目的と終了条件を明確にすると、挙動を追いやすくなります。例えば、次のように指示します(テキストエリアに指示文を入力します)。指示は英語でも日本語でも問題ありませんが、いくつかのローカルモデルでも検証することを考慮し、出力精度への影響を避けるため、システムプロンプトと同じ英語で入力することにしました。
Target: 172.17.0.3
Goal:
Perform an authorized security assessment of the target and identify exposed services, weak configurations, and exploitable vulnerabilities.
Verify whether it is possible to compromise the target by leveraging the identified vulnerabilities and escalate privileges to obtain root user permissions.
Execution requirements:
Use the terminal resource assigned to this flow.
Begin by identifying reachable services and versions.
Do not access any IP address or host other than the target.
Action plan:
1. Network Reconnaissance: ARP scanning, identify network segments, map internal infrastructure
2. Service Discovery: comprehensive port scanning of internal hosts; perform both TCP and UDP scans
Be sure to perform a UDP scan.
Example:
nmap -sU --top-ports=500 --max-rtt-timeout=1s --max-retries=0 §*ipv4*§
Be sure to search the knowledge base for every open port. If relevant knowledge exists, run the commands specified in that knowledge to verify the findings.
3. Credential Attacks: relay attacks, password spraying
4. Vulnerability Exploitation: exploit unpatched services, test default credentials, known CVEs
5. Privilege Escalation: exploit local vulnerabilities, misconfigured services, weak permission settings
6. Report: document internal security resilience, attack path visualization, remediation priorities
Deliverables:
Return a summary of findings with severity, evidence, affected service, and remediation guidance. The deliverables must be written in Japanese.
IPアドレスは環境によって変わりますので、コマンド`docker inspect` で実際のIPアドレスを確認して、適宜変更してください。
上記の「Execution requirements:」のように、文章で実行時の制約条件を指定しておくのがよいと考えます。指示文は予め登録しておいたTemplateを基に作成していくこともできるようになっています。左メニューのTemplatesから事前登録することができます。
指示文を入力した後、図3に示す「Create a new flow」画面左下のプルダウンメニューからモデル/Provider(例えばopenai)を選択し、画面右下の「↑」をクリックします。クリックすると以下の図4のように自動で検査が開始され、画面下のテキストエリアに「PentAGI is working...Click Stop to interrupt」と表示されます。
実行中は、ツールへの指示と応答を確認し、対象や処理内容が想定通りかを見ます。
途中で処理が停止した場合は、画面下のテキストエリアに「Provide additional context or instructions...」と出力されます。ヒントを与えると、タスクが自動生成され、追加で処理が実行されていきます。ヒントを与えながらですが、権限昇格まで到達した画面を以下に示します。
実行後はレポートを読み、重要な指摘について手動で再確認します。
「脆弱性がある可能性」と「再現して確認できた事実」は分けて読む必要があります。また、何も検出されなかった場合も、安全性が証明されたわけではありませんので、それらを踏まえてみていく必要があります。
また、画面右上のタブを切り替えることで、それぞれ以下を確認することができます。
- Terminal:端末で実行されたコマンドおよびその結果を確認することができます。
- Tasks:指示がどのようなタスクに分割され、実行されているのかをリアルタイムで確認することができます(図6)。
- Agents:Primary Agentからほかのエージェントにどのような指示がでたかを確認することができます。
- Searches:実施された外部検索の内容および結果を確認することができます。
- Vector Store:ベクトル検索(知識ストアへの類似検索)の結果などを確認することができます。意図通り知識ストアを参照できているか確認することができます。
- Files:検査で使っているコンテナとファイル/リソースをやりとりしたい場合に利用することができます。
- Screenshots:検査の過程で取得されたキャプチャ画像を参照することができます。
画面上部の「Dashboard」タブに切り替えると、そのFlowで使用したリソースを確認できます。実行したタスク数・ツール呼び出し回数・所要時間に加えて、LLMのトークン使用量と、そのFlowにかかったコスト(課金額)を確認できます。使用量とコストはモデル別・エージェント別にも集計されるため、「どのエージェントにどのモデルを割り当てると、精度とコストのバランスが良いか」を調整する際の参考になります。
1点、Flow操作に関して、考慮に入れておいた方が良い点があります。
図2に示すFlowの一覧画面を参照した際、StatusがWaitingとなっているFlowに紐づくコンテナ(Terminal)は、起動状態のまま存在し続けます。StatusがWaitingになっているFlowで、かつ追加指示を出さないFlowについては、随時Flowを削除するか、StatusをFinishedに変えておくことを推奨します。Flowを削除するか、StatusをFinishedに変えることでコンテナが停止・削除され、マシンリソースが解放されます。操作はFlowsメニューから行うことができます。
FlowのStatus更新/削除を忘れると大量にコンテナが起動した状態のままになりますので、注意してください。
左メニューのResourcesでは、検査で使うコンテナにマウントしたいリソースデータを登録しておくことができます。前述のFilesタブから登録したリソースデータを実行中のFlowと紐づけることにより、実行中コンテナのディレクトリ/work/resources/配下 にリソースデータが配置(マウント)され、検査時に使うことができるようになります。Resources画面から辞書ファイル(rockyou.txt など)を予めアップロードしておいて、検査時(パスワードクラック時)に使用するなどが具体的な利用例になります。
左メニューのKnowledgesでは、コマンド操作などのナレッジ(CheatSheetsなど)を登録しておくことができます。詳細は後述します。FlowのStatusをFinishedに変えたタイミングと思いますが、自動でKnowledgesが幾つか追加されました。PentAGIは、使えば使うほど賢くなる仕組みも備えているようです。
ナレッジの追加方法
自動検査の前にナレッジを登録しておくことで、検査の精度を上げることができます。次の手順でナレッジを追加登録することができます。
- 左メニューからKnowledges画面を開きます。
- 画面右上の「+ New Knowledge」ボタンをクリックします。「Create a new knowledge document」画面(ナレッジの登録画面)に遷移します。
- ペンテスト自動化に関するナレッジを登録したい場合、例えば以下のように設定します。
Document type:guide(guide以外にcodeとanswerを選択できます)
Guide type:pentest(pentest以外にconfigure, development, install, other, useを選択できます)
Question:ナレッジの概要を記載します。※検索時にQuestionは参照されないようです。
Content:コマンドの使用例など、ナレッジを記載していきます。Contentの内容がナレッジ検索時の検索対象になります。
設定例を図8に示します。
4. 記載が完了したら画面右上の「Create」ボタンをクリックします。
Anonymizeボタンをクリックすると、記載内容の匿名化を自動で実施してくれます。意図しない変更になる可能性があるため、一旦記載した内容をクリップボードに退避してから実行した方がよいです。
検査時にKnowledgeが参照されているかどうかは、前述のFlow操作で記載しました「Vector Store」タブから確認することができます。検索結果として、Scoreなども出力されますので、微調整していくことができるようになっています。
APIを用いて自動で検査する方法
APIを使用することで、スクリプトや定期実行の仕組みからFlowを開始できます。ここでは公式のGraphQL APIを使った開始例を紹介します[10]。
実環境のAPI仕様は、次の画面で確認できます。画面を参照する前に認証をパスしておく必要があります。
- GraphQL Playground
https://{PentAGIが稼働している端末のIPアドレス}:8443/api/v1/graphql/playground - REST API
https://{PentAGIが稼働している端末のIPアドレス}:8443/api/v1/swagger/index.html
APIの利用には、API Tokenが必要になります。まずはWeb画面の「Settings」→「API Tokens」でトークンを作成し、表示された値を保存します。
[Appendix-2]に、検証時に使っていたスクリプトを記載します。環境変数 PENTAGI_API_TOKEN で取得したトークンを設定して使うような作りにしています。定期実行に組み込む場合は、重複起動を避ける処理を追加しておいた方がよいと考えます。CI/CDのフローに組み込む際の参考にしていただければと思います。
カスタムProvidersの設定
Web画面の「Settings」→「Providers」の画面で、Primary Agent、Pentester、Searcherなどエージェントの役割ごとに使用するモデルを選択し、カスタムProviderとして登録できるような設定画面があります。適宜、重要なところ(Generator/Refiner/Coderなど)で使用するモデルをカスタマイズすると、精度を上げることができます。
重要な設定ですが、賢いモデル(商用の上位モデルなど)を選ぶと、モデル側の安全機構によって攻撃的な操作が拒否され、処理が先に進まなくなることがありました。これはPentAGIの制限ではなく、モデル提供元のポリシーによるものです。セキュリティのガードが比較的緩いローカルモデルを調整する際に利用することが多くなりそうな機能かなと思いました。
また、筆者が試した範囲では、OpenAI、Ollamaで選択できるモデルを一つのProviderにまとめて登録するような設定は、PentAGI単体ではできないようでした。OpenAIベースで設定を開始した場合、OpenAI関連のモデル一覧のみから、各エージェントで使用するモデルを選択/カスタマイズしていくような形になるようです。
まとめ
PentAGIを使い、自分で用意したやられサーバに対して、自動でペネトレーションテストを実行してみました。ヒントを与えながらではありますが、最終的に権限昇格(root権限の奪取)まで到達することができました。
PentAGIに関して気づいた点などを以下に記載します。
- 対象と目的を言葉で伝えるだけで、エージェントが自ら手順を組み立て、Nmapによるスキャンから権限昇格までを一通り進めてくれる点がよい
- エージェントが途中で臨機応変にtaskを追加/更新していく点がよい
- 実行中に割り込みでヒントを与えると、ヒントに応じて動作を変えてくれる点がよい
- 検査の流れ(taskの実行状況)をWeb画面でトレースできるので、「セキュリティ検査がどういう手順で進むのか」を学ぶ教材としても使えそうな点がよい
- 検査結果を基に自動でKnowledgeを登録してくれる点がよい(使えば使うほど賢くなっていく点がよい)
- WebUI上に出力されるVector Storeのログ/Scoreなどを参考に、Knowledgeを調整できる点がよい
- 指示文の雛形をTemplateとして事前に登録しておける点がよい
- 並行して複数サーバを検証できる点が良い
- Dashboard画面でFlowごとにLLMのトークン使用量・コストなどをモデル別、エージェント別に集計してくれるので、精度とコストバランスを見直す際の参考になる点がよい
- WebAPIを用いて検査を自動化可能で、CI/CDの流れに組み込める点がよい
- ペネトレーションテスト時に使用されるDockerイメージ(Nmapなどのツール格納)を、設定ファイルから自由に変更できる点がよい
- ローカルモデルでも検査を自動化できるKnowledgeセットがあればほしい(追加したい)
- カスタムProvidersでローカルモデルをチューニングした事例などがあれば知りたい(チューニングしてみたい)
- 制約条件の追加などで安全サイドに傾けて動作してくれる点はよいが、システムへの影響が気になるケースもあるので、コマンド実行の前に実施可否を聞いてくれるモードがあるとうれしい(追加してみたい)
- 同じ指示でも実行の度にアウトプットが異なってくるため、複数回実行が必要になる点が気になる(ナレッジ追加で、どの程度調整できるか検証してみたい)
今回は主にOpenAIのモデルを使用してPentAGIの動作を検証しましたが、安全機構に止められずに済むローカルモデルだけで、どこまで同じ検査を完走できるかを継続して検証していきたいと思っています。
今後、LLMの活用によりペネトレーションテスト/セキュリティ診断の領域は大きな変化が生じていきそうです。引き続き動向を注視し、興味深い技術については深く調査していきたいと考えています。本ブログの内容が、少しでも皆様の学習や検証に取り組むきっかけになれば幸いです。
参考文献
[1] PentAGI公式サイト
https://pentagi.com/
[2] VXControl
https://vxcontrol.com/
[3] PentAGIソースコード(MIT License)
https://github.com/vxcontrol/pentagi
[4] Enterprise版とOSS版の比較
https://pentagi.com/enterprise/
[5] Nmap
https://github.com/nmap/nmap
[6] Ollama(MIT License)
https://github.com/ollama/ollama
[7] Installing and Configuring PentAGI
https://github.com/vxcontrol/pentagi/blob/main/examples/guides/installation_configuration.md
[8] Docker Engine:Ubuntuへのインストール
https://docs.docker.com/engine/install/ubuntu/
[9] README:How to Use PentAGI After Login
https://github.com/vxcontrol/pentagi#how-to-use-pentagi-after-login
[10] README:API Access
https://github.com/vxcontrol/pentagi#api-access
Appendix-1 やられサーバのDockerfile
前述の a~d の弱点を持つ「やられサーバ」を、作成するためのDockerfileを以下に記載します。vuln-target/Dockerfileとして保存して使用してください。
# --- 必要なパッケージ ---
RUN apt-get update && \
apt-get install -y --no-install-recommends \
snmpd openssh-server sudo procps && \
rm -rf /var/lib/apt/lists/*
# --- (a) 認証情報を引数で平文指定する常駐プロセス ---
RUN printf '#!/bin/sh\nwhile : ; do sleep 3 ; done\n' > /opt/monitor.sh && \
chmod +x /opt/monitor.sh
# --- (c)(d) 権限昇格に使うユーザと sudo 設定 ---
RUN useradd -m -s /bin/bash testuser && \
echo 'testuser:testuser' | chpasswd && \
usermod -aG adm testuser && \
echo 'Cmnd_Alias ALLOWCMD = /usr/bin/tar' > /etc/sudoers.d/vuln && \
echo '%adm ALL = (ALL) ALLOWCMD' >> /etc/sudoers.d/vuln && \
chmod 440 /etc/sudoers.d/vuln && \
mkdir -p /var/run/sshd
# --- (b) SNMP: コミュニティ名 public で参照可能 ---
RUN printf 'agentaddress udp:161\nview all included .1 80\nrocommunity public default -V all\n' \
> /etc/snmp/snmpd.conf
# --- 起動スクリプト ---
RUN printf '#!/bin/sh\n\
service ssh start\n\
service snmpd start\n\
nohup sh /opt/monitor.sh -u testuser -p testuser >/dev/null 2>&1 &\n\
tail -f /dev/null\n' > /root/init.sh && chmod +x /root/init.sh
EXPOSE 22 161/udp
CMD ["/root/init.sh"]
Appendix-2 フロー自動実行スクリプト
検証では、Web画面を操作せずにFlowを作成・監視するスクリプトを使っていました。使用していたスクリプトを以下に記載します。
PentAGIのAPI(フロー作成はGraphQL、状態確認はREST)を呼び出し、フローが running (実行中)を経て waiting(指示待ち)に到達したら成功とみなして終了するようにしています。cronなどからの定期実行を想定しています。ファイルpentagi-scheduled-flow.shとして保存してください。
実行には curlコマンド と jqコマンド、および有効なAPIトークンが必要です。トークンはWeb画面の設定から発行し、環境変数で渡すようにしています。
export PENTAGI_API_TOKEN="eyJhb(省略)" # 発行したAPIトークンを指定します
export TARGET_IPADDR="172.17.0.3" # 検査対象を指定します
bash pentagi-scheduled-flow.sh
INSECURE_TLS=true(既定)では、自己署名証明書の検証を省略します(コマンドcurlに-kオプションを付与します)。ローカル検証用の設定なので、信頼できる環境以外では使わないでください。
# =================================================================
# PentAGI のフローを API 経由で自動実行するスクリプト
#
# 概要:
# GraphQL API(createFlow)で新規フローを作成し、REST API でステータスを
# ポーリングする。フローが running を経て waiting に到達したら成功とみなし
# て終了する。cron などから定期実行することを想定している。
#
# 必要なもの:
# curl, jq / 有効な PentAGI API トークン
#
# 主な環境変数(未設定時は右記の既定値):
# PENTAGI_URL PentAGI の URL (既定: https://127.0.0.1:8443)
# PENTAGI_API_TOKEN API トークン (必須。未設定ならエラー終了)
# MODEL_PROVIDER 使用するモデル提供元 (既定: openai)
# TARGET_IPADDR 検査対象の IP アドレス(既定: 172.17.0.3)
# POLL_INTERVAL_SECONDS 状態確認の間隔(秒) (既定: 30)
# TIMEOUT_SECONDS 全体のタイムアウト(秒)(既定: 3600)
# INSECURE_TLS 自己署名証明書を許可 (既定: true → curl -k)
#
# 終了コード:
# 0 = waiting に到達(成功) / 1 = エラー / 2 = タイムアウト
# =================================================================
# set -Eeuo pipefail: 未定義変数の参照やコマンド失敗、パイプ途中の失敗で
# 即座に終了させ、エラーの見落としを防ぐ
set -Eeuo pipefail
# --- 設定項目(環境変数で上書き可能。${VAR:-既定値} 形式) -------------------
PENTAGI_URL="${PENTAGI_URL//127.0.0.1:8443}"
# :? を使い、トークン未設定なら明示的にエラーメッセージを出して終了する
PENTAGI_API_TOKEN="${PENTAGI_API_TOKEN:?PENTAGI_API_TOKENが未設定です}"
# 使用するモデル提供元。下の行のコメントを外せば他の提供元に切り替えられる
MODEL_PROVIDER="${MODEL_PROVIDER:-openai}"
#MODEL_PROVIDER="${MODEL_PROVIDER:-anthropic}"
#MODEL_PROVIDER="${MODEL_PROVIDER:-ollama}"
#MODEL_PROVIDER="${MODEL_PROVIDER:-openai-custom3}"
TARGET_IPADDR="${TARGET_IPADDR:-172.17.0.3}"
POLL_INTERVAL_SECONDS="${POLL_INTERVAL_SECONDS:-30}"
TIMEOUT_SECONDS="${TIMEOUT_SECONDS:-3600}"
# true の場合、後段で curl に -k を付けて証明書検証をスキップする
INSECURE_TLS="${INSECURE_TLS:-true}"
# --- フローへ渡す指示文(プロンプト) ---------------------------------------
# ここから下のヒアドキュメント本文が、そのまま PentAGI への指示として送られる。
# ${TARGET_IPADDR} のみ変数展開される。文面を変えると検査内容が変わる点に注意。
TASK_DESCRIPTION=$(cat <<EOF
Target: ${TARGET_IPADDR}
Goal:
Perform an authorized security assessment of the target and identify exposed services, weak configurations, and exploitable vulnerabilities.
Verify whether it is possible to compromise the target by leveraging the identified vulnerabilities and escalate privileges to obtain root user permissions.
Execution requirements:
Use the terminal resource assigned to this flow.
Begin by identifying reachable services and versions.
Do not access any IP address or host other than the target.
Action plan:
1. Network Reconnaissance: ARP scanning, identify network segments, map internal infrastructure
2. Service Discovery: comprehensive port scanning of internal hosts; perform both TCP and UDP scans
Be sure to perform a UDP scan.
Example:
nmap -sU --top-ports=500 --max-rtt-timeout=1s --max-retries=0 §*ipv4*§
Be sure to search the knowledge base for every open port. If relevant knowledge exists, run the commands specified in that knowledge to verify the findings.
3. Credential Attacks: relay attacks, password spraying
4. Vulnerability Exploitation: exploit unpatched services, test default credentials, known CVEs
5. Privilege Escalation: exploit local vulnerabilities, misconfigured services, weak permission settings
6. Report: document internal security resilience, attack path visualization, remediation priorities
Deliverables:
Return a summary of findings with severity, evidence, affected service, and remediation guidance. The deliverables must be written in Japanese.
EOF
)
# --- 前提コマンドの存在確認 -------------------------------------------------
for cmd in curl jq; do
command -v "$cmd" >/dev/null || { echo "$cmd が必要です" >&2; exit 1; }
done
# URL 末尾の / を除去してパス連結時の // を防ぐ
PENTAGI_URL="${PENTAGI_URL%/}"
# 全 curl 呼び出しで共通のオプション(静かに実行/失敗時も本文表示/認証ヘッダ)
curl_opts=(-sS --fail-with-body -H "Authorization: Bearer ${PENTAGI_API_TOKEN}")
if [[ "$INSECURE_TLS" == true ]]; then curl_opts+=(-k); fi
# --- フローの作成(GraphQL mutation) ---------------------------------------
# createFlow に provider と input(指示文)を渡し、id/title/status を受け取る
query='mutation($provider:String!,$input:String!){createFlow(modelProvider:$provider,input:$input){id title status}}'
# jq -n でクエリと変数を JSON に組み立てる(特殊文字のエスケープも jq に任せる)
payload=$(jq -nc --arg query "$query" --arg provider "$MODEL_PROVIDER" \
--arg input "$TASK_DESCRIPTION" \
'{query:$query,variables:{provider:$provider,input:$input}}')
created=$(curl "${curl_opts[@]}" -H 'Content-Type: application/json' \
--data-binary "$payload" "${PENTAGI_URL}/api/v1/graphql")
# GraphQL は HTTP 200 でも errors を返すことがあるため、本文側で判定する
if jq -e '.errors and (.errors | length > 0)' <<<"$created" >/dev/null; then
echo "$created" >&2
exit 1
fi
# 作成されたフローの ID を取得(取れなければ中断)
FLOW_ID=$(jq -er '.data.createFlow.id // empty' <<<"$created") || {
echo "フローIDを取得できませんでした" >&2
exit 1
}
# 初期ステータスを控え、以降のポーリングで running を観測済みか追跡する
initial_status=$(jq -r '.data.createFlow.status // empty' <<<"$created")
seen_running=false
if [[ "$initial_status" == running ]]; then seen_running=true; fi
echo "flow_id=${FLOW_ID} initial_status=${initial_status}" >&2
# --- ステータスのポーリング -------------------------------------------------
# SECONDS は bash の組み込み変数で、0 代入後の経過秒数を自動で数える。
# TIMEOUT_SECONDS を超えるまで、一定間隔でフローの状態を確認し続ける。
SECONDS=0
last_status="$initial_status"
while (( SECONDS < TIMEOUT_SECONDS )); do
# フロー一覧(init タイプ)を取得する
response=$(curl "${curl_opts[@]}" \
"${PENTAGI_URL}/api/v1/flows/?page=1&type=init")
# 応答が期待する配列形式かを確認する
jq -e '(.data.flows | type) == "array"' <<<"$response" >/dev/null || {
echo "フロー一覧の応答形式が不正です" >&2
exit 1
}
# 一覧から対象の FLOW_ID の要素を抜き出す
flow=$(jq -c --arg id "$FLOW_ID" \
'.data.flows[] | select((.id | tostring) == $id)' <<<"$response")
# まだ一覧に現れていなければ、待って再試行する
if [[ -z "$flow" ]]; then
sleep "$POLL_INTERVAL_SECONDS"
continue
fi
# 状態が前回から変化したときだけログを出す(出力の重複を抑える)
status=$(jq -r '.status // empty' <<<"$flow")
if [[ "$status" != "$last_status" ]]; then
echo "flow_id=${FLOW_ID} status=${status}" >&2
last_status="$status"
fi
case "$status" in
running)
# 稼働を確認。waiting 判定の前提になるフラグを立てる
seen_running=true
;;
waiting)
# 一度 running を経てからの waiting を「指示待ち=成功」とみなす。
# (作成直後の waiting を誤検知しないよう seen_running で保護)
if [[ "$seen_running" == true ]]; then
title=$(jq -r '.title // "(タイトルなし)"' <<<"$flow")
printf 'flow_id=%s title=%s status=waiting\n' "$FLOW_ID" "$title"
exit 0
fi
;;
created|queued|pending|working|in_progress)
# 処理継続中の状態。何もせず次のポーリングへ
;;
finished|completed|complete|succeeded|done|success|failed|failure|error|cancelled|canceled|stopped)
# waiting に至らず終了してしまったケースは失敗として扱う
echo "waitingになる前にフローが終了しました: ${status}" >&2
exit 1
;;
*)
# 想定外の状態は安全側に倒してエラー終了する
echo "不明な状態です: ${status}" >&2
exit 1
;;
esac
sleep "$POLL_INTERVAL_SECONDS"
done
# ループを抜けた=制限時間内に waiting に到達しなかった
echo "タイムアウトしました: ${TIMEOUT_SECONDS}秒" >&2
exit 2
執筆者プロフィール
木津 由也(きづ よしや)
担当領域:リスクハンティング
主にネットワークセキュリティ製品・サービスの開発に従事してきたが、最近はCTFに取り組んできた経験を活かし、ペネトレーションテスト、脆弱性診断などの領域にも仕事の範囲を拡大中。
2013年にnoraneco という社会人CTF チームを立ち上げ、現在は主にPwn/Reversing 問を担当。
SANS - Cyber Defense NetWars 2019.10 1位(Team)
SECCON 2019 国際決勝5位
Hack The Box - Omniscient