700-pentesting-epp.md (19977B)
1 --- 2 title: "700 - Pentesting EPP" 3 section: "Network Services" 4 sectionSlug: "network-services-pentesting" 5 sourcePath: "src/network-services-pentesting/700-pentesting-epp.md" 6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/network-services-pentesting/700-pentesting-epp.md" 7 sha: "188de82beb54e70956b2952367a0af91d26758b8" 8 isIndex: false 9 modified: true 10 license: "CC-BY-NC-4.0" 11 --- 12 13 # 700 - Pentesting EPP 14 15 ## Basic Information 16 17 The **Extensible Provisioning Protocol (EPP)** is an XML-based protocol used by **registries** and **registrars** to provision objects such as domains, hosts, and contacts. Extensions add functions such as DNSSEC management and lifecycle notifications.<sup>[[4]](#references)</sup> 18 19 In practice, this is one of the most sensitive services in a TLD environment: if you can operate EPP as a registrar or abuse a registrar-facing control plane that proxies EPP actions, you can usually **change nameservers, rotate transfer credentials, alter DNSSEC state, or transfer domains away**. 20 21 The standardized transport is **TLS over TCP on port `700/tcp`**. Deployments commonly layer certificate-based client authentication, source-IP restrictions, and an EPP `login` username/password. Each data unit begins with a **four-byte big-endian total length** (including the length field), followed by the XML document. Current IETF work also defines **EPP over HTTPS**, so assessments should check documented web gateways rather than assume the surface is limited to raw TCP/700.<sup>[[5]](#references)[[6]](#references)</sup> 22 23 ### Pentest 24 25 A good real-world starting point is [**HackCompute's research on vulnerable EPP implementations**](https://hackcompute.com/hacking-epp-servers/). They found XML parser abuse (XXE) and chained it into local file disclosure against real registry software, showing how an EPP bug can become **domain or even TLD-level compromise**.<sup>[[1]](#references)</sup> 26 27 --- 28 29 ## Enumeration & Recon 30 31 ### Initial network checks 32 33 EPP servers commonly use hostnames such as `epp.<registry>`, `ote.<registry>`, `ot&e.<registry>`, `sandbox`, or `staging`. 34 35 ```bash 36 # TLS and certificate inspection 37 nmap -sV -Pn -p700 --script ssl-cert,ssl-enum-ciphers <target> 38 openssl s_client -connect <target>:700 -servername <target> -showcerts </dev/null 39 ``` 40 41 Many registries require **mTLS** and will drop the session if no valid client certificate is presented. Still, it is worth checking whether: 42 43 - the server leaks a greeting before enforcing registrar auth 44 - OT&E / staging endpoints enforce weaker controls than production 45 - a reverse proxy or HTTPS transport exists in front of the EPP service 46 47 ### Grab the EPP greeting 48 49 The greeting is the EPP equivalent of banner-grabbing. It tells you which **object URIs** and **extension namespaces** the server supports. 50 51 ```python 52 import socket 53 import ssl 54 import struct 55 56 host = "target" 57 message = b'<?xml version="1.0" encoding="UTF-8"?><epp xmlns="urn:ietf:params:xml:ns:epp-1.0"><hello/></epp>' 58 59 def recv_exact(sock, size): 60 data = b"" 61 while len(data) < size: 62 chunk = sock.recv(size - len(data)) 63 if not chunk: 64 raise ConnectionError("EPP connection closed") 65 data += chunk 66 return data 67 68 def recv_epp(sock): 69 header = recv_exact(sock, 4) 70 size = struct.unpack("!I", header)[0] 71 return recv_exact(sock, size - 4) 72 73 context = ssl.create_default_context() 74 with context.wrap_socket(socket.create_connection((host, 700)), server_hostname=host) as sock: 75 print(recv_epp(sock).decode(errors="replace")) # Server greeting 76 sock.sendall(struct.pack("!I", len(message) + 4) + message) 77 print(recv_epp(sock).decode(errors="replace")) 78 ``` 79 80 From the greeting, pay attention to namespaces such as: 81 82 - `domain`, `host`, `contact` 83 - `secDNS` --> DNSSEC DS / key-data management 84 - `rgp` --> restore / redemption flows 85 - `launch`, `fee`, `ttl`, proprietary namespaces --> custom business logic / extra parser surface 86 - `loginSec` --> login-security extension 87 - `changePoll`, `maintenance` --> out-of-band workflow visibility 88 89 If the server advertises a lot of extensions, the parser and authorization surface is usually much larger than the base RFCs suggest. 90 91 ### Check for EPP over HTTPS 92 93 The current EPP-over-HTTPS Internet-Draft maps connection initiation/greeting retrieval to an **HTTP `GET`** and commands to **HTTP `POST`**, with state associated through a server cookie. Because this remains a draft, confirm behavior against the exact implementation and draft version. Indicators include `application/epp+xml`, `Set-Cookie`, and explicit cache controls.<sup>[[6]](#references)</sup> 94 95 ```bash 96 curl -isk https://<target>/ -H 'Accept: application/epp+xml' 97 ``` 98 99 If HTTPS works, test it like an authenticated/stateful API in addition to classic EPP: 100 101 - cookie fixation / session mix-up behind load balancers 102 - path confusion (`/`, `/epp`, `/api/epp`, `/registry/epp`) 103 - reverse-proxy auth mistakes 104 - accidental caching or logging of XML bodies and transfer credentials 105 106 ### Look for forgotten OT&E / registrar onboarding infrastructure 107 108 Public registry documentation is often gold. For example, some registrar manuals openly document: 109 110 - production EPP endpoints 111 - OT&E / certification endpoints 112 - whether OT&E is IP-restricted or not 113 - registrar consoles, WHOIS test services, and onboarding workflows 114 115 That matters because **test environments commonly share code paths with production** while having weaker IP allowlists, reused credentials, weaker certificates, or lower scrutiny. 116 117 ### Authentication stack to map 118 119 Real deployments often layer several controls: 120 121 - **client certificate** 122 - **source IP allowlist** 123 - **EPP username/password** 124 - optional registrar web panel / reseller console that ultimately issues EPP actions 125 126 This is important during an assessment because you do **not** always need direct socket-level EPP access. Compromising a registrar console, support workflow, internal API, or an automation worker that holds the client certificate may be enough. 127 128 ### Open-source clients useful for testing 129 130 - **[domainr/epp](https://github.com/domainr/epp)** / **[domainr/epp2](https://github.com/domainr/epp2)** – lightweight Go clients that are easy to instrument for fuzzing and custom namespaces. 131 - **[CZ-NIC/fred-client](https://github.com/CZ-NIC/fred-client)** – Python CLI/API for FRED-based registries. 132 - **[getnamingo/epp-client](https://github.com/getnamingo/epp-client)** – PHP client with broad registry support, including EPP-over-HTTPS support in current releases. 133 - **[metaregistrar/php-epp-client](https://github.com/metaregistrar/php-epp-client)** – mature object-oriented PHP client with support for many registry-specific extensions. 134 135 --- 136 137 ## High-Value EPP Operations 138 139 If you obtain registrar-level access, these operations usually have the highest offensive value: 140 141 | Operation | Why it matters | 142 | --- | --- | 143 | `domain:update` | Change nameservers, contacts, statuses, or `authInfo` | 144 | `domain:transfer` | Move the domain to another registrar or interfere with approval flows | 145 | `domain:info` | Reveals object and transfer state; authorization material is subject to object mapping and server policy | 146 | `secDNS:update` | Add/remove/replace DS or key data to break validation or control DNSSEC state | 147 | `poll` | Observe asynchronous events: transfer approvals, registry actions, out-of-band changes | 148 149 A lot of real compromises happen **around** these commands rather than in the XML parser itself: panel/API auth bugs, support workflows, leaked transfer codes, stale OT&E credentials, or weak separation between resellers and parent registrar accounts. 150 151 --- 152 153 ## Common Weaknesses & Attack Surface 154 155 ### XML parser bugs (XXE, SSRF, local file disclosure) 156 157 EPP is XML, so the classic parser bug class is still relevant. Some implementations parse and schema-validate XML **before** processing `login`, allowing malformed commands to reach the parser unauthenticated. The HackCompute research showed how XXE in real EPP implementations could be chained into local file disclosure and potentially much wider registry compromise.<sup>[[1]](#references)</sup> 158 159 Basic test payload: 160 161 ```xml 162 <?xml version="1.0"?> 163 <!DOCTYPE x [<!ENTITY xxe SYSTEM "file:///etc/passwd">]> 164 <epp xmlns="urn:ietf:params:xml:ns:epp-1.0"> 165 <command> 166 <check> 167 <domain:check xmlns:domain="urn:ietf:params:xml:ns:domain-1.0"> 168 <domain:name>&xxe;</domain:name> 169 </domain:check> 170 </check> 171 </command> 172 </epp> 173 ``` 174 175 Besides plain file read, test for: 176 177 - **SSRF** to metadata/internal services 178 - **external DTD fetches** for blind callbacks 179 - entity expansion reflected through schema or validation errors 180 - parser differences between **production** and **OT&E** stacks 181 - XML handling in **registrar-side portals** that transform user input into EPP XML 182 183 ### mTLS and transport mistakes 184 185 Common real-world failures include: 186 187 1. **Anonymous TLS is accepted**, and only the EPP `login` is enforced. 188 2. A **reverse proxy terminates TLS**, but the backend does not require or correctly forward the verified client-certificate identity. 189 3. A registrar client **does not validate the registry certificate** correctly, enabling credential theft or on-path interception of the EPP `login`. 190 4. The service lacks **IP allowlists, connection quotas, or rate limits**, making low-and-slow password spraying practical. 191 192 Because TCP EPP uses a length prefix, custom gateways and protocol relays are also worth fuzzing with **truncated**, **oversized**, or **desynchronized** frame lengths before the XML parser is reached. 193 194 ### EPP-over-HTTPS session handling 195 196 Where the registry exposes EPP over HTTPS, add standard web-session testing on top of EPP semantics: 197 198 - **session fixation**, especially when a pre-authentication cookie survives login 199 - **session replay** from another IP or client 200 - weak or predictable session identifiers 201 - loss of mTLS guarantees at the HTTPS gateway 202 - caching or logging of XML bodies and transfer credentials 203 204 The HTTP session and reverse proxy become part of the EPP security boundary, so ordinary cookie or proxy bugs can become registry-control bugs. 205 206 ### Legacy password model and the `loginSec` extension 207 208 Base EPP constrains `pw`/`newPW` to 6–16 characters. RFC 8807 introduced the **Login Security Extension**, which can carry longer server-policy-controlled passwords and machine-readable security events.<sup>[[4]](#references)[[7]](#references)</sup> 209 210 When testing authenticated access, check whether the registry still behaves like an old deployment: 211 212 - short shared passwords only 213 - no password rotation hints 214 - no visibility into expiring client certificates 215 - no telemetry for repeated failed logins or insecure TLS/cipher negotiation 216 217 If `loginSec` is enabled, a successful login can return structured warnings such as **expiring passwords/certificates**, **insecure TLS versions/ciphers**, or **high failed-login counts**. That is useful both for offensive situational awareness and for identifying weak operational hygiene. 218 219 ### `authInfo` / EPP code abuse and transfer workflows 220 221 `authInfo` (also called EPP code / transfer code / Auth-Info code) is one of the most valuable secrets in the domain lifecycle. 222 223 The important offensive detail is that **the protocol and policy surface around transfers is still large**: 224 225 - EPP domain objects support `authInfo` 226 - ICANN transfer policy still requires registrars to provide the AuthInfo code and remove `ClientTransferProhibited` within specific conditions/time limits 227 - [RFC 9154](https://datatracker.ietf.org/doc/html/rfc9154) exists because long-lived, stored, reusable transfer secrets are dangerous<sup>[[2]](#references)</sup> 228 229 Practical checks: 230 231 - Can a low-privilege user, reseller, or support role **view or reset** `authInfo`? 232 - Does a registrar panel/API return a **static** transfer code that rarely changes? 233 - Is `authInfo` emailed, ticketed, logged, or stored in CRM/internal notes? 234 - Can you **unlock** a domain or fetch its EPP code through a weaker path than the one required to edit nameservers/contacts? 235 - Do internal APIs mirror `domain:info` responses containing authorization data to users that should not see it? 236 - Can a transfer be raced against manual review or asynchronous approval messages? 237 238 Example transfer request using leaked `authInfo`: 239 240 ```xml 241 <epp xmlns="urn:ietf:params:xml:ns:epp-1.0"> 242 <command> 243 <transfer op="request"> 244 <domain:transfer xmlns:domain="urn:ietf:params:xml:ns:domain-1.0"> 245 <domain:name>victim.tld</domain:name> 246 <domain:authInfo><domain:pw>AUTH-CODE</domain:pw></domain:authInfo> 247 </domain:transfer> 248 </transfer> 249 </command> 250 </epp> 251 ``` 252 253 The secure model from RFC 9154 is: **strong random authInfo, short-lived, not stored by the client, hashed at the server, not logged, and automatically unset after successful transfer**. Anything materially weaker is worth digging into.<sup>[[2]](#references)</sup> 254 255 ### DNSSEC / `secDNS` abuse 256 257 Once you have EPP access, do not stop at nameserver changes. Many operators forget that EPP also controls **DNSSEC state**. 258 259 With the EPP `secDNS` extension, a registrar can add or remove **DS records** and key data. A privileged attacker may therefore be able to:<sup>[[8]](#references)</sup> 260 261 - remove DS material to intentionally break validation during takeover 262 - replace DS/key data to match attacker-controlled signing keys 263 - combine nameserver and DNSSEC changes in one workflow to make recovery slower and more error-prone 264 265 Minimal example of removing all existing DNSSEC material and adding attacker-controlled DS data: 266 267 ```xml 268 <extension xmlns:secDNS="urn:ietf:params:xml:ns:secDNS-1.1"> 269 <secDNS:update> 270 <secDNS:rem><secDNS:all>true</secDNS:all></secDNS:rem> 271 <secDNS:add> 272 <secDNS:dsData> 273 <secDNS:keyTag>31337</secDNS:keyTag><secDNS:alg>13</secDNS:alg> 274 <secDNS:digestType>2</secDNS:digestType><secDNS:digest>DEADBEEF</secDNS:digest> 275 </secDNS:dsData> 276 </secDNS:add> 277 </secDNS:update> 278 </extension> 279 ``` 280 281 ### Poll queue, change poll, and maintenance events 282 283 Modern EPP deployments increasingly rely on asynchronous workflows: 284 285 - `poll` for queued messages 286 - **Change Poll** for out-of-band object changes.<sup>[[9]](#references)</sup> 287 - **Registry Maintenance Notification** for planned and emergency maintenance.<sup>[[10]](#references)</sup> 288 289 These are valuable during an assessment because they often reveal: 290 291 - transfers initiated outside your current session 292 - support/operator actions not initiated via EPP 293 - UDRP/court/policy-driven changes 294 - maintenance windows and secondary systems 295 296 If a registrar mirrors these messages into **email, webhooks, dashboards, or reseller portals**, test those integrations too. A weak internal consumer can become the easier compromise path than raw EPP itself. 297 298 --- 299 300 ## Registry-Side Lifecycle Flaws 301 302 Registry abuse is not limited to parser and authentication bugs. Research presented at USENIX Security 2025 identified lifecycle and delegation inconsistencies with security impact:<sup>[[3]](#references)</sup> 303 304 1. **Twin domain names for IDNs**: defensive auto-created sibling objects can leave a related internationalized-domain variant available for registration. 305 2. **Stale glue or siloed host-object management**: a registry may continue delegating domains through expired or attacker-controlled nameserver objects. 306 3. **Relic domains**: a domain becomes available again while the TLD zone retains old NS or glue delegation, allowing the next registrant to inherit dangerous state. 307 308 Useful external checks include comparing registry or RDAP lifecycle data with the live delegation: 309 310 ```bash 311 dig +trace victim.tld NS 312 dig +short NS victim.tld 313 ``` 314 315 If a domain is available or recently dropped but the TLD still delegates old NS or glue records, re-registration can become a registry-level hijack primitive. The downstream effect resembles [domain or subdomain takeover](/hacktricks/pentesting-web/domain-subdomain-takeover), but the flaw is in the registry lifecycle and delegation pipeline. 316 317 --- 318 319 ## Practical Offensive Checks 320 321 1. **Find every endpoint**: production, OT&E, reseller, registrar console, API gateway, docs, and WHOIS/RDAP references. 322 2. **Enumerate greeting namespaces** and map which flows exist: transfer, DNSSEC, poll, launch, fee, maintenance. 323 3. **Compare prod vs OT&E**: cert policy, source-IP restrictions, login behavior, extension availability, error handling. 324 4. **Hunt for transfer-secret exposure** in registrar UIs, APIs, ticketing, logs, exports, and support workflows. 325 5. **Test authorization asymmetry**: can you unlock / fetch EPP code / transfer more easily than you can edit nameservers? 326 6. **Abuse post-compromise EPP breadth**: nameservers, statuses, `authInfo`, DS records, contact changes, and poll queue visibility. 327 7. **For HTTPS transports**, test cookie/session behavior and proxy-induced bugs exactly like a high-value stateful XML API. 328 8. **Compare lifecycle state with DNS delegation** to find stale glue, relic domains, and inconsistent IDN sibling handling. 329 330 --- 331 332 ## Attack Path: From Recon to Domain / TLD Hijack 333 334 1. Discover production or OT&E EPP infrastructure via docs, certificates, registrar portals, or related services. 335 2. Enumerate the greeting to learn supported namespaces and high-value operations. 336 3. Obtain registrar capability by exploiting XML parsing, a registrar control-plane bug, stolen client certificate, leaked EPP credentials, or exposed `authInfo` workflows. 337 4. Change `hostObj` / nameserver data, rotate `authInfo`, submit transfer operations, or alter DNSSEC material through `secDNS:update`. 338 5. Abuse stale glue or relic-domain behavior to retain or regain control across lifecycle transitions. 339 6. Use `poll` responses and asynchronous workflow artefacts to monitor completion and race defenders. 340 341 For a **single domain**, this usually means DNS takeover, certificate issuance opportunity, and email interception. For a **registry-side compromise**, the blast radius can become **every domain sponsored by that registrar or even the full TLD**. 342 343 --- 344 345 ## Defensive Measures & Hardening 346 347 Keep this short from an offensive perspective, but these are the controls that most reduce attacker options: 348 349 - enforce **mTLS + source-IP restrictions + strong/passphrase-based login security** 350 - treat **OT&E/staging** as production-grade from an auth and monitoring perspective 351 - implement **short-lived, one-time, hashed `authInfo`** workflows 352 - alert on **nameserver, transfer, and DNSSEC** changes together, not separately 353 - consume and review **poll / change-poll / maintenance** events centrally 354 - continuously reconcile registration state, host objects, and live **NS/glue delegation** 355 356 ## References 357 358 - [1] [HackCompute - can I speak to your manager? hacking root EPP servers to take control of zones](https://hackcompute.com/hacking-epp-servers/) 359 - [2] [RFC 9154 - Extensible Provisioning Protocol (EPP) Secure Authorization Information for Transfer](https://datatracker.ietf.org/doc/html/rfc9154) 360 - [3] [USENIX Security 2025 - Misty Registry: An Empirical Study of Flawed Domain Registry Operation](https://www.usenix.org/conference/usenixsecurity25/presentation/zhang-mingming) 361 - [4] [RFC 5730 – Extensible Provisioning Protocol (EPP)](https://www.rfc-editor.org/rfc/rfc5730) 362 - [5] [RFC 5734 – EPP Transport over TCP](https://www.rfc-editor.org/rfc/rfc5734) 363 - [6] [IETF Internet-Draft – EPP Transport over HTTPS](https://datatracker.ietf.org/doc/draft-ietf-regext-epp-https/) 364 - [7] [RFC 8807 – Login Security Extension for EPP](https://www.rfc-editor.org/rfc/rfc8807) 365 - [8] [RFC 5910 – Domain Name System Security Extensions Mapping for EPP](https://www.rfc-editor.org/rfc/rfc5910) 366 - [9] [RFC 8590 – Change Poll Extension for EPP](https://www.rfc-editor.org/rfc/rfc8590) 367 - [10] [RFC 9167 – Registry Maintenance Notification for EPP](https://www.rfc-editor.org/rfc/rfc9167)