Initial commit
This commit is contained in:
commit
292cc4147d
18 changed files with 1958 additions and 0 deletions
65
README.md
Normal file
65
README.md
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
# checker-dangling
|
||||
|
||||
A happyDomain checker that scans a working zone for **dangling subdomains**:
|
||||
records (`CNAME` / `MX` / `SRV` / `NS`) whose targets resolve to NXDOMAIN,
|
||||
or whose external registrable domain is expired, in `pendingDelete`, or
|
||||
recently re-registered. This is the attack class popularised by Ars
|
||||
Technica in 2017, where universities ended up serving porn from CNAMEs
|
||||
that pointed at decommissioned third-party services after malicious
|
||||
actors re-registered the lapsed targets.
|
||||
|
||||
It runs in three deployment modes (standalone HTTP binary, Go plugin,
|
||||
Docker image), like every other checker in the happyDomain ecosystem.
|
||||
|
||||
## How it works
|
||||
|
||||
The checker walks every service in the working zone (`AutoFillZone`) and
|
||||
extracts pointer records from `svcs.CNAME`, `svcs.SpecialCNAME`,
|
||||
`svcs.MXs`, `svcs.UnknownSRV`, and `svcs.Orphan` bodies (the latter
|
||||
covering bare `NS`/`CNAME`/`MX` records when no dedicated service is
|
||||
attached). For each (owner, rrtype, target) triple it:
|
||||
|
||||
1. Classifies the target as in-zone or external relative to the zone's
|
||||
eTLD+1 (via `golang.org/x/net/publicsuffix`).
|
||||
2. Performs a single, time-bounded DNS resolution to detect immediate
|
||||
breakage (`nxdomain`, `servfail`, `no_answer`, `timeout`).
|
||||
3. Publishes a `DiscoveryEntry` per pointer:
|
||||
- `dangling.external-target.v1` for external pointers — companion
|
||||
checkers (notably the host's `domain_expiry`) subscribe to this
|
||||
type and run RDAP/WHOIS on the registrable domain.
|
||||
- `dangling.in-zone-target.v1` for same-registrable pointers — used
|
||||
as a join key for future reachability checkers (alias / ping /
|
||||
http) that may consume it.
|
||||
|
||||
## Verdict matrix
|
||||
|
||||
| Signal | Severity | Source |
|
||||
|--------------------------------------------------------------|----------|-------------------------|
|
||||
| Target NXDOMAIN | Critical | local DNS resolution |
|
||||
| Target SERVFAIL | Warning | local DNS resolution |
|
||||
| Target NOERROR with empty answer | Info | local DNS resolution |
|
||||
| Registrable domain expired | Critical | `whois` related obs. |
|
||||
| Registrable status `pendingDelete` / `redemptionPeriod` | Critical | `whois` related obs. |
|
||||
| Registrable registered within the last 90 days | Warning | `whois` related obs. |
|
||||
|
||||
The rule emits one `CheckState` per impacted owner and ranks them by
|
||||
descending severity so the report's "Fix this first" card always
|
||||
matches the rule output.
|
||||
|
||||
## Companion: `domain_expiry`
|
||||
|
||||
For the WHOIS-driven signals to fire, the host's existing
|
||||
`domain_expiry` checker must be extended to subscribe to
|
||||
`dangling.external-target.v1` entries via `AutoFillDiscoveryEntries`,
|
||||
run RDAP per registrable domain, and publish a per-Ref `whois`
|
||||
observation. Without that subscription the checker still works as a
|
||||
DNS-only dangling detector.
|
||||
|
||||
## Build
|
||||
|
||||
```sh
|
||||
make # standalone binary
|
||||
make plugin # .so plugin for happyDomain
|
||||
make docker # Docker image
|
||||
make test # run the unit tests
|
||||
```
|
||||
Loading…
Add table
Add a link
Reference in a new issue