라우팅 가능한 DNS 환경과 대상별 기계 판독 가능 정답 키를 갖춘 의도적으로 취약한 Docker 실습 환경으로, 스캐너의 정밀도, 재현율, 범위를 로컬에서 채점합니다.
보안 테스트 랩. 의도적으로 취약하게 만든 타깃들의 플릿, 자산 탐색을 위해 열거할 권한 있는 DNS를 갖춘 라우팅 가능한 네트워크 자산, 타깃별 기계 판독 가능한 정답 키, 그리고 이 모든 것을 구동하는 제어 패널.
여기 있는 모든 것은 의도적으로 취약합니다. 로컬 테스트 전용입니다. 인터넷이나 신뢰할 수 없는 네트워크에 노출하지 마십시오. 게시된 포트는
127.0.0.1에 바인딩되며, 랩 타깃은 아무것에도 바인딩되지 않습니다.우리 자체 스캐너는 이 컨테이너들 안에서 의도적으로 RCE를 얻으므로, 컨테이너는 보안 경계로 취급됩니다. 모든 이미지는 다이제스트로 고정되고, 모든 서비스는 모든 capability를 드롭한 뒤 최소한만 다시 추가하며,
./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 # 언제든 다시 마법사 실행
./lime start --all # 모든 라이트 타깃
./lime start crapi --heavy # 헤비 타깃을 명시적으로
./lime scenario-up estate # 네트워크 자산: DNS, vhost, 서비스
./lime status # 무엇이 떠 있는지
./lime stop --all --heavy # 전부 내림; 이미지와 볼륨은 유지
./lime credits # 각 타깃을 누가 어떤 라이선스로 작성했는지
./lime doctor # 환경, 저작자 표시, 디스크 검사
./lime doctor --fix # 모든 검사의 자동 해결책을 적용한 뒤 재검사
./lime audit # 컨테이너 하드닝 + 공급망 불변식
./lime pin # 레지스트리 대비 이미지 드리프트 보고
설치 프로그램 없이 수동으로:
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 # 필수, SECURITY.md 참조
docker compose up -d --build # 컨트롤 플레인 + UI는 http://127.0.0.1:7000
./lime setup
모든 매니페스트는 측정된 resources 블록(컨테이너, 유휴 RAM, 이미지 디스크, 유휴 CPU)을 담고 있습니다. 마법사, 패널의 선택 스트립, 각 타깃 페이지가 여기서 합산하므로 추정치는 어디서나 동일합니다.
둘, 오직 둘뿐입니다.
main**은 설치 프로그램이 클론하는 것이며 아무것도 하지 않으면 얻게 되는 것입니다. 풀 리퀘스트로만 이동하며, 직접 푸시로는 절대 이동하지 않습니다.dev**는 기본 브랜치이며 작업이 도착하는 곳입니다. 풀 리퀘스트는 이 브랜치를 대상으로 여십시오.| target | 선언된 kind의 테스트 대상 하나. compose 파일, 선택적 setup, 자체 정답 키를 소유합니다. 자체 격리된 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/ 데몬: CLI + HTTP API + 스코어러
control/ui/ SvelteKit 제어 패널
truth/ 계약, 그리고 날짜별 스코어카드
docker compose up -d는 두 컨테이너만 시작하고 그 외에는 아무것도 시작하지 않습니다: limeyard_control(Docker 소켓을 보유한 limed 데몬)과 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, 볼 수 있는 이력, 두 실행 간 diff |
| 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 목록, 상태와 저작자 표시 포함
GET /api/targets/<slug> truth, 이미지, 랩 주소 포함
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}: 풀 3개, 슬러그별 거부
GET /api/scenarios 호스트별 컨테이너 상태 포함
POST /api/scenarios/<slug>/<action> up | down | restart
GET /api/scorecards 최신순, by_class에 오탐 포함
GET /api/scorecards/<id> 카드 하나
POST /api/score {tool, findings, save?, targets?}
GET /api/doctor 판정, 이유, 값, 항목, 수정이 있는 검사
POST /api/doctor/fix {ids}: 해당 검사들, 비어 있으면 수정 가능한 모든 검사
GET /api/ports /api/credits /api/truth /api/status
GET /api/events SSE: state, scenario, tick
세 계층입니다. 하나였던 것이 원래 문제였기 때문입니다.
lime-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 | 웹 및 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 매니페스트, 필수 upstream 블록 포함
compose.yml 컨테이너. 127.0.0.1 바인딩만
setup.sh 선택적 일회성 초기화, 시작 후 실행
truth.yml 정답 키
랩을 깨끗하게 유지하는 규칙:
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는 호스트의 root인 Docker 소켓을 보유하므로 모든 호출에 공유 비밀을 요구합니다. 뚫린 타깃이 그것에 도달해도 아무것도 알 수 없습니다../lime audit은 privileged, 호스트 네트워킹, 타깃 내 소켓 마운트, 루프백 외 바인딩, 고정되지 않은 이미지, 누락된 토큰에서 실패합니다.여기 있는 어떤 것도 커널 수준 컨테이너 탈출을 방어하지 않습니다. 그것에는 일회용 VM을 사용하십시오.
여기 있는 거의 모든 것은 다른 누군가가 작성했으며, 여러 타깃은 라이선스를 전혀 선언하지 않습니다. 따라서 저자를 명시하는 것은 관례가 아니라 강제 게이트입니다.
target.yml은 필수 upstream 블록을 담습니다: 저자, repo, 라이선스, 그리고 마지막으로 빌드를 검증한 날짜. 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 |