Related:
Summary
The pool metadata fetcher in crates/minibf sends an HTTP request to a URL from on-chain pool metadata. The fetcher does not restrict the target address. The fetcher does not limit the response size.
#1295 added the governance proposal metadata routes. The PR also added a restricted fetch path for those routes. The pinned implementation rejects non-public targets and filters DNS results. It also applies the same restriction to redirect targets. The body reader limits each response to 3000000 bytes. The pool fetcher does not use this path.
Affected code
Problem 1: the fetcher does not restrict the target
The client sends the request to any URL in the pool metadata. The URL can point to a private address. The URL can point to a loopback address. The URL can point to a link-local address. The URL can point to a cloud metadata service.
The hash check does not help here. The client reaches the target and reads the body before the hash check. The redirect policy permits three redirects. The policy does not restrict the redirect target.
The client uses the default DNS resolution. A hostname can resolve to a private address. A hostname can return a different address for a second request. This behavior makes a DNS rebinding attack possible.
Problem 2: the fetcher does not limit the response size
The client calls bytes() to read the full body. The client does not set a size limit. The client does not reject a large Content-Length value. A large body uses a large amount of memory.
The pool list route starts one fetch for each pool. The route runs the fetches at the same time. Many large bodies increase the total memory use.
Impact
An attacker can publish pool metadata with a hostile URL. A request to the pool endpoints can then reach an internal service. A large response can use too much memory.
Suggested fix
Use the restricted fetch path from #1295. Reuse its target restrictions. Reuse its bounded body reader. Make the path reusable for pool metadata and governance metadata.
- Reject a URL that is not HTTP or HTTPS.
- Reject a URL whose host is a private or special IP address.
- Resolve each hostname through a DNS filter that removes non-public addresses.
- Apply the same address restriction to every redirect.
- Do not use a configured proxy for these requests.
- If the
Content-Length is more than the limit, reject the response.
- Read the body in chunks and stop at the limit.
- Use a limit of 3000000 bytes, which is the
cardano-db-sync limit for vote metadata.
References
Related:
/governance/proposals/*/metadataroutes #1295Summary
The pool metadata fetcher in
crates/minibfsends an HTTP request to a URL from on-chain pool metadata. The fetcher does not restrict the target address. The fetcher does not limit the response size.#1295 added the governance proposal metadata routes. The PR also added a restricted fetch path for those routes. The pinned implementation rejects non-public targets and filters DNS results. It also applies the same restriction to redirect targets. The body reader limits each response to 3000000 bytes. The pool fetcher does not use this path.
Affected code
pool_offchain_metadatabuilds an HTTP client and reads the complete body.fetch_pool_metadata_with_errorbuilds a second HTTP client with the same problems.Problem 1: the fetcher does not restrict the target
The client sends the request to any URL in the pool metadata. The URL can point to a private address. The URL can point to a loopback address. The URL can point to a link-local address. The URL can point to a cloud metadata service.
The hash check does not help here. The client reaches the target and reads the body before the hash check. The redirect policy permits three redirects. The policy does not restrict the redirect target.
The client uses the default DNS resolution. A hostname can resolve to a private address. A hostname can return a different address for a second request. This behavior makes a DNS rebinding attack possible.
Problem 2: the fetcher does not limit the response size
The client calls
bytes()to read the full body. The client does not set a size limit. The client does not reject a largeContent-Lengthvalue. A large body uses a large amount of memory.The pool list route starts one fetch for each pool. The route runs the fetches at the same time. Many large bodies increase the total memory use.
Impact
An attacker can publish pool metadata with a hostile URL. A request to the pool endpoints can then reach an internal service. A large response can use too much memory.
Suggested fix
Use the restricted fetch path from #1295. Reuse its target restrictions. Reuse its bounded body reader. Make the path reusable for pool metadata and governance metadata.
Content-Lengthis more than the limit, reject the response.cardano-db-synclimit for vote metadata.References
pool_offchain_metadatabuilds an unrestricted client and reads an unbounded body.fetch_pool_metadata_with_errorbuilds a second unrestricted client.fetch_pool_metadata_with_errorsends the unchecked request and reads an unbounded body.cardano-db-syncrestricts connections to private and special addresses.cardano-db-syncreads a bounded body and rejects a body that exceeds the limit.