Redis是什么?
Redis是数据库的意思。Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
Redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
Redis运行在内存中但是可以持久化到磁盘,所以在对不同数据集进行高速读写时需要权衡内存,因为数据量不能大于硬件内存。在内存数据库方面的另一个优点是,相比在磁盘上相同的复杂的数据结构,在内存中操作起来非常简单,这样Redis可以做很多内部复杂性很强的事情。同时,在磁盘格式方面他们是紧凑的以追加的方式产生的,因为他们并不需要进行随机访问。
Redis的出现,很大程度补偿了memcached这类key/value存储的不足,在部分场合可以对关系数据库起到很好的补充作用。
Redis 基本语法
Redis 配置
Redis 的配置文件位于 Redis 安装目录下,文件名为 redis.conf(Windows 名为redis.windows.conf)。你可以通过 CONFIG 命令查看或设置配置项。
Redis CONFIG 查看配置命令格式如下:
redis 127.0.0.1:6379> CONFIG GET CONFIG_SETTING_NAME
使用 * 号获取所有配置项:
redis 127.0.0.1:6379> CONFIG GET * 1) "dbfilename" 2) "dump.rdb" 3) "requirepass" 4) "" 5) "masterauth" 6) "" 7) "unixsocket" 8) "" 9) "logfile" ......
编辑配置
你可以通过修改 redis.conf 文件或使用 CONFIG set 命令来修改配置。
CONFIG SET 命令基本语法:
redis 127.0.0.1:6379> CONFIG SET CONFIG_SETTING_NAME NEW_CONFIG_VALUE
实例
redis 127.0.0.1:6379> CONFIG SET loglevel "notice" OK redis 127.0.0.1:6379> CONFIG GET loglevel 1) "loglevel" 2) "notice"
参数说明
几个redis.conf 配置项说明如下:
配置项 | 说明 |
port 6379 |
指定 Redis 监听端口,默认端口为 6379 |
bind 127.0.0.1 |
绑定的主机地址 |
timeout 300 |
当客户端闲置多长秒后关闭连接,如果指定为 0 ,表示关闭该功能 |
databases 16 |
设置数据库的数量,默认数据库为0,可以使用 SELECT 命令在连接上指定数据库id |
save <seconds> <changes> |
指定在多长时间内,有多少次更新操作,就将数据同步到数据文件,可以多个条件配合 |
dbfilename dump.rdb |
指定本地数据库文件名,默认值为 dump.rdb |
dir ./ |
指定本地数据库存放目录 |
详情请见:https://www.657260.com/redis/redis-conf.html
Redis 命令
Redis 命令用于在 redis 服务上执行操作。要在 redis 服务上执行命令需要一个 redis 客户端。Redis 客户端在我们之前下载的的 redis 的安装包中。
Redis 客户端的基本语法为:
$ redis-cli
以下实例讲解了如何启动 redis 客户端:
启动 redis 客户端,打开终端并输入命令 redis-cli。该命令会连接本地的 redis 服务。
$ redis-cli redis 127.0.0.1:6379> redis 127.0.0.1:6379> PING PONG
在以上实例中我们连接到本地的 redis 服务并执行 PING 命令,该命令用于检测 redis 服务是否启动,如果服务器运作正常的话,会返回一个 PONG 。
在远程服务上执行命令
如果需要在远程 redis 服务上执行命令,同样我们使用的也是 redis-cli 命令。
语法
$ redis-cli -h host -p port -a password
以下实例演示了如何连接到主机为 127.0.0.1,端口为 6379 ,密码为 mypass 的 redis 服务上。
$redis-cli -h 127.0.0.1 -p 6379 -a "mypass" redis 127.0.0.1:6379> redis 127.0.0.1:6379> PING PONG
SET 命令
Redis SET 命令用于设置给定 key 的值。如果 key 已经存储其他值, SET 就覆写旧值,且无视类型。
redis SET 命令基本语法如下:
redis 127.0.0.1:6379> SET KEY_NAME VALUE
Get 命令
Redis Get 命令用于获取指定 key 的值。如果 key 不存在,返回 nil 。
redis Get 命令基本语法如下:
redis 127.0.0.1:6379> GET KEY_NAME
Flushall 命令
Redis Flushall 命令用于清空整个 Redis 服务器的数据(删除所有数据库的所有 key )。
redis Flushall 命令基本语法如下:
redis 127.0.0.1:6379> FLUSHALL
Redis 数据备份与恢复
Redis SAVE 命令用于创建当前数据库的备份。Save 命令执行一个同步保存操作,将当前 Redis 实例的所有数据快照(snapshot)以默认 RDB 文件的形式保存到硬盘。
redis Save 命令基本语法如下:
redis 127.0.0.1:6379> SAVE OK
该命令将在 redis 安装目录中创建dump.rdb文件。
恢复数据
如果需要恢复数据,只需将备份文件 (dump.rdb) 移动到 redis 安装目录并启动服务即可。获取 redis 目录可以使用 CONFIG 命令,如下所示:
redis 127.0.0.1:6379> CONFIG GET dir 1) "dir" 2) "/usr/local/redis/bin"
以上命令 CONFIG GET dir 输出的 redis 安装目录为 /usr/local/redis/bin。
Redis 安全
我们可以通过 redis 的配置文件设置密码参数,这样客户端连接到 redis 服务就需要密码验证,这样可以让你的 redis 服务更安全。
我们可以通过以下命令查看是否设置了密码验证:
127.0.0.1:6379> CONFIG get requirepass 1) "requirepass" 2) ""
默认情况下 requirepass 参数是空的,也就是说默认情况下是无密码验证的,这就意味着你无需通过密码验证就可以连接到 redis 服务。
你可以通过以下命令来修改该参数:
127.0.0.1:6379> CONFIG set requirepass "657260" OK 127.0.0.1:6379> CONFIG get requirepass 1) "requirepass" 2) "657260"
设置密码后,客户端连接 redis 服务就需要密码验证,否则无法执行命令。
语法
AUTH 命令基本语法格式如下:
127.0.0.1:6379> AUTH password
该命令用于检测给定的密码和配置文件中的密码是否相符。
redis Auth 命令基本语法如下:
redis 127.0.0.1:6379> AUTH PASSWORD
密码匹配时返回 OK ,否则返回一个错误。
实例
127.0.0.1:6379> AUTH "657260" OK 127.0.0.1:6379> SET mykey "Test value" OK 127.0.0.1:6379> GET mykey "Test value"
Redis 环境搭建
第一步:ubuntu中下载安装Redis并解压:
wget http://download.redis.io/releases/redis-5.0.12.tar.gz tar -zxvf redis-5.0.12.tar.gz
第二步:下载并解压好以后,进入到Redis目录中,执行 make
,通过make编译的方式来安装:
make
如上图提示 "It’s a good idea to run 'make test' " 则代表编译安装成功。
第四步:make结束后,进入src目录,将redis-server和redis-cli拷贝到/usr/bin目录下(这样启动redis-server和redis-cli就不用每次都进入安装目录了)
cd src cp redis-cli /usr/bin cp redis-server /usr/bin
第五步:返回redis-2.8.17目录,将redis.conf拷贝到/etc目录下。
cd ../ cp redis.conf /etc
第六步:使用/etc目录下的reids.conf文件中的配置启动redis服务:
redis-server /etc/redis.conf
Redis 未授权访问漏洞
Redis 默认情况下,会绑定在 0.0.0.0:6379,如果没有进行采用相关的策略,比如添加防火墙规则避免其他非信任来源 ip 访问等,这样将会将 Redis 服务暴露到公网上,如果在没有设置密码认证(一般为空),会导致任意用户在可以访问目标服务器的情况下未授权访问 Redis 以及读取 Redis 的数据。攻击者在未授权访问 Redis 的情况下,可以利用 Redis 自身的提供的 config 命令像目标主机写WebShell、写SSH公钥、创建计划任务反弹Shell等。其思路都是一样的,就是先将Redis的本地数据库存放目录设置为web目录、~/.ssh目录或/var/spool/cron目录等,然后将dbfilename(本地数据库文件名)设置为文件名你想要写入的文件名称,最后再执行save或bgsave保存,则我们就指定的目录里写入指定的文件了。
简单说,漏洞的产生条件有以下两点:
- redis 绑定在 0.0.0.0:6379,且没有进行添加防火墙规则避免其他非信任来源ip访问等相关安全策略,直接暴露在公网。
- 没有设置密码认证(一般为空),可以免密码远程登录redis服务。
漏洞危害:
- 攻击者无需认证就可以访问到内部数据,可能导致敏感信息泄露,黑客也可以恶意执行flushall来清空所有数据;
- 攻击者可通过EVAL执行lua代码,或通过数据备份功能往磁盘写入后门文件;
- 最严重的情况,如果Redis以root身份运行,黑客可以给root账户写入SSH公钥文件,直接通过SSH登录受害服务器。
下面我们对 Redis 未授权访问漏洞进行测试。
实验环境:
- 攻击机Kali:192.168.43.247
- 受害机Ubuntu:192.168.43.82
此时受害机Ubuntu中的Redis服务(作为服务端)已经启动了,作为攻击机的kali系统,需要按照之前的步骤同样安装Redis(作为客户端)。安装成功后在攻击机上使用redis客户端直接无账号成功登录Ubuntu上的Redis服务端,并且成功列出服务端Redis的信息:
redis-cli -h 192.168.43.82