जानबूझकर कमजोर 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 स्कोर किया, शून्य चूक, शून्य गलत सकारात्मक। जो बेंचमार्क विफल नहीं हो सकता वह रिग्रेशन का पता नहीं लगा सकता। संरचनात्मक रूप से तीन चीज़ें गलत थीं:
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)। विज़ार्ड, पैनल की चयन पट्टी और प्रत्येक लक्ष्य का पृष्ठ इससे योग करते हैं, इसलिए अनुमान हर जगह समान होता है।
दो, और केवल दो।
main वह है जिसे इंस्टॉलर क्लोन करता है और जो आपको मिलता है यदि आप कुछ नहीं करते। यह पुल रिक्वेस्ट द्वारा आगे बढ़ती है, कभी सीधे पुश द्वारा नहीं।dev डिफ़ॉल्ट ब्रांच है और जहाँ काम आता है। इसके विरुद्ध पुल रिक्वेस्ट खोलें।| target | परीक्षण के अधीन एक चीज़, घोषित kind की। एक compose फ़ाइल, वैकल्पिक सेटअप, और अपनी उत्तर कुंजी रखती है। अपने स्वयं के पृथक compose प्रोजेक्ट के रूप में चलती है, इसलिए Postgres का उपयोग करने वाले दो लक्ष्य कभी एक साझा नहीं करते |
| 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 दो कंटेनर शुरू करता है और कुछ नहीं: 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 | डेल्टा के साथ नवीनतम रन, प्रति-वर्ग और प्रति-लक्ष्य कवरेज, छूटे हुए आईडी, एक इतिहास जिसे आप देख सकते हैं, और दो-रन का अंतर |
| Ports | localhost पर क्या बाइंड होता है, और क्या केवल लैब ब्रिज पर मौजूद है |
| Doctor | प्रत्येक के लिए एक निर्णय के साथ जाँचों की एक सूची। Fix और Fix all पहले सटीक कमांड और फ़ाइल संपादन दिखाते हैं, जैसा लैब है उससे गणना करके, और पुष्टि पर उन्हें चलाते हैं। जो फिक्स अपनी जाँच को विफल छोड़ता है वह ऐसा बताता है |
| Credits | प्रत्येक लक्ष्य किसने लिखा और किस लाइसेंस के अंतर्गत |
पैनल स्वयं को अद्यतन करता है: limed SSE पर स्थिति संक्रमण स्ट्रीम करता है, इसलिए CLI से शुरू किया गया लक्ष्य बिना रीफ्रेश के दिखाई देता है। हेडर उसी स्ट्रीम से होस्ट का CPU, RAM और खाली डिस्क रखता है, रंग केवल तब जब वे ध्यान देने योग्य हों। प्रत्येक तालिका कॉलम हेडर पर क्लिक करके क्रमबद्ध होती है; दूसरा क्लिक दिशा पलट देता है।
पैनल या डेमॉन में बदलाव के बाद, जोड़ी को पुनः बनाएँ:
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
तीन स्तर, क्योंकि एक ही मूल समस्या थी।
lime-web ब्रिज। Web और API लक्ष्य, 127.0.0.1:70xx पर प्रकाशित।lime-lab ब्रिज, 10.66.0.0/16, स्थिर IP, कोई होस्ट बाइंडिंग नहीं। एक स्कैनर इस नेटवर्क में एक कंटेनर के रूप में जुड़ता है और लूपबैक पोर्ट सूची के बजाय वास्तविक होस्ट और वास्तविक पोर्ट वाला वास्तविक सबनेट देखता है।lime-edge WAF स्तर, जिसमें ओरिजिन पहुँच योग्य है लेकिन DNS से अनुपस्थित है।DNS .test ज़ोन पर प्राधिकृत BIND है (RFC 6761 इसे आरक्षित करता है)। 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":[...]}'
तीन चीज़ें गिनी जाती हैं, एक नहीं। रिकॉल: क्या हमने वह पाया जो वहाँ है।
सटीकता: क्या हमने वह रिपोर्ट करने से बचा जो नहीं है, प्रत्येक उत्तर कुंजी में मौजूद negative प्रविष्टियों के विरुद्ध मापा गया। दायरा: जो हमने सही ढंग से प्रयास नहीं किया, दर्ज किया गया ताकि कोई भी इसे हर तिमाही फिर से न उठाए।
mirage लक्ष्य केवल दूसरे के लिए मौजूद है। इसमें कुछ भी कमजोर नहीं है और इसमें सब कुछ ऐसा दिखता है, इसलिए इसके विरुद्ध कोई भी निष्कर्ष निर्माण से एक गलत सकारात्मक है।
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 (एक व्यक्ति), ऐसे ही नामित हैं।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 न कहे।
| लक्ष्य | लेखक | लाइसेंस | स्रोत |
|---|---|---|---|
| mirage | Clickswave | MIT | repo |
| लक्ष्य | लेखक | लाइसेंस | स्रोत |
|---|---|---|---|
| Log4Shell lab | Christophe Tafani-Dereeper (christophetd) | Apache-2.0 | repo |
| लक्ष्य | लेखक | लाइसेंस | स्रोत |
|---|---|---|---|
| ModSecurity CRS pair | OWASP Core Rule Set project (coreruleset) | Apache-2.0 | repo |
| लक्ष्य | लेखक | लाइसेंस | स्रोत |
|---|---|---|---|
| AndroGoat | Satish Patnayak | none declared | repo |
| परिदृश्य | लेखक | लाइसेंस | स्रोत |
|---|---|---|---|
| estate | Clickswave | MIT | - |
| लक्ष्य | लेखक | लाइसेंस | स्रोत |
|---|---|---|---|
| Open services | Clickswave (composition of upstream official images) | mixed, per-image | - |
| लक्ष्य | लेखक | लाइसेंस | स्रोत |
|---|---|---|---|
| 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 |