SSRF¶
Introduction to SSRF¶
SSRF, Server-Side Request Forgery, is a vulnerability where an attacker constructs a request that is initiated by the server. Generally, SSRF attacks target internal systems that are inaccessible from the external network.
The root cause of this vulnerability is that the server provides functionality to fetch data from other server applications without filtering or restricting the target address.
There are mainly 5 types of attacks that an attacker can achieve using SSRF:
- Port scanning of the external network, the server's internal network, and localhost to obtain banner information of some services
- Attacking applications running on the internal network or localhost (e.g., buffer overflow)
- Fingerprinting internal web applications by accessing default files
- Attacking internal and external web applications, mainly attacks achievable with GET parameters (e.g., Struts2, SQL injection, etc.)
- Reading local files using the
fileprotocol, etc.
Scenarios Where SSRF Vulnerabilities Appear¶
- Any place that can initiate outbound network requests may have SSRF vulnerabilities
- Requesting resources from remote servers (Upload from URL, Import & Export RSS Feed)
- Built-in database functionality (Oracle, MongoDB, MSSQL, Postgres, CouchDB)
- Webmail fetching emails from other mailboxes (POP3, IMAP, SMTP)
- File processing, encoding processing, attribute information processing (ffmpeg, ImageMagick, DOCX, PDF, XML)
Common Backend Implementations¶
-
file_get_contents<?php if (isset($_POST['url'])) { $content = file_get_contents($_POST['url']); $filename ='./images/'.rand().';img1.jpg'; file_put_contents($filename, $content); echo $_POST['url']; $img = "<img src=\"".$filename."\"/>"; } echo $img; ?>This code uses the
file_get_contentsfunction to fetch an image from a user-specified URL. It then saves it to disk with a random filename and displays it to the user. -
fsockopen()<?php function GetFile($host,$port,$link) { $fp = fsockopen($host, intval($port), $errno, $errstr, 30); if (!$fp) { echo "$errstr (error number $errno) \n"; } else { $out = "GET $link HTTP/1.1\r\n"; $out .= "Host: $host\r\n"; $out .= "Connection: Close\r\n\r\n"; $out .= "\r\n"; fwrite($fp, $out); $contents=''; while (!feof($fp)) { $contents.= fgets($fp, 1024); } fclose($fp); return $contents; } } ?>This code uses the
fsockopenfunction to fetch data (files or HTML) from a user-specified URL. This function uses a socket to establish a TCP connection with the server and transmits raw data. -
curl_exec()<?php if (isset($_POST['url'])) { $link = $_POST['url']; $curlobj = curl_init(); curl_setopt($curlobj, CURLOPT_POST, 0); curl_setopt($curlobj,CURLOPT_URL,$link); curl_setopt($curlobj, CURLOPT_RETURNTRANSFER, 1); $result=curl_exec($curlobj); curl_close($curlobj); $filename = './curled/'.rand().'.txt'; file_put_contents($filename, $result); echo $result; } ?>Using
curlto fetch data.
Scenarios That Hinder SSRF Exploitation¶
- The server has OpenSSL enabled, preventing interactive exploitation
- Server-side authentication required (Cookies & User:Pass), preventing perfect exploitation
- Restricting request ports to common HTTP ports, such as 80, 443, 8080, 8090
- Disabling unnecessary protocols. Only allowing HTTP and HTTPS requests. This can prevent issues caused by file:///, gopher://, ftp://, etc.
- Unified error messages to prevent users from determining remote server port status based on error messages
Using SSRF for Port Scanning¶
Determine port status based on the server's response information. Most applications do not distinguish ports, and port status can be determined through the returned banner information.
Backend implementation:
<?php
if (isset($_POST['url'])) {
$link = $_POST['url'];
$filename = './curled/'.rand().'txt';
$curlobj = curl_init($link);
$fp = fopen($filename,"w");
curl_setopt($curlobj, CURLOPT_FILE, $fp);
curl_setopt($curlobj, CURLOPT_HEADER, 0);
curl_exec($curlobj);
curl_close($curlobj);
fclose($fp);
$fp = fopen($filename,"r");
$result = fread($fp, filesize($filename));
fclose($fp);
echo $result;
}
?>
Construct a frontend page:
<html>
<body>
<form name="px" method="post" action="http://127.0.0.1/ss.php">
<input type="text" name="url" value="">
<input type="submit" name="commit" value="submit">
</form>
<script></script>
</body>
</html>
Requesting non-HTTP ports can return banner information.
Alternatively, 302 redirects can be used to bypass HTTP protocol restrictions.
Helper script:
<?php
$ip = $_GET['ip'];
$port = $_GET['port'];
$scheme = $_GET['s'];
$data = $_GET['data'];
header("Location: $scheme://$ip:$port/$data");
?>
Tencent SSRF Vulnerability (Excellent Exploitation Point) with Exploitation Script
Protocol Exploitation¶
-
Dict Protocol
dict://fuzz.wuyun.org:8080/helo:dict -
Gopher Protocol
gopher://fuzz.wuyun.org:8080/gopher -
File Protocol
file:///etc/passwd
Bypass Techniques¶
-
Changing IP Address Notation For example,
192.168.0.1- Octal format:
0300.0250.0.1 - Hexadecimal format:
0xC0.0xA8.0.1 - Decimal integer format:
3232235521 - Hexadecimal integer format:
0xC0A80001 - There is also a special abbreviated mode, for example, the IP
10.0.0.1can be written as10.1
- Octal format:
-
Exploiting URL Parsing Issues In some cases, the backend program may parse the accessed URL and filter the parsed host address. This can lead to improper URL parameter parsing, allowing bypass of the filter. For example:
http://www.baidu.com@192.168.0.1/andhttp://192.168.0.1both request the content of192.168.0.1- A domain that can point to any IP
xip.io:http://127.0.0.1.xip.io/==>http://127.0.0.1/ - Short URL
http://dwz.cn/11SMa==>http://127.0.0.1 - Using fullwidth period
。:127。0。0。1==>127.0.0.1 - Using Enclosed Alphanumerics
ⓔⓧⓐⓜⓟⓛⓔ.ⓒⓞⓜ >>> example.com List: ① ② ③ ④ ⑤ ⑥ ⑦ ⑧ ⑨ ⑩ ⑪ ⑫ ⑬ ⑭ ⑮ ⑯ ⑰ ⑱ ⑲ ⑳ ⑴ ⑵ ⑶ ⑷ ⑸ ⑹ ⑺ ⑻ ⑼ ⑽ ⑾ ⑿ ⒀ ⒁ ⒂ ⒃ ⒄ ⒅ ⒆ ⒇ ⒈ ⒉ ⒊ ⒋ ⒌ ⒍ ⒎ ⒏ ⒐ ⒑ ⒒ ⒓ ⒔ ⒕ ⒖ ⒗ ⒘ ⒙ ⒚ ⒛ ⒜ ⒝ ⒞ ⒟ ⒠ ⒡ ⒢ ⒣ ⒤ ⒥ ⒦ ⒧ ⒨ ⒩ ⒪ ⒫ ⒬ ⒭ ⒮ ⒯ ⒰ ⒱ ⒲ ⒳ ⒴ ⒵ Ⓐ Ⓑ Ⓒ Ⓓ Ⓔ Ⓕ Ⓖ Ⓗ Ⓘ Ⓙ Ⓚ Ⓛ Ⓜ Ⓝ Ⓞ Ⓟ Ⓠ Ⓡ Ⓢ Ⓣ Ⓤ Ⓥ Ⓦ Ⓧ Ⓨ Ⓩ ⓐ ⓑ ⓒ ⓓ ⓔ ⓕ ⓖ ⓗ ⓘ ⓙ ⓚ ⓛ ⓜ ⓝ ⓞ ⓟ ⓠ ⓡ ⓢ ⓣ ⓤ ⓥ ⓦ ⓧ ⓨ ⓩ ⓪ ⓫ ⓬ ⓭ ⓮ ⓯ ⓰ ⓱ ⓲ ⓳ ⓴ ⓵ ⓶ ⓷ ⓸ ⓹ ⓺ ⓻ ⓼ ⓽ ⓾ ⓿
Impact¶
- Port scanning of the external network, the server's internal network, and localhost to obtain banner information of some services;
- Attacking applications running on the internal network or localhost (e.g., buffer overflow);
- Fingerprinting internal web applications by accessing default files;
- Attacking internal and external web applications, mainly attacks achievable with GET parameters (e.g., Struts2, SQL injection, etc.);
- Reading local files using the file protocol, etc.