
외부에서 관찰 가능한 데이터만 사용하여 조직이 구독 중인 SaaS 서비스를 찾아냅니다. 섀도 IT 탐색을 위해 만들어졌습니다.
▄▄▓▓▓▓▓▓▓▓▓▄▄
▄▓▓▒▒▒▒▒▒▒▒▒▒▒▓▓▄ Yowie · 아무도 알려주지 않은 SaaS를 추적하기
▓▓▒▒░░░░░░░░░░░▒▒▓▓
▓▒░░ ● ● ░▒▓ Domain acme.com.au
▓▒░░ ▼ ░▒▓ Candidates acme, acmecorp
▓▓▒░░ ╰───╯ ░▒▓▓
▀▓▓▒▒░░░░░░░░░▒▒▓▓▀
▀▀▓▓▓▓▓▓▓▓▓▓▓▀▀
외부에서 관찰 가능한 데이터만을 사용해 조직이 구독 중인 SaaS 서비스를 찾아냅니다. 섀도 IT 탐색을 위해 만들어졌습니다. 찾을 가치가 있는 서비스는 바로 아무도 알려주지 않은 것들입니다.
호주 부시 크립티드의 이름을 따서 지었습니다. 모두가 없다고 우기는 무언가를 쫓고 있기 때문입니다.

412개 벤더를 커버하는 574개의 시그니처가 9개의 탐지기에 걸쳐 있으며, 추가로 104개가 확인 대기 중으로 보류되어 있습니다. 발견 사항은 등급이 매겨지며, 각각은 이를 생성한 레코드나 응답을 함께 담고 있습니다.
go build -o yowie ./cmd/yowie
Go 1.22 이상. 시그니처 팩은 바이너리에 내장되어 있으므로 단일 파일만 있으면 배포할 수 있습니다.
yowie [flags] <domain> [candidate ...]
도메인은 조직의 루트 도메인입니다. 후보는 벤더 테넌트의 이름이 될 수 있는 짧은 문자열입니다 — 상호, 약어, 인수로 넘어온 옛 브랜드 등입니다. 가능한 한 많이 제공하세요. 각각이 테넌트를 찾을 또 하나의 기회입니다. 아무것도 주지 않으면 도메인의 첫 번째 레이블이 사용됩니다.
yowie acme.com.au acme acmecorp acmegroup
yowie -format html -o report.html acme.com.au acme
yowie -format json acme.com.au | jq '.findings[] | select(.confidence=="high")'
yowie -only dns,spf,dmarc -compact acme.com.au
yowie -signatures ./signatures -validate
| Detector | Signal |
|---|---|
dns | TXT 검증 토큰, CNAME, MX 및 NS 레코드 |
vanity | 조직 이름을 딴 벤더 호스팅 테넌트 (acme.zendesk.com) |
http | DNS 흔적이 없는 서비스에 대한 애플리케이션 계층 지문 |
spf | 중첩된 include와 redirect를 따라가는 전체 SPF include 그래프 |
dmarc | DMARC 집계/포렌식 보고서 목적지 |
bimi | BIMI 로고 및 Verified Mark Certificate 호스팅 |
mta-sts | MTA-STS 정책 내용 |
tenant | Microsoft 테넌트 ID, 페더레이션 자격 증명 공급자, 형제 도메인 |
ct | Certificate Transparency 로그에서 나온 서브도메인, 해석 및 귀속 |
-only 또는 -skip으로 선택하세요. 예: 빠른 DNS 전용 패스를 위한 -skip ct,http.
마지막 두 개는 시그니처 목록이 찾을 수 없는 것들을 찾아내므로 짚고 넘어갈 가치가 있습니다.
**tenant**는 Microsoft의 인증되지 않은 엔드포인트에 도메인이 누구에게 속하는지 묻습니다. Autodiscover의 페더레이션 정보는 같은 테넌트에 연결된 모든 도메인을 반환하며, 이는 사업부, 인수, 버려진 브랜드를 흔히 드러냅니다. 각각이 스캔할 가치가 있는 또 하나의 도메인입니다.
**ct**는 탐색 모델을 뒤집습니다. 다른 모든 검사는 고정된 목록에 대해 "이 조직이 벤더 X를 사용하는가?"라고 묻기 때문에 누군가 이미 시그니처를 작성한 벤더만 찾을 수 있습니다. CT는 "이 조직이 실제로 서브도메인을 무엇을 향하게 했는가?"라고 묻습니다. 제품에 가입하고 support.acme.com을 연결한 팀은 인증서를 발급받게 되며, 그 인증서는 공개적이고 영구적입니다. 어떤 시그니처와도 일치하지 않는 대상은 리드로 보고되며, 이것이 바로 찾아야 할지 몰랐던 것을 찾는 방법입니다.
발견 사항은 등급이 매겨지며, 등급이 핵심입니다:
acme.blogspot.com이 당신의 acme가 아닐 수 있습니다.두 개의 독립적인 탐지기가 같은 벤더에 동의하면 Probable 발견이 Confirmed로 승격됩니다. 모든 발견은 이를 촉발한 정확한 레코드나 응답을 담고 있으므로, 도구를 다시 실행하지 않고도 보고서를 방어할 수 있습니다.
승격에는 예외가 하나 있는데, 그것이 "이 테넌트가 존재한다"와 "이 테넌트가 당신의 것이다"의 차이입니다 — 정확성에 관한 참고의 네임스페이스 항목을 참조하세요.
-no-unknown은 신호만 원할 경우 귀속되지 않은 리드를 제거합니다.
-format cli(기본값), json, jsonl, csv, html. -o로 파일에 쓸 수 있습니다. HTML 보고서는 자체 완결적이어서 — 외부 자산 없음 — 이메일로 보내거나 공유 드라이브에 올려도 그대로 살아남습니다.
진행 상황은 stderr로, 결과는 stdout으로 가므로 yowie -format json acme.com > out.json도 여전히 실시간 진행 라인을 보여줍니다.
시그니처는 signatures/*.yaml에 있습니다. 바이너리에 내장되어 있으며, -signatures <dir> 또는 YOWIE_SIGNATURES=<dir>은 디스크에서 대신 로드합니다. 이는 재빌드 없이 반복 작업하는 방법입니다.
version: 1
pack: dns-txt
description: "Domain-ownership verification tokens published as TXT records."
defaults:
confidence: high
signatures:
- id: txt-1password
vendor: "1Password"
category: "Identity & Secrets"
type: txt
query: "{domain}"
match:
contains: "1password-site-verification"
{domain}은 루트 도메인으로, {candidate}는 각 후보 문자열로 확장됩니다. {candidate}를 참조하는 시그니처는 후보마다 한 번씩 평가됩니다.
| Type | Matches | Notes |
|---|---|---|
txt, cname, mx, ns | query의 레코드에 대한 match.contains | 대소문자 구분 없음 |
vanity_a, vanity_cname | 기준선 비교; match 블록 없음 | query에 {candidate}가 포함되어야 함 |
http | match.present, match.absent, 또는 match.status 단독 | 아래 상태 처리 참조 |
spf_include | 해석된 SPF include 그래프에 대한 match.contains | |
dmarc_rua | DMARC 보고서 목적지에 대한 match.contains | |
cname_target | query는 순수 호스팅 접미사 | ct가 발견한 호스트에 적용됨; *는 레이블 하나와 일치 |
disabled: true는 시그니처를 그 뒤의 연구를 잃지 않고 보류시킵니다. notes:는 분석가 지침을 보고서까지 전달합니다.
편집 후 yowie -validate를 실행하세요. 검증은 엄격합니다 — 알 수 없는 키는 조용한 무시가 아니라 오류입니다 — 그리고 팩은 go test로도 검사되므로, 오타가 향후 모든 스캔에서 조용히 커버리지를 잃게 하는 일은 없습니다.
| Pack | Contents |
|---|---|
dns-txt, dns-cname, dns-mx | 검증 토큰 및 위임된 호스트명. 활성. |
email-spf, email-dmarc | 발신자 및 DMARC 처리기. 활성. |
vanity-tenants, http-endpoints | 테넌트 호스트명 및 앱 지문. 활성. |
cname-targets | CT로 발견된 서브도메인용 호스팅 접미사. 활성. |
ai-services | AI 및 LLM 플랫폼. 보류. |
file-transfer | 관리형 파일 전송 — MOVEit, GoAnywhere, Egnyte. 보류. |
finance-procurement | 재무, 경비, 급여, 조달. 보류. |
security-grc | 보안 도구 및 컴플라이언스 자동화. 보류. |
graveyard | 검증되지 않은 항목, 그리고 운영자를 식별할 수 없는 플랫폼. 보류. |
다섯 개의 팩은 전부 비활성 상태로 제공됩니다. 구조적으로 완전하고 검증을 통과하지만, 매치 기준이 실제 테넌트에 대해 확인된 적이 없으므로 스캔 중에 평가되지 않습니다.
이는 의도적입니다. contains 값이 틀린 시그니처는 절대 발동하지도, 오류를 내지도 않습니다 — 단지 벤더가 커버되는 것처럼 보이게 할 뿐입니다. 이를 비활성으로 제공하면 숫자를 부풀리지 않으면서 연구를 저장소에 남길 수 있습니다.
지금까지 다섯 개가 졸업했으며, 나머지를 신뢰하기 전에 그 기록을 알아둘 가치가 있습니다: 두 개는 작성된 그대로 정확했고, 하나는 도메인이 틀렸으며, 두 개는 도메인은 맞았지만 채널이 틀렸습니다 — 벤더가 항목이 예측한 고객별 호스트명이 아니라 SPF include로 나타났습니다. 남은 보류 항목은 잠재적 커버리지가 아니라 연구 노트로 취급하세요.
-validate는 백로그를 팩별로 묶어 출력합니다:
$ ./yowie -validate
574 signatures across 13 packs, covering 412 vendors
...
104 signature(s) parked behind `disabled: true`, awaiting confirmation against a live tenant:
ai-services.yaml (24)
txt-fireflies-ai Fireflies.ai
...
하나를 승격하려면:
dig +short TXT known-customer.com | grep -i <vendor> # token signatures
dig +short A acme.egnyte.com # vanity signatures
dig +short A $(openssl rand -hex 6).egnyte.com # ...and its baseline
배니티 테넌트는 무작위 레이블과 다르게 응답해야 합니다.disabled: true를 삭제하며, 정직한 신뢰도를 설정합니다.notes:를 확인한 내용을 말하도록 다시 작성합니다../yowie -signatures ./signatures -validate메커니즘이 작동하지 않는 것으로 밝혀지면, 비활성으로 두고 부정적 결과를 notes:에 기록하세요. 이는 작동하는 시그니처만큼 가치가 있습니다 — 다음 사람이 그것을 다시 발견하느라 오후를 허비하는 것을 막아주기 때문입니다. security-grc에는 이미 이런 것들이 여럿 있으며, CrowdStrike, Wiz, Tenable에 배니티 시그니처가 없는 이유를 설명합니다: 이들은 모든 고객을 공유 콘솔에 배치하므로 고객별로 탐지할 것이 없습니다.
도구는 스스로 백로그를 생성합니다. 귀속되지 않은 발신자와 호스트는 바로 시그니처를 작성할 가치가 있는 벤더이며, 여러 스캔에 걸쳐 빈도순으로 스스로 순위를 매깁니다:
for d in $(cat domains.txt); do ./yowie -format json -quiet "$d"; done \
| jq -r '.findings[] | select(.category|startswith("Unidentified")) | .vendor' \
| sort | uniq -c | sort -rn | head -40
서로 무관한 조직들에 걸쳐 반복되는 것은 실재합니다. 이는 또한 확인된 실제 샘플을 공짜로 제공합니다 — SPF 및 DMARC 증거에 실제 발신자 호스트명이 들어 있는데, 이것이 바로 보류된 항목에 필요한 것입니다.
많은 벤더가 테넌트 존을 와일드카드 처리하므로 "해석된다"는 아무것도 증명하지 못합니다. 각 템플릿은 먼저 두 개의 무작위 레이블로 프로브되어 존재하지 않는 테넌트에 대해 벤더가 어떻게 응답하는지 학습합니다. 후보는 그 응답이 기준선과 다를 때만 카운트됩니다. 두 기준선이 서로 불일치하면 — 지오-DNS, 라운드 로빈 — 비교가 무의미하므로 시그니처는 추측되지 않고 경고와 함께 건너뜁니다.
NXDOMAIN 기준선은 Confirmed 발견을 낳습니다. 다른 응답을 보이는 와일드카드 기준선은 시그니처 자체의 신뢰도와 그것이 더 약한 이유를 설명하는 노트를 낳습니다.