Private OOB 테스팅을 위한 Self Hosted Interactsh

이번 주말은 log4shell로 인해 정말 인터넷이 불타고 있습니다. 자 이제 보안담당자들은 이를 대응하고 자산에 대해 스캐닝을 진행하게 될텐데, 여기서 식별에 사용하는 대표적인 방법인 OOB(Out-Of-Band)를 알려진 서비스들(ZAP OAST, Burpsuite collaborator, Interactsh 등)을 이용하여 편하게 테스팅할 수 있겠지만, 이는 결국 외부에 callback이 발생한 서버의 IP가 남게되고, 이를 통해서 해당 서비스를 운영하는 운영하는 회사 또는 그룹 등 정보를 얻어갈 수 있는 구간이 존재하게 됩니다. (썩 좋은 그림은 아니죠)

그래서 오늘은 Private하게 OOB를 테스트할 수 있도록 VPC와 DNS Glue Record를 이용하여 interactsh 서버를 따로 구축하고 사용하는 방법에 대해 이야기할까 합니다.

What is Interactsh

interactsh는 projectdiscovery가 만든 대표적인 OOB 도구로 이전에도 한번 설명드린 적이 있었습니다.

OOB Testing with interactsh!

여러 도구도 있지만 Interactsh를 선택한 이유가 2개 있는데요, 바로 nuclei의 log4shell template과 범용적인 사용성 때문이니다.

당연히 nuclei 템플릿이 나왔기 떄문에 대량 스캔을 위해선 이만한 선택지가 없을 것 같고, nuclei는 Interactsh를 지원하기 때문에 이점이 높습니다.

사용성 부분은 아래 표를 보시면 딱 이해가 되실겁니다.

  ZAP Burpsuite Nuclei
OAST(BOAST) O X X
Interactsh O O O
Burpsuite Collaborator X O O

네 ZAP,Burp,Nuclei 모두 지원하기 때문에 한번 구축해두면 편하게 쓸 수 있겠죠 😎

Set VPC

OOB 서버는 DNS Query까지 잡아야하기 때문에 Nameserver 구축이 필요합니다. 이를 위해선 서버든 PC든 컴퓨터가 필요하기 때문에 저는 제 GPC에서 비교적 리소스를 적게쓰고 있는 VPC 한대를 사용하기로 했습니다.

그리고 공인IP(Public IP)를 잘 봐두시길 바랍니다. (나중에 써야해서요)

Firewall

대부분의 Public cloud 서비스는 기본적으로 방화벽이 차단하기 때문에 Interactsh에서 사용할 포트를 미리 열어두는게 좋습니다. (DNS와 HTTP/HTTPS는 필수입니다. DNS를 제외할꺼면 이렇게 구축하는 의미가 없죠)

  • 25 (TCP/SMTP)
  • 53 (TCP/DNS)
  • 53 (UDP/DNS)
  • 80 (TCP/HTTP)
  • 443 (TCP/HTTPs)

Set DNS

Buy domain

우선 Private한 OOB 서버를 구축하기 위해선 도메인이 필요합니다. 저는 처음에 현재 제 도메인을 이용할까 하다가 장애의 여지가 있어서 그냥 하나 더 사기로했습니다. (1년에 10$ 정도면 무난하죠 뭐.. 😁)

Glue records

일반적으로 도메인을 구매하면 등록 대행 업체 등의 DNS 서버를 사용하게 됩니다. 당장 제 메인 도메인인 hahwul.com만 해도 google의 nameserver를 쓰고 있죠.

nslookup hahwul.com -d
*** Invalid option: d
Server:		168.126.63.1
Address:	168.126.63.1#53

Non-authoritative answer:
Name:	hahwul.com
Address: 216.239.32.21
...

Authoritative answers can be found from:
38.239.216.in-addr.arpa	nameserver = ns4.google.com.
38.239.216.in-addr.arpa	nameserver = ns1.google.com.
38.239.216.in-addr.arpa	nameserver = ns2.google.com.
38.239.216.in-addr.arpa	nameserver = ns3.google.com.
ns1.google.com	internet address = 216.239.32.10
ns2.google.com	internet address = 216.239.34.10
ns3.google.com	internet address = 216.239.36.10
ns4.google.com	internet address = 216.239.38.10

그러나 이런 경우에 DNS Query는 위 nameserver로 가기 때문에 우리가 이를 알 수 없습니다. 그래서 위에서 별도로 nameserver를 구성할 목적으로 VPC도 세팅한거였으니, 도메인에 대한 nameserver를 직접 설정해서 사용해야합니다.

다만 여기서 동일 도메인 내부에 nameserver의 도메인이 위치하는 경우 문제가 하나 발생합니다. 우린 nameserver 이전에 해당 도메인의 주소도 모르기 때문에 이를 알 방법이 있어야 합니다. 그게 바로 글루 레코드(Glue record)입니다.

글루 레코드는 루트 네임서버에 NS Record(네임서버 이름)와 A Record(매핑되는 IP)를 기록해서 이를 통해 subdomain으로 구성된 nameserver를 질의할 수 있게 됩니다.

Glue record 설정

Nameserver 등록

이 작업을 완료하고 어느정도 시간을 기다리면 (여기가 생각보다 오래걸려요) 제 nameserver는 외부에서 쿼리할 수 있게됩니다.

nslookup ns1.hahwuls.privatedomain
Server:		168.126.63.1
Address:	168.126.63.1#53

Non-authoritative answer:
Name:	ns1.hahwuls.privatedomain
Address: **.**.**.**

Setup Interactsh

Install go1.17

Linux 머신에서 apt 패키지 매니저를 이용해 go를 설치할 수 있습니다. 단 여기서 설치되는 go는 1.11 등 낮은 버전으로 최근 go 기반으로 만들어진 도구를 빌드할 수 없는 경우가 많습니다. 그래서 따로 1.16이나 1.17로 설치해주시는게 좋습니다.

아래 스크립트로 install.sh 파일을 하나 만들고..

GO_VERSION=1.17.1

curl -LO https://dl.google.com/go/go${GO_VERSION}.linux-amd64.tar.gz
rm -rf /usr/local/go && tar -C /usr/local -xzf go${GO_VERSION}.linux-amd64.tar.gz

cat ~/.profile | grep /usr/local/go/bin || echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.profile
cat ~/.profile | grep GOPATH= || echo 'export GOPATH=$(go env GOPATH)' >> ~/.profile
cat ~/.profile | grep GOPATH/bin || echo 'export PATH=$PATH:$GOPATH/bin' >> ~/.profile
source ~/.profile

echo $GOPATH
go version

권한을 준 후 sudo로 실행하면 go 1.17이 설치됩니다.

chmod 755 ./install.sh
sudo ./install.sh

Install interactsh

go install로 설치해줍시다.

go install -v github.com/projectdiscovery/interactsh/cmd/interactsh-server@latest

Run interactsh-server

설치가 완료되면 interactsh-server를 구동하여 nameserver와 http등의 서비스를 올려줍니다.

interactsh-server -domain hahwuls.privatedomain \
-token <TOKEN> -listen-ip 0.0.0.0 \
-ip **.**.**.**

이 때 꼭 사용이 필요한 각각의 flag는 아래와 같습니다.

flag description
-domain interactsh가 사용할 도메인 (e.g hahwul.com)
-token interactsh가 사용할 토큰 (따로 지정안하면 토큰을 자동으로 생성하는 인증 옵션으로 변경됩니다.)
-listen-ip bind ip (e.g 0.0.0.0)
-ip interactsh가 사용할 Public IP

명령을 실행하면 letsencrypt를 통해서 인증서 처리를 진행한 후 DNS, SMTP, HTTP/HTTPS 서비스를 올리고 OOB 테스트를 위한 기능이 제공됩니다. 만약 OS에 의해 53번 포트가 선점됬다면 systemd-resolved를 중지시켜 53번 포트를 확보할 수 있습니다.

sudo systemctl stop systemd-resolved

Testing with interactsh-client

자 그럼 실제로 동작이 잘 되는지 테스트해봐야겠죠? interactsh-client로 아까 지정한 token 정보를 가지고 접근해 봅시다.

interactsh-client -server https://hahwuls.privatedomain -token <TOKEN>
...
[INF] Listing 1 payload for OOB Testing
[INF] c6r0spesbkqcd1p83algcg5yh3oyyyyyn.hahwuls.privatedomain

// 실제 호출 시 ..

[c6r0spesbkqcd1p83algcg5yh3oyyyyyn] Received DNS interaction (A) from **.**.**.** at 2021-12-12 15:00:07
[c6r0spesbkqcd1p83algcg5yh3oyyyyyn] Received HTTP interaction from **.**.**.** at 2021-12-12 15:00:08
[c6r0spesbkqcd1p83algcg5yh3oyyyyyn] Received HTTP interaction from **.**.**.** at 2021-12-12 15:00:08

동작하면 -server flag로 지정한 주소로 POST 요청을 통해 Token 검증 과정을 진행하고, 사용할 subdomain 정보를 리턴받습니다. 이제 OOB를 위한 Callback 주소가 완성됬고 해당 주소가 호출되면 DNS Query와 HTTP Request 모두 수집되는 것을 확인할 수 있습니다.

Testing log4shell with private interactsh

Interactsh 관련 flag 입니다. -iserver-itoken을 이용하면 private oob 서버로도 테스트할 수 있습니다.

INTERACTSH:
   -iserver, -interactsh-server string  interactsh server url for self-hosted instance (default "https://interactsh.com")
   -itoken, -interactsh-token string    authentication token for self-hosted interactsh server
   -interactions-cache-size int         number of requests to keep in the interactions cache (default 5000)
   -interactions-eviction int           number of seconds to wait before evicting requests from cache (default 60)
   -interactions-poll-duration int      number of seconds to wait before each interaction poll request (default 5)
   -interactions-cooldown-period int    extra time for interaction polling before exiting (default 5)
   -ni, -no-interactsh                  disable interactsh server for OAST testing, exclude OAST based templates
nuclei -u http://localhost:8080 -t cves/2021/CVE-2021-44228.yaml -iserver "https://hahwuls.privatedomain" -itoken "<TOKEN>"

Cloud metadata domain

이것도 interactsh의 좋은점 중 하나인데, aws나 alibaba 퍼블릭 클라우드의 SSRF 등 테스트를 위해서 metadata api 주소를 쉽게 호출할 수 있도록 아래 패턴으로 도메인을 매핑해줍니다.

  • aws: aws.{interactsh-server} points to 169.254.169.254
  • alibaba: alibaba.{interactsh-server} points to 100.100.100.200

References

  • https://github.com/projectdiscovery/interactsh
  • https://www.hahwul.com/2021/05/01/oob-testing-with-interactsh/#self-hostsed-instance
  • https://support.google.com/domains/answer/10751068#zippy=