ZAP OAST 릴리즈! 이제 ZAP에서 Out-Of-Band가 더 쉬워집니다 🚀

오늘 ZAP OAST가 Alpha 버전으로 release 되었습니다. 지난번에 이야기드린대로 OAST는 callback 과 비슷하게 Out-Of-Band를 식별하기 위한 도구로 SSRF, RCE 등에서 굉장히 유용하게 사용할 수 있습니다.

정말 릴리즈 순간에 보게된 것 같습니다. 5분 차이로 없다가 생겼어요

겸사겸사 몇가지 살펴봤는데요, 지난번 글에서 예상했듯이 odiss.eu 도메인에 미리 구성되어 있는 BOAST가 있긴 하지만, BOAST 서버를 직접 구축하고 사용하는게 가장 좋은 사용 방법으로 보이네요.

ZAP OAST

ZAP OAST는 BurpSuite의 collaborator, project-discovery의 interactsh 같이 OOB(Out-Of-Bound) 테스트를 위해 DNS Query, HTTP Request 등이 발생하면 사용자에게 어떤 요청이 발생했는지 알려주는 도구입니다.

기본적으로 Burp Collaborator와 같이 커스텀 도메인 기반의 Callback 서버를 지원하며, 오픈소스 도구인 BOAST 를 별도로 구축하여 본인만의 Callback 서버를 구성할 수도 있습니다.

DNS, HTTP, HTTPS 등 OOB 테스트에 필요한 대다수 프로토콜을 처리할 수 있어서, ZAP 사용자 입장에선 정말 큰 기능이 추가된 것 같네요.

Setup OAST

Options > OAST에 들어가서 Endpoint URI와 ID, Canary 값을 세팅할 수 있습니다.

여기서 Register 버튼을 눌러 odiss.eu에서 ID와 Canary 값을 받아올 수 있습니다.

Register에 대한 스펙은 https://github.com/marcoagner/boast/blob/master/docs/interacting.md 참고 해주시면 될 것 같습니다.

curl -H "Authorization: Secret kkMrhv3ic2Em63PH6duIejNVRiqyOYpfBZHkjTDswBk=" https://example.com:1337/events
{"id":"cxcjyaf5wahkidrp2zvhxe6ola","canary":"x7ilthx62hx2kfyvsioydd43da","events":[]}

Use Interaction

아까 ZAP OAST에서 Register를 통해 얻어온 ID 값을 가지고 odiss.eu에 개인용으로 사용할 수 있는 개별 주소를 할당받을 수 있습니다. 그래서 이 주소에 HTTP, SMTP 등 요청이 발생하게 되면 Burp Collaborator와 같이 ZAP에서도 OAST Callback 탭을 통해 확인할 수 있습니다.

URI-Path case

curl -i -k https://odiss.eu/c7uahecqkjjzee5gymjq6rhuui

Subdomain case

curl -i -k https://c7uahecqkjjzee5gymjq6rhuui.odiss.eu

callback이 잘 오네요! 직접 구축해서 사용해도 되겠지만, 우선 간단하게는 odiss.eu 도메인으로 테스트하면 burpcollaborator.net과 비슷한 느낌으로 테스트할 수 있겠네요. 개인적으론 DNS Record까지 체크하는게 훨씬 좋기 때문에 Subdomain 케이스로 사용하시는걸 추천드려요.

https://www.youtube.com/watch?v=GK46fsCL7kk

For on-premise (local setting)

odiss.eu를 사용하는 것도 좋지만 어쨌던 일부 요청은 odiss.eu로 넘어간다는 단점이 있습니다. 물론 burp suite도 이는 동일하지만, pro나 enterprise는 상용이기 때문에 portswigger 측에서 신경쓸 수 밖에 없고, 혹시라도 사고가 있는 경우 아무래도 오픈소스인 ZAP 보다는 대응에 수월함이 있을 것 같네요.

어쨌던 on premise로 구축하고 싶으신 분들을 위해 작성해봅니다. 이전 포스팅에서도 언급헀었지만, ZAP OAST에서 사용하는 백엔드는 BOAST라는 오픈소스 프로젝트이고, 아래 Repo를 통해 관리되고 있습니다.

https://github.com/marcoagner/boast

BOAST는 go 기반의 Application으로 그냥 서버에 하나 올리고 도메인만 물려주면 odiss.eu와 같이 Out-of-band를 식별하는데 callback으로 사용할 수 있습니다.

https://github.com/marcoagner/boast/blob/master/docs/deploying.md => 영어

Build BOAST

clone

git clone https://github.com/marcoagner/boast
cd boast

make

make

make가 완료되면 바이너리 파일이 빌드되어 나타납니다.

./boast -h   
BOAST v0.1.0 (by Marco Pereira 'AGNER')

Usage:
./boast [OPTION...]

  -config string
    	TOML configuration file (default "boast.toml")
  -dns_only
    	Run only the DNS receiver and its dependencies
  -dns_txt string
    	DNS receiver's TXT record
  -log_file string
    	Path to log file
  -log_level int
    	Set the logging level (0=DEBUG|1=INFO) (default 1)
  -v	Print program version and quit

DNS Configration

BOAST의 모든 기능을 제대로 사용하기 위해선 자체 DNS 서버가 있는게 가장 좋습니다. BOAST는 구동 시 내장된 DNS 서버를 실행해서, 도메인 쿼리를 수집/저장하고 사용자에게 제공하는데요, 이를 위해선 NS 도메인에 대해 glue-record를 설정해야합니다.

glue-record에 대한 내용은 KLDP 문서를 참고해주세요!

TLS Certificate

BOAST는 API(1337 port)의 https 지원, 그리고 Callback의 https 등 ssl 지원을 위해 인증서를 세팅합니다. 이 중 http의 경우 https를 로깅하지 않도록 config에서 제거하면 크게 상관 없겠지만, API의 경우 무조건 https 사용이 필요하기 때문에 인증서 설정이 필요합니다.

Make Certificate Using Let’s Encrypt

인증서는 Let’s Encrypt 등을 통해서 알아서 생성해주시고, BOAST 구동 시 ~/go/src/agner.io/boast/tls 경로에 넣어주시면 인증서를 사용하여 구동됩니다.

certbot certonly --agree-tos --manual --preferred-challenges=dns -d *.example.com --manual-auth-hook ./build/certbot-dns-01-pre-hook.sh

Make Certificate Using OpenSSL (for Testing)

당연히 임시로 인증서를 생성해서 처리할 수도 있습니다.

먼저 cakey 파일을 생성하고.

openssl genrsa -out servercakey.pem
openssl req -new -x509 -key servercakey.pem -out serverca.crt

이후 개인키 생성, 이를 기반으로 공개키를 생성합니다.

openssl genrsa -out server.key
openssl req -new -key server.key -out server_reqout.txt
openssl x509 -req -in server_reqout.txt -days 3650 -sha256 -CAcreateserial -CA serverca.crt -CAkey servercakey.pem -out server.crt

이후 BOAST는 PEM 파일만 지원하기 때문에 pem으로 변경해줍니다.

# key 변경
openssl rsa -in server.key -text > private.pem

# crt 변경
openssl x509 -inform PEM -in server.crt > public.pem

Set config file

BOAST는 toml 파일을 config로 사용합니다. 각각 섹션은 아래 정보를 의미합니다.

Section Subsection
storage max_events
  max_event_by_test
  max_dump_size
  hmac_key
storage.expire ttl
  check_interval
  max_restarts
dns_receiver domain
  public_ip

자세한 내용은 https://github.com/marcoagner/boast/blob/master/docs/boast-configuration.md를 참고해주세요. 제가 테스트를 위해 구성한 config는 아래와 같습니다.

[storage]
  max_events = 1_000_000
  max_events_by_test = 100
  max_dump_size = "80KB"
  hmac_key = "TJkhXnMqSqOaYDiTw7HsfQ=="

  [storage.expire]
    ttl = "24h"
    check_interval = "1h"
    max_restarts = 100

[api]
  domain = "frozen.hahwul.com"
  host = "0.0.0.0"
  tls_port = 1337
  tls_cert = "./public.pem"
  tls_key = "./private.pem"

  [api.status]
    url_path = "rzaedgmqloivvw7v3lamu3tzvi"

[http_receiver]
  host = "0.0.0.0"
  ports = [8090]

내욜을 보면, stoage 세팅은 위와 같이 하고, API(1337 포트)는 위에서 생성한 키 파일, receiver는 http만 로깅하도록 설정했습니다. 여기서 storage.hmac_keyapi.status.url_path 는 예제에 있는 값이 아닌 다른 값으로 변경해서 사용하시길 바랍니다. (저게 접근에 필요한 중요한 정보여서 노출되지 않는게 좋습니다)

Run

config 파일을 다 작성하셨으면 boast를 실행합니다.

./boast
2021-08-07T00:07:08.288Z 3922139 main.go:65: [INFO] Starting BOAST v0.1.0
2021-08-07T00:07:08.288Z 3922139 httprcv.go:56: [INFO] HTTP receiver: Listening on http://0.0.0.0:8099
2021-08-07T00:07:08.288Z 3922143 server.go:65: [INFO] Web API Server: status URL is https://0.0.0.0:1337/rzaedgmqloivvw7v3lamu3tzvi
2021-08-07T00:07:08.288Z 3922143 server.go:67: [INFO] Web API Server: Listening on https://0.0.0.0:1337

자 이제 별도의 Callback 서버를 위한 BOAST 세팅이 완료되었습니다. ZAP에서 바로 연동하셔서 사용하시면 됩니다 :D

k8s?

제가 내용을 진행하면서 딱 하나 걸렸던 부분이 있습니다. 바로 API 서버의 https 필수 여부인데요, k8s ingress 와 같이 앞단 proxy에서 tls 처리를 하는 경우 application은 별도로 https 설정을 할 필요가 없는데, 이러한 경우엔 좀 불편한 부분이 있는 것 같습니다. 우선 내용은 정리해서 기능 추가해달라고 issue로 이야기는 해볼 예정인데, 당장은 선택지가 없으니 app단에서 https 설정을 하셔야할 것 같네요 😭

Conclusion

드디어 ZAP OAST가 추가됬네요. OOB 자체가 많은 취약점을 쉽게 식별할 수 있게 도움을 주고, 테스팅함에 있어서도 굉장히 중요한 부분이기 떄문에 ZAP에도 자체적으로 내장할 수 있는 OOB 도구에 대한 니즈가 강했는데, 이번에 빠르게 개발되고 추가되어서 정말 좋네요 :D

References