Throughout this course, you have seen SSRF vulnerabilities grow progressively more dangerous. You started by reading AWS metadata and internal API responses, then learned how attackers bypass basic defenses using alternative IP formats and redirects. In the previous lesson, you exploited blind SSRF through timing analysis and DNS exfiltration to map networks without seeing response content.
Now you will learn the most devastating SSRF attack: chaining the vulnerability with internal service exploitation to achieve Remote Code Execution (RCE). When attackers combine SSRF with CRLF injection techniques, they can execute arbitrary commands on your server, install backdoors, and take complete control of your infrastructure. This lesson covers how Redis and similar internal services become attack targets, introduces CRLF injection as the primary exploitation technique for HTTP-based attacks, and shows you how to build defense-in-depth protections using protocol restrictions, port allowlists, and network segmentation.
Many organizations follow a "firewall mentality" where they assume anything inside the network perimeter is trustworthy. This leads to a dangerous pattern: internal services like Redis, Memcached, Elasticsearch, and internal APIs run without authentication because they are "only accessible from inside the network." However, SSRF vulnerabilities completely break this assumption by turning your own application server into a proxy that bridges the external attacker to the internal network.
Why Redis is particularly vulnerable:
- No authentication by default — administrators assume network isolation provides sufficient security
- Text-based protocol — commands like
SET key valueare sent as plainASCIItext overTCP, making them exploitable throughHTTPrequests - Tolerant parsing — Redis can extract valid commands even when mixed with HTTP garbage data
- Powerful features — the
CONFIGcommand allows changing whereRediswrites database files, which attackers abuse to write malicious files to sensitive locations
Other vulnerable internal services:
- Memcached — text-based protocol for caching, typically runs without authentication
- Elasticsearch — powerful
HTTPAPIthat allows data querying, index manipulation, and script execution (in older versions) - Internal REST APIs — often trust requests simply because they originate from the application server's
IPaddress
The principle of network-level trust fails spectacularly in the presence of SSRF. When your application makes an HTTP request to a user-controlled URL, that request originates from the application server itself, carrying the server's IP address and network context.
From the perspective of internal services:
Redissees a connection from the application server and processes commands without question- Cloud metadata services see a request from an
EC2instance and return credentials - Internal
APIssee a familiar sourceIPand bypass authentication
This is why SSRF is so dangerous — it inherits all the trust your infrastructure places in your own application servers.
When exploiting internal services through SSRF, the most practical technique in modern web applications is CRLF injection. The CRLF sequence (\r\n or URL-encoded as %0d%0a) represents a newline in network protocols. Many protocols, including Redis, use newlines to separate commands, so injecting CRLF sequences lets attackers break out of the current request context and inject their own commands.
Why CRLF injection is the primary technique:
Most modern HTTP client libraries like axios (which our pastebin uses), fetch, and requests only support http:// and https:// protocols. They will reject or throw errors for exotic protocols like gopher://, file://, or dict://. This means that in real-world applications built with these libraries, attackers must rely on CRLF injection over HTTP to communicate with text-based internal services.
How CRLF injection works with Redis:
Redis is remarkably tolerant of garbage data. When you send an HTTP request to Redis on port 6379, the HTTP headers (like GET / HTTP/1.1 and Host: 127.0.0.1) are garbage from Redis's perspective. However, Redis simply ignores what it cannot parse and looks for valid commands within the data stream. By injecting CRLF sequences followed by Redis commands into the URL path, attackers can smuggle commands that Redis will execute.
URL encoding considerations:
- Spaces →
%20 - Newlines →
%0d%0a(CR+LF) - Asterisks →
%2a - Dollar signs →
%24
When crafting CRLF injection payloads, attackers must carefully encode every special character to ensure the payload survives URL parsing and arrives at Redis with the intended structure.
You may encounter references to the gopher protocol (gopher://) in SSRF literature and security research. Gopher is an ancient internet protocol that allows sending raw TCP data directly to a target without HTTP headers — giving attackers complete control over every byte sent. This makes it theoretically ideal for exploiting text-based services like Redis.
However, gopher is not supported by modern HTTP client libraries. Libraries like axios, node-fetch, requests (Python), and others validate the protocol scheme and reject anything other than http:// and https://. Attempting to use gopher:// with these libraries will result in an error, not a connection to the target service.
When gopher attacks are possible:
- Applications using older or custom HTTP clients that support arbitrary protocols
- Proxy services that forward requests without protocol validation
- Security testing tools like
curl(which supports gopher natively)
For our pastebin application (and most modern web applications), CRLF injection over HTTP is the practical attack vector, while gopher remains a theoretical consideration for legacy systems or specialized environments.
The pastebin application has an endpoint that imports content from URLs. This endpoint makes HTTP requests to user-provided URLs and returns the response content. Without proper validation, it accepts any destination including internal services:
Why this is dangerous:
- Accepts any
urlparameter without validation validateStatus: () => truetreats anyHTTPstatus code as success- Allows requests to any port, including internal services like Redis on 6379
The attack works by injecting Redis commands into the URL path using CRLF sequences. When axios makes an HTTP request to http://127.0.0.1:6379/, it sends something like:
By crafting a path that contains %0d%0a (CRLF) followed by Redis commands, we can inject commands that Redis will execute. Redis ignores the HTTP garbage and extracts the valid commands from the data stream.
Attack payload breakdown:
When URL-decoded and sent to Redis, this becomes:
What each injected command does:
- FLUSHALL — deletes all existing keys in
Redis(optional but ensures clean exploit) - SET 1 RCE_payload — stores a payload value (in a real attack, this would contain a cron job or SSH key)
- CONFIG SET dir /tmp — tells
Redisto save database file in/tmp(or/var/spool/cron/for cron-based RCE) - CONFIG SET dbfilename exploit — names the output file
- SAVE — writes the in-memory database to disk
To exploit the vulnerable endpoint using CRLF injection:
When this request is processed:
- The vulnerable endpoint receives the URL
- Axios makes an HTTP GET request to
127.0.0.1:6379with the crafted path - Redis receives the connection and parses the data stream
- Redis ignores the HTTP headers but executes the injected commands
- The payload is written to
/tmp/exploit
In a real attack scenario, the attacker would:
- Set the directory to
/var/spool/cron/(cron job directory) - Set the filename to
root(to create a cron job for the root user) - Include a reverse shell command in the SET payload
The cron daemon would then execute the malicious job, giving the attacker shell access.
Redis's protocol tolerance is both a feature and a security liability:
- Redis uses a simple text-based protocol (RESP - Redis Serialization Protocol)
- It processes commands line by line
- Invalid commands or garbage data generate errors but don't terminate the connection
- Valid commands embedded in garbage are still executed
This tolerance, combined with powerful administrative commands like CONFIG, makes Redis an attractive target for SSRF exploitation.
Throughout previous lessons, you implemented protocol restrictions, port allowlisting, and DNS-based IP validation. Now you'll add the final critical layer: CRLF injection prevention.
In this lesson, you'll see how to implement a seven-layer defense-in-depth middleware that protects against SSRF escalation to RCE. We'll walk through the first five layers here, and in the upcoming practice, you'll complete the implementation by adding IP range validation and CRLF injection prevention:
- URL parsing and validation (ensure proper format)
- Protocol blocklist (block dangerous protocols)
- Protocol allowlist (only allow http/https)
- Port restriction (only allow standard web ports: 80, 443)
- DNS resolution (convert hostnames to IPs)
- IP range validation (block internal networks) — you'll implement this in practice
- CRLF injection prevention (block protocol smuggling) — you'll implement this in practice
Create the middleware file and define security parameters:
Why these restrictions matter:
- ALLOWED_PORTS — restricts communication to standard web ports, preventing access to internal services like
Redis(6379),PostgreSQL(5432), etc. - BLOCKED_PROTOCOLS — while modern HTTP clients already reject these, explicitly blocking them provides defense-in-depth and protects against future library changes or alternative code paths
The first defense layer validates URL format. Malformed URLs might bypass subsequent validation checks, so we catch them immediately.
Defense-in-depth approach:
- First check blocks known dangerous protocols explicitly
- Second check uses positive security (only allow known-good)
- If someone forgets to block a new dangerous protocol, the allowlist catches it
- Even though axios already rejects non-HTTP protocols, this explicit check provides logging, consistent error messages, and protection if the HTTP client changes
This is the critical defense against Redis exploitation. Even with CRLF injection possible, attackers cannot reach Redis on port 6379 if we only allow ports 80 and 443. This single check blocks the entire class of internal service attacks we've discussed.
Critical defense against internal network access:
- Performs
DNSlookup to get actualIPaddresses - Handles
DNS-based bypasses (domains pointing to internalIPs) - Only accepts
unicast(publicly routable) addresses - Blocks:
127.0.0.1,192.168.x.x,10.x.x.x,172.16-31.x.x,169.254.169.254
Raw CRLF characters should never appear in properly formatted URLs. While browsers and most clients encode these characters, explicitly checking for them catches direct API attacks where an attacker might send raw newlines. This prevents the protocol smuggling attacks we demonstrated against Redis.
The protected endpoint validates all URLs before making any external requests. If validation fails, the request is rejected with a 400 Bad Request response.
Why this layered approach works:
Even if one defense fails, others provide backup protection:
- CRLF injection attempted → CRLF check blocks it
- CRLF check bypassed → Port restriction blocks Redis access
- Port restriction bypassed → IP validation blocks internal networks
- DNS rebinding attempted → IP validation catches the internal IP
This is defense-in-depth: multiple independent layers that must all be bypassed for an attack to succeed.
While code-level defenses are essential, they are not sufficient on their own. Application code can have bugs, new vulnerabilities might be discovered in HTTP libraries, and zero-day exploits might bypass validation logic. Network segmentation operates independently of your application code and provides a critical safety net.
Your application servers only need to communicate with specific internal services for legitimate business reasons. For example:
- Web application needs:
Rediscache,PostgreSQLdatabase, authenticationAPI - Web application doesn't need: metrics service, backup server,
CI/CDsystem,VPNgateway
Implementation strategy:
- Deploy application servers in one subnet (
10.0.1.0/24) - Deploy
Redisservers in different subnet (10.0.2.0/24) - Configure security groups/firewall rules:
- Allow:
10.0.1.0/24→10.0.2.0/24on port6379 - Deny: everything else
- Allow:
Result: Even if an attacker achieves SSRF and bypasses code-level validation, the network infrastructure blocks unauthorized connections.
Cloud platforms:
- AWS Security Groups — define inbound/outbound rules based on
IPranges and ports - Azure Network Security Groups — similar functionality for Azure infrastructure
- GCP Firewall Rules — protect Google Cloud resources
On-premises:
- Enterprise firewall appliances
- Linux
iptablesrules - Hardware network segmentation
Pattern: Deny by default, allow only necessary connections, log everything.
Run internal services with authentication even behind firewalls:
- Redis — configure
requirepassdirective to require passwords - PostgreSQL/MySQL — strong passwords and limited user privileges
- Internal APIs — use
APIkeys orJWTtokens even for internal callers
Defense-in-depth result:
Even if an attacker achieves SSRF AND the network firewall fails (misconfiguration or lateral movement), they still cannot interact with the service without valid credentials. Multiple independent security controls must all be bypassed for attacks to succeed.
You have completed your journey through SSRF vulnerabilities, progressing from basic data theft to the ultimate attack: remote code execution through CRLF injection. You learned that internal services like Redis become dangerous targets when they assume network-level trust, that CRLF injection enables command smuggling through HTTP requests to text-based services, and that attackers chain these capabilities to write malicious files and potentially spawn reverse shells.
Your defense-in-depth approach combines protocol restrictions, port allowlists, DNS-based IP validation, and CRLF injection prevention at the code level with network segmentation and service authentication at the infrastructure level.
In the upcoming practice exercises, you will exploit the vulnerable URL import endpoint to achieve command execution against Redis using CRLF injection, then implement the complete ssrfGuard middleware to eliminate all SSRF attack vectors. Congratulations on completing this course — you now understand both the attacker's perspective and the defender's toolbox for one of the most dangerous web application vulnerabilities.
