意図的に脆弱なDockerラボ。ルーティング可能なDNS環境と、ターゲットごとの機械可読な解答キーを備え、スキャナーの適合率、再現率、スコープをローカルで採点します。
セキュリティテスト用ラボ。意図的に脆弱に作られたターゲット群、資産探索で列挙するための権威DNSを備えたルーティング可能なネットワーク環境、ターゲットごとの機械可読な解答キー、そしてそれらすべてを操作するためのコントロールパネル。
ここにあるものはすべて意図的に脆弱です。ローカルテスト専用。 インターネットや信頼できないネットワークに公開しないでください。公開されるポートは
127.0.0.1にバインドされ、ラボのターゲットは一切バインドされません。私たち自身のスキャナは、これらのコンテナ内で意図的にRCEを取得するため、コンテナはセキュリティ境界として扱われます。すべてのイメージはダイジェストで固定され、すべてのサービスはすべてのケーパビリティを削除した上で最小限を追加し、
./lime auditがそれを強制します。初回実行前に SECURITY.md を読んでください。コンテナ分離がカバーしない範囲についての記述も含まれます。
http://127.0.0.1:7000 のコントロールパネル。実行中のラボを表示。
limeyardは以前 vuln_apps でした。アプリケーションのフォルダではなくなったため改名されました。現在はベアサービス、DNSゾーン、WAFペア、精密ターゲット、APKフィクスチャを保持しており、そのいずれもアプリではありません。
旧来のフリートは9/9を獲得し、ミスゼロ、誤検知ゼロでした。失敗できないベンチマークはリグレッションを検出できません。構造的に3つの問題がありました。
127.0.0.1:70xx だったため、サブドメイン列挙には列挙するものがなく、ポートスキャンは答えを渡され、サービスフィンガープリンティングは非HTTPデーモンを見ることがありませんでした。必要なのはDocker(composeプラグイン付き)とgitだけです。それ以外は何も要りません。
curl -fsSL https://raw.githubusercontent.com/clickswave/limeyard/main/install.sh | bash
これによりラボが ./limeyard にクローンされ、新しいAPIトークンを含む .env が書き込まれ、コントロールプレーンがビルド・起動され、何を実行するか尋ねられます。何かが始まる前に、その選択にかかるコストを、参照マシンでアイドル時に測定した値として、あなたのマシンの空き容量と比較して表示します。
This selection, idle, on the box it was measured on:
17 targets, 1 scenarios, 45 containers
RAM about 2.9 GB resident (host has 22.4 GB available)
disk about 11.0 GB of images to pull (host has 111 GB free)
CPU near idle once up (3% of one core); pulling and first boots are the busy part
Start it? [y/N]
非対話形式: curl ... | bash -s -- --light --yes(または --all、--none、--pick dvwa,juice-shop,estate)。チェックアウト先を別の場所にするには LIMEYARD_DIR=/path。
パネルは http://127.0.0.1:7000 にあり、同じことを手動で行うには:
./lime setup # the wizard again, any time
./lime start --all # every light target
./lime start crapi --heavy # a heavy one, explicitly
./lime scenario-up estate # the network estate: DNS, vhosts, services
./lime status # what is up
./lime stop --all --heavy # everything down; images and volumes stay
./lime credits # who wrote each target, and under what licence
./lime doctor # environment, attribution and disk checks
./lime doctor --fix # apply every check's automatic remedy, then re-check
./lime audit # container hardening + supply chain invariants
./lime pin # report image drift against the registry
インストーラを使わず手動で:
git clone https://github.com/clickswave/limeyard && cd limeyard
cp .env.example .env
echo "LIMEYARD_DIR=$PWD" >> .env
echo "LIME_TOKEN=$(openssl rand -hex 24)" >> .env # required, see SECURITY.md
docker compose up -d --build # control plane + UI on http://127.0.0.1:7000
./lime setup
すべてのマニフェストには測定済みの resources ブロック(コンテナ、アイドルRAM、イメージディスク、アイドルCPU)が含まれます。ウィザード、パネルの選択ストリップ、各ターゲットのページはこれをもとに合計するため、見積もりはどこでも同じになります。
2つだけ、それだけです。
main はインストーラがクローンするもので、何もしなければ得られるものです。プルリクエストによってのみ移動し、直接プッシュされることはありません。dev はデフォルトブランチであり、作業が着地する場所です。プルリクエストはこれに対して開いてください。| target | テスト対象の1つ。宣言された kind を持ちます。composeファイル、任意のセットアップ、独自の解答キーを所有します。独自の分離されたcomposeプロジェクトとして実行されるため、Postgresを使う2つのターゲットが共有することはありません |
| scenario | 権威DNSを備えたネットワークトポロジに配線された複数のターゲット。資産探索がこれに対して採点されます |
| truth | 機械可読な解答キー。truth/schema.md を参照 |
| doctor | それぞれに判定を伴うチェックのリスト: 環境、帰属、サプライチェーン、ハードニング。明確な対処法を持つチェックには、パネル(/doctor)でのワンクリック修正とCLIの --fix があります: ネットワークの作成、ディスクの回収、イメージの固定、ソースの取得、実行中ターゲットの再検証、ループバック外バインドの書き換え。帰属、ポート競合、ハードニングには人が必要です |
種類: web api bench cve service estate edge control mobile。
targets/<kind>/<slug>/ target.yml, compose.yml, setup.sh, truth.yml
scenarios/<slug>/ scenario.yml, compose.yml, zones/
control/limed/ the daemon: CLI + HTTP API + scorer
control/ui/ the SvelteKit control panel
truth/ the contract, and dated scorecards
docker compose up -d は2つのコンテナだけを起動します: limeyard_control(limedデーモン、Dockerソケットを保持)と limeyard_ui(SvelteKitパネル)。どちらもループバックのみにバインドします。パネルは http://127.0.0.1:7000、生のAPIは http://127.0.0.1:7099 です。どちらも .env を必要とし、その中の LIME_TOKEN は必須です。パネルはトークンをサーバー側で保持し、ブラウザがそれを見ることはありません。
| ページ | 用途 |
|---|---|
| Targets | すべてのターゲット。種類と状態でフィルタ、ソート、複数選択してStart、Stop、Restart。行をクリックするとターゲットへ |
| Target | 事実(アドレス、認証情報、スタック、アップストリーム、検証、イメージダイジェスト)、ライブログ、およびネガティブを含む解答キー |
| Scenarios | エステート: リゾルバ、ゾーン、サブネット、コンテナごとの状態を持つホストテーブル。起動、停止、再起動 |
| Scorecard | 差分付きの最新実行、クラス別およびターゲット別のカバレッジ、見逃したID、閲覧可能な履歴、2回の実行の差分 |
| Ports | localhostでバインドされるもの、およびラボブリッジにのみ存在するもの |
| Doctor | それぞれに判定を伴うチェックのリスト。FixとFix allは、ラボの現状から計算された正確なコマンドとファイル編集を最初に表示し、確認後に実行します。チェックを失敗させたままにする修正はその旨を報告します |
| Credits | 各ターゲットを誰がどのライセンスで書いたか |
パネルは自動更新されます: limedは状態遷移をSSEでストリーミングするため、CLIから起動されたターゲットはリフレッシュなしで表示されます。ヘッダーは同じストリームからホストのCPU、RAM、空きディスクを表示し、注目に値する場合にのみ色付けされます。すべてのテーブルは列ヘッダーをクリックするとソートされ、2回目のクリックで方向が反転します。
パネルまたはデーモンを変更した後は、ペアを再ビルドします:
docker compose up -d --build
イメージを再ビルドせずに実行中のデーモンに対してパネルを操作するには:
cd control/ui && npm install
LIMED_URL=http://127.0.0.1:7099 LIME_TOKEN=<from .env> npm run dev # :7000
/api/health を除くすべての呼び出しには X-Lime-Token が必要です。
GET /api/targets list, with state and attribution
GET /api/targets/<slug> plus truth, images, lab addresses
GET /api/targets/<slug>/logs SSE, docker compose logs -f
POST /api/targets/<slug>/<action> start | stop | restart | pull | setup
POST /api/targets/bulk {action, slugs}: a pool of three, per-slug refusals
GET /api/scenarios with per-host container state
POST /api/scenarios/<slug>/<action> up | down | restart
GET /api/scorecards newest first, by_class carries false positives
GET /api/scorecards/<id> one card
POST /api/score {tool, findings, save?, targets?}
GET /api/doctor checks with verdict, reason, value, items, fix
POST /api/doctor/fix {ids}: those checks, or every fixable one when empty
GET /api/ports /api/credits /api/truth /api/status
GET /api/events SSE: state, scenario, tick
3つの階層。1つだったことが元々の問題でした。
lime-web ブリッジ。WebおよびAPIターゲット。127.0.0.1:70xx で公開。lime-lab ブリッジ、10.66.0.0/16、静的IP、ホストバインドなし。スキャナはコンテナとしてこのネットワークに参加し、ループバックのポートリストではなく、実際のサブネット、実際のホスト、実際のポートを見ます。lime-edge WAF階層。オリジンには到達可能だがDNSには存在しません。DNSは .test ゾーン(RFC 6761が予約)上の権威BINDです。Dockerネットワークエイリアスは意図的に信頼できる情報源ではありません。ゾーン転送に決して現れず、トポロジが解答キーと食い違うことになるからです。
| 範囲 | 用途 |
|---|---|
| 7000 | UI |
| 7099 | limed API |
| 7001-7099 | webおよびapiターゲット |
| 7100-7199 | ベンチマークスイート |
| 7200-7299 | CVEラボ |
| 7300-7399 | edgeおよびcontrolターゲット |
| 5353 | ラボDNS |
| なし | serviceおよびestateターゲット、lime-lab アドレスのみ |
すべてのターゲットは truth.yml を同梱します。スコアラは検出結果を精度、再現率、F1に変換します。ターゲット別およびクラス別に:
curl -s -XPOST localhost:7099/api/score -H 'Content-Type: application/json' \
-d '{"tool":"crossfyre","save":true,"findings":[...]}'
数えられるのは1つではなく3つです。再現率: そこにあるものを見つけたか。精度: ないものを報告するのを避けたか。すべての解答キーが持つ negative エントリに対して測定されます。スコープ: 正しく試みなかったもの。四半期ごとに誰も蒸し返さないように記録されます。
mirage ターゲットは2つ目のためだけに存在します。その中の何も脆弱ではなく、その中のすべてが脆弱に見えるため、それに対する検出結果は構造的に誤検知です。
CONTRIBUTING.md にすべてが書かれています: コントリビューションが通常何であるか、./lime audit が強制する不変条件、そしてなぜ解答キーへの修正がここでは新機能よりも価値があるのか。ルールの短縮版は以下です。参加するすべての人は行動規範に従うことが求められます。
targets/<kind>/<slug>/
target.yml manifest, including a REQUIRED upstream block
compose.yml the containers. 127.0.0.1 binds only
setup.sh optional one-time init, run after start
truth.yml the answer key
ラボをクリーンに保つルール:
127.0.0.1 にバインドする。[lime-web] のみに参加する。プロジェクトごとのネットワークを追加しないこと: ネットワークが多すぎるとDockerのアドレスプールが枯渇します。[default, lime-web] に参加し、データベースは [default] のみに置く。各ターゲットは独自のデータベースサービスとボリュームを持ちます。[lime-lab] に参加し、ホストポートを公開しない。upstream は必須です。 lime doctor はそれがないターゲットを失敗させ、マネージャは登録を拒否します。以下を参照。repo: と compose: を書けば、ソースは実行時に <target>/src に取得されます。./lime measure <slug> が貼り付けるべき resources ブロックを出力します。インストーラとパネルはこれらを合計して、起動前に警告するため、ここでの推測はそこでの嘘になります。ターゲットは他人の意図的に脆弱なソフトウェアであるため、出所は仮定されるのではなく記録され、ランタイムは信頼されるのではなく制約されます。SECURITY.md に全体像があります。短縮版:
./lime pin がドリフトを報告します。raesene/bwapp(アーカイブ済み、最終リビルド2022年、ライセンスなし)と delfer/alpine-ftp-server(個人1人)はそのように明記されています。no-new-privileges、cap_drop: ALL に加えてイメージごとの最小限の cap_add、pid上限、メモリ上限で実行されます。データベース階層は外部へのルートを持たない internal: true ネットワーク上にあります。limed はDockerソケットを保持しており、これはホスト上のrootであるため、すべての呼び出しで共有シークレットを要求します。侵害されたターゲットがそれに到達しても何も学べません。./lime audit は privileged、ホストネットワーキング、ターゲット内のソケットマウント、ループバック外バインド、固定されていないイメージ、欠落したトークンで失敗します。ここにあるものはカーネルレベルのコンテナエスケープに対して防御しません。それには使い捨てのVMを使ってください。
ここにあるほぼすべては他人によって書かれ、いくつかのターゲットはライセンスを一切宣言していません。したがって、作者をクレジットすることは慣習ではなく厳格なゲートです:
target.yml は必須の upstream ブロックを持ちます: 作者、リポジトリ、ライセンス、そして最後にビルドを検証した日付。packager は、書いた人と異なる場合に何かをコンテナ化した人を記録します。none declared のライセンスは警告としてレンダリングされ、これは再配布禁止のシグナルでもあります。/credits と ./lime credits はすべてのターゲット、作者、ライセンスを一覧表示します。./lime credits --markdown は以下のセクションを再生成します。limeyardは他人の作品を実行します。以下のすべてのターゲットとシナリオは、Clickswaveと書かれていない限り、他人によって作られました。
| target | author | licence | source |
|---|---|---|---|
| mirage | Clickswave | MIT | repo |
| target | author | licence | source |
|---|---|---|---|
| Log4Shell lab | Christophe Tafani-Dereeper (christophetd) | Apache-2.0 | repo |
| target | author | licence | source |
|---|---|---|---|
| ModSecurity CRS pair | OWASP Core Rule Set project (coreruleset) | Apache-2.0 | repo |
| target | author | licence | source |
|---|---|---|---|
| AndroGoat | Satish Patnayak | none declared | repo |
| scenario | author | licence | source |
|---|---|---|---|
| estate | Clickswave | MIT | - |
| target | author | licence | source |
|---|---|---|---|
| Open services | Clickswave (composition of upstream official images) | mixed, per-image | - |
| target | author | licence | source |
|---|---|---|---|
| bWAPP | Malik Mesellem (pkg: Rory McCune (raesene)) | none declared | repo |
| DVWA | Robin Wood (digininja) | GPL-3.0 | repo |
| FaultLine ISP | Clickswave | MIT | repo |
| OWASP Juice Shop | Bjoern Kimminich (OWASP Juice Shop project) | MIT | repo |
| OWASP Mutillidae II | Jeremy Druin (webpwnized), OWASP Mutillidae II | GPL-3.0 | repo |
| OWASP RailsGoat | OWASP RailsGoat project | MIT | repo |
| OWASP WebGoat + WebWolf | OWASP WebGoat project | GPL-2.0 | repo |