碳基体

奋斗在产品安全第一线的安全妹子

大数据之Redis渗透人员入门—— 安装配置、基本操作及常用管理工具

大数据滋生了NoSQL数据库,除了MongoDB,Redis更是各种系统的常客。作为一名作渗透的,很明显我们需要普及一下这方面的常识,最起码 ,当得知对方使用redis数据库的时候,知道如何查看里面的信息。


首先我们实际安装一个redis让其跑起来看看手感。


一、安装

wget https://download.redis.io/releases/redis-2.8.7.tar.gz

tar zxvf redis-2.8.7.tar.gz

cd redis-2.8.7

make test

make

安装成功后要注意的重要的文件有以下这些:


(1)服务端

src/redis-server


(2)客户端 (现在市面上已经有各种各样的客户端le)

src/redis-cls


(3)配置文件

redis.conf


然后将可执行文件放置在$PATH环境目录下,便于以后执行程序时可以不用输入完整的路径,

cp redis-server /usr/local/bin/

cp redis-cli /usr/local/bin/


接下来我们可以看看redis配置文件redis.conf,我就超级喜欢看各种配置文件,总能发现惊喜。我将常用的配置项列出来

#是否将redis设置为守护程序,默认为no

daemonize yes


#如果设置为守护程序,需要指定pid文件

pidfile /var/run/redis/redis-server.pid


#redis监听端口 (渗透人员对端口肯定超级敏感

port 65432


#如果指定从unix socket连接,port设置为0

#port 0

#unixsocket /tmp/redis.sock

#unixsocketperm 777


#包含的其他配置文件

include /etc/redis/common.conf


#绑定监听端口 

bind 127.0.0.1 (渗透人员注意,连接redis的ip限制,跳板准备好


#工作目录

dir /home/lidanqing01/redis (渗透人员注意,数据库存放地址


#数据库名字

dbfilename redis.rdb


#RDB持久化(一般选择这种)

save 900 1  #900秒内如果超过1个key被修改,则发起快照保存

save 300 10 #300秒内容如超过10个key被修改,则发起快照保存

save 60 10000


#AOF持久化

appendonly yes              //启用aof持久化方式

# appendfsync always      //每次收到写命令就立即强制写入磁盘,最慢的,但是保证完全的持久化,不推荐使用

appendfsync everysec     //每秒钟强制写入磁盘一次,在性能和持久化方面做了很好的折中,推荐

# appendfsync no    //完全依赖os,性能最好,持久化没保证


#数据库数量,redis数据库的概念和MySQL/MongoDB都不同,一个redis实例的所有数据库都采用同样的访问控制,即同样的认证密码,一般情况下,将同一个APP按不同环境,例如生产环境,测试环境放在不同的数据库中。而不能将不同的APP放在不同的数据库中,得新建一个redis实例,原因是不隔离嘛。 

MySQL数据库相当于一个抽屉柜,每个抽屉都有一把锁,而Redis数据库则是一个有锁的抽屉,但这个抽屉有不同的挡板

databases 16


#身份认证  (渗透人员注意:是明文密码!!

requirepass xxxxx


#主从同步 

slaveof xxxx(master redis host) xxx(master redis port) (渗透人员注意:如果发现的是slave,这里提供的master的信息和密码

masterauth xxxxxxxx


#日志记录

syslog-enabled yes

syslog-ident redis

附加说明的配置项都是和安全相关的重要配置,redis在安全上并没有过多的考虑,用《redis入门指南》这本书上的话说


“redis的安全设计是在"Redis运行在可信环境下", 在生产环节运行时不允许外界直接连接到Redis服务器上,而应该通过应用程序进行中转”


正是这样,或许渗透人员能看到redis中的财富并能好好利用利用。


二、启动/关闭操作

好了,现在可以跑起来了


启动服务端

redis-server redis.conf(配置文件路径)



客户端连接redis

./redis-cli  -h host(默认为127.0.0.1)-p 65432(默认为6379)-a xxxx(密码)

或者

./redis-cli  -h host(默认为127.0.0.1)-p 65432(默认为6379)

127.0.0.1:65432> auth xxxx(密码)
OK

或者从socket文件连接

redis-cli -s /tmp/redis.sock


关闭redis

redis-cli -p 65432  -a xxxx(密码) shutdown


三、redis启动脚本 

我们也可以写一个启动脚本,放在/etc/init.d/下方便操作


脚本基于《redis入门指南》(推荐这本书)修改,增加了需要认证的部分

vim /etc/init.d/redis_init_script

#!/bin/sh

#这里替换成实际的配置项
REDISPORT=65432
EXEC=/usr/local/bin/redis-server
CLIEXEC=/usr/local/bin/redis-cli
PIDFILE=/var/run/redis.pid
CONF="/home/work/lidanqing01/redis.conf"
PASSWD="xxxxx"

case "$1" in
    start)
        if [ -f $PIDFILE ]
        then
            echo " PIDFILE exists, process is already running or crashed"
        else
            echo " Starting Redis Server ..."
            $EXEC $CONF
        fi
    ;;

    stop)
        if [ ! -f $PIDFILE ]
        then
            echo "PIDFILE does not exist, process is not running"
        else
            PID=$(cat $PIDFILE)
            echo "Stopping ..."
            $CLIEXEC -p $REDISPORT -a $PASSWD shutdown

            while [ -x "/proc/{$PID}" ]
            do
                echo "Waiting for Redis to shutdown ..."
                sleep 1
            done

            echo "Redis stopped"
        fi
    ;;

    *)
        echo "Please use start or stop as first argument"
    ;;
esac

在运行这个脚本的时候,发生了一个小插曲,我在windows下编辑然后再传到debain机器上,结果就报错了

# /etc/init.d/redis_init_script start

-bash: /etc/init.d/redis_init_script: /bin/sh^M: bad interpreter: No such file or directory

后来发现原因:sh对DOS格式(windows下编辑器默认格式)的文本解析有问题


解决方法:将DOS格式转换为UNIX格式

vim redis_init_script

:set ff    查看当前文本格式

fileformat=dos  


:set ff=unix 设置当前文本格式 

:wq



redis安装好了,也跑起来了,然后呢,我们需要普及一下redis数据库的基本常识,对于数据敏感的渗透者而言最应该了解的是redis 数据的格式及数据类型



四、基本数据类型及数据命名特点

redis采用key-value的形式存储数据, key就是数据的名字, value就是数据的值。


其中value可以有以下5种类型


(1)string字符串类型 :string可以看作byte 数组,最大上限是 1G字节 ,更多操作见help @string

(2)list列表类型: 每个子元素都是string类型的双向链表,链表的最大长度是 (2的 32次方 -1)  更多操作见help @list

(3)set集合类型 :string类型的无序集合,通过hash table实现的,set元素最大可以包含(2的32 次方-1) 更多操作见help @set

(4)sorted set有序集合类型 :string类型元素的集合,每个元素都会关联一个double类型的score,是skip list 和hash table的混合体 更多操作见help @sorted_set

(5)hash散列类型: 是一个string类型的field和value的映射表,更多操作见help @hash



redis喜欢采用 对象类型:对象ID:对象属性 这种格式来给数据取名字 



五、针对渗透人员的常见命令

接下来,我们在redis数据库里放置一些样本数据,通过这些数据来演示,当渗透人员连接到了一台redis数据库,如何查看里面的内容


我们先搭建一个包含五种数据类型的redis 数据库的实例,先不不用管命令的意思,当然最好使用 help 命令查看命令的意思


总的方针,Redis命令不区分大小写,忘记某个命令时,TAB键补全,忘记某个命令的意思时, help(空格)TAB键 查找吧


使用redis-cli连接上redis server


 (1) 增加string 字符串类型的数据

127.0.0.1:65432> set string_name xiaoge

OK

127.0.0.1:65432> append string_name ,tianzheng

(integer) 16


(2) 添加list列表类型的数据

127.0.0.1:65432> lpush list_programmer perl

(integer) 1

127.0.0.1:65432> lpush list_programmer python

(integer) 2

127.0.0.1:65432> lpush list_programmer lua

(integer) 3

127.0.0.1:65432> lpush list_programmer ruby

(integer) 4

127.0.0.1:65432> lpush list_programmer shell

(integer) 5

127.0.0.1:65432> lpush list_programmer javascript

(integer) 6

127.0.0.1:65432> lpush list_programmer R

(integer) 7


(3)添加set集合类型的数据

127.0.0.1:65432> sadd set_fruits apple

(integer) 1

127.0.0.1:65432> sadd set_fruits pear

(integer) 1

127.0.0.1:65432> sadd set_fruits orange

(integer) 1

127.0.0.1:65432> sadd set_fruits banana

(integer) 1

127.0.0.1:65432> sadd set_fruits pipeapple

(integer) 1

127.0.0.1:65432> sadd set_fruits strawbrew

(integer) 1



(4)添加sorted_set有序集合的数据

127.0.0.1:65432> zadd sorted_set_attacktype 10 webshell

(integer) 1

127.0.0.1:65432> zadd sorted_set_attacktype 9 command_exexute

(integer) 1

127.0.0.1:65432> zadd sorted_set_attacktype 8 sqli

(integer) 1

127.0.0.1:65432> zadd sorted_set_attacktype 7 file_upload

(integer) 1

127.0.0.1:65432> zadd sorted_set_attacktyp 6 file_include

(integer) 1

127.0.0.1:65432> zadd sorted_set_attacktyp 5 xss

(integer) 1



(5)添加hash

127.0.0.1:65432> hset hash_resume name tanjiti

(integer) 1

127.0.0.1:65432> hset hash_resume city shanghai

(integer) 1

127.0.0.1:65432> hset hash_resume gender female

(integer) 1


现在,测试数据搭建好了,我们来假想一下,当我们发现一台机器装有redis的时候,怎么做信息探测


第一步:看是否开启了redis服务,redis 的监听端口,使用的配置文件

-bash-4.2# ps aux | grep redis
root     21051  0.0  0.9  33128  1280 ?        Ssl  Mar18   0:05 /usr/local/bin/redis-server 127.0.0.1:65432  /etc/redis.conf 


我们知道了端口是65432,配置文件在/home/work/lidanqing01/redis.conf


第二步:然后查看redis.conf文件,看redis是否设置的认证密码,redis持久化数据库存储地址

requirepass xxxxxx

masterauth xxxxxx


可以知道认证密码为xxxxxx 


dir /home/lidanqing01/redis 

dbfilename redis.rdb  

可以知道持久化数据库存储在/home/lidanqing01/redis/redis.rdb


第三步:我们可以连接redis服务端,使用以下命令查看数据库的内容


首先,连接redis

redis-cli -p  65432-a xxxxxx


如果没有redis-cli,可以使用telnet,使用同样的命令,但返回会比较难看

-bash-4.2# telnet 127.0.0.1 65432
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
auth xxxxxxx
+OK
keys *
*5
$10
set_fruits
$11
string_name
$15
list_programmer
$11
hash_resume
$21
sorted_set_attacktype



然后,查看有哪些keys

127.0.0.1:65432> keys *
1) "set_fruits"
2) "string_name"
3) "list_programmer"
4) "hash_resume"
5) "sorted_set_attacktype"



接着,获得key的数据类型

返回值 string(字符串)、hash(散列)、list(列表) 、set(集合)、zset(有序集合)、none(该key不存在)

127.0.0.1:65432> type string_name
string
127.0.0.1:65432> type list_programmer
list
127.0.0.1:65432> type set_fruits
set
127.0.0.1:65432> type sorted_set_attacktype
zset
127.0.0.1:65432> type hash_resume
hash


最后,查看key对应的value,根据前面判断的key的数据类型,选择不同的查看方法,对命令不熟悉的我们,可以使用

help @string 

help @list

help @set

help @sorted_set

help @hash

来查看具体的方法


a.对string类型的

可以使用get获得string的值

127.0.0.1:65432> get string_name
"xiaoge,tianzheng"


b.对list类型的


可以先时用llen获得这个list的长度

127.0.0.1:65432> llen list_programmer
(integer) 7



然后使用lrange查看list中的内容

127.0.0.1:65432> lrange list_programmer 0 6
1) "R"
2) "javascript"
3) "shell"
4) "ruby"
5) "lua"
6) "python"
7) "perl"


c.对set类型的


可以先使用scard获得这个集合set的元素member个数

127.0.0.1:65432> scard set_fruits
(integer) 6


然后使用srandmember获得集合set任意个数的member

127.0.0.1:65432> srandmember set_fruits 6
1) "pear"
2) "apple"
3) "orange"
4) "strawbrew"
5) "pipeapple"
6) "banana"


d.对sorted_set类型的

可以先使用zcard获得这个集合set的元素member个数

127.0.0.1:65432> zcard sorted_set_attacktype
(integer) 6


然后使用zrange获得集合set任意个数的member及对应的score

127.0.0.1:65432> zrange sorted_set_attacktype 0 5 withscores
1) "xss"
2) "5"
3) "file_include"
4) "6"
5) "file_upload"
6) "7"
7) "sqli"
8) "8"
9) "command_exexute"
10) "9"
11) "webshell"
12) "10"


e.对hash类型的


可以先使用hkeys获得hash中所有的field

127.0.0.1:65432> hkeys hash_resume
1) "name"
2) "city"
3) "gender"


然后使用hget获得hash中指定field对应的value

127.0.0.1:65432> hget hash_resume name
"tanjiti"



第四步:将/home/lidanqing01/redis/redis.rdb数据库下载到本地,使用rdbtools工具读取(在六、redis编程接口及管理工具中rdbtools的介绍)


六、redis编程接口及管理工具

1. 客户端编程接口

除了redis 自带的redis-cli 客户端,还提供了以下类型的

(1)PHP客户端


Predis https://github.com/nrk/predis 使用PHP代码实现的原生客户端

PhpRedis https://github.com/nicolasff/phpredis 使用C语言编写的PHP扩展


(2)ruby客户端

redis-rb https://github.com/redis/redis-rb



(3)python客户端

redis-py https://github.com/andymccurdy/redis-py


(4)node.js客户端

node-redis https://github.com/mranney/node_redis



2.管理工具

(1) phpRedisAdmin https://github.com/ErikDubbelboer/phpRedisAdmin 

听名字也知道是干啥的了,超级喜欢phpMyAdmin


1)安装

cd /var/www/ web根目录

git clone https://github.com/ErikDubbelboer/phpRedisAdmin.git

cd phpRedisAdmin/


2)配置

cd includes/

cp config.sample.inc.php config.inc.php

vim config.inc.php 替换相应的配置选项

$config = array(
  'servers' => array(
    array(
      'name' => 'local server', // Optional name.
      'host' => '127.0.0.1',
      'port' => 65432, 
      'filter' => '*',

      // Optional Redis authentication.
      'auth' => 'xxxxx' // Warning: The password is sent in plain-text to the Redis server. 渗透者注意拉
    ),


3)访问

https://www.tanjiti.com/phpRedisAdmin/

 

是不是很像简陋版本的phpMyAdmin呀


(2)rdbtools https://github.com/sripathikrishnan/redis-rdb-tools

 

如果redis采取RDB的持久化方式(由内存存储到硬盘文件系统),则会在文件系统中存储为*rdb, 文件存放位置见见redis配置

工作目录

dir /home/lidanqing01/redis


数据库存放路径

dbfilename redis.sites.rdb


那我们可以使用rdbtools来读取放置在 /home/lidanqing01/redis/redis.rdb 下的redis.rdb 数据库


1)安装rdbtools

git clone https://github.com/sripathikrishnan/redis-rdb-tools.git

cd redis-rdb-tools/

sudo python setup.py install


2)使用rdbtools将数据库的内容导出来

可以指定多种格式,如下所示

rdb --command json /root/redis/redis.rdb > output.json

more output.json
[{
"set_fruits":["apple","orange","strawbrew","pear","pipeapple","banana"],
"string_name":"xiaoge,tianzheng",
"list_programmer":["R","javascript","shell","ruby","lua","python","perl"],
"hash_resume":{"name":"tanjiti","city":"shanghai","gender":"female"},
"sorted_set_attacktype":{"xss":5,"file_include":6,"file_upload":7,"sqli":8,"command_exexute":9,"webshell":10}}]


rdb --command diff /root/redis/dump.rdb > output.diff

more output.diff
db=0 "set_fruits" { "apple" }
db=0 "set_fruits" { "orange" }
db=0 "set_fruits" { "strawbrew" }
db=0 "set_fruits" { "pear" }
db=0 "set_fruits" { "pipeapple" }
db=0 "set_fruits" { "banana" }
db=0 "string_name" -> "xiaoge,tianzheng"
db=0 "list_programmer"[0] -> "R"
db=0 "list_programmer"[1] -> "javascript"
db=0 "list_programmer"[2] -> "shell"
db=0 "list_programmer"[3] -> "ruby"
db=0 "list_programmer"[4] -> "lua"
db=0 "list_programmer"[5] -> "python"
db=0 "list_programmer"[6] -> "perl"
db=0 "hash_resume" . "name" -> "tanjiti"
db=0 "hash_resume" . "city" -> "shanghai"
db=0 "hash_resume" . "gender" -> "female"
db=0 "sorted_set_attacktype"[0] -> {"xss", score=5}
db=0 "sorted_set_attacktype"[1] -> {"file_include", score=6}
db=0 "sorted_set_attacktype"[2] -> {"file_upload", score=7}
db=0 "sorted_set_attacktype"[3] -> {"sqli", score=8}
db=0 "sorted_set_attacktype"[4] -> {"command_exexute", score=9}
db=0 "sorted_set_attacktype"[5] -> {"webshell", score=10}


好了,就介绍到这了,是非常基础的皮毛,其实redis现在有很多应用场景,例如根据redis的list 特性,做队列rq服务器 https://python-rq.org/,值得好好看看。

来源:碳基体

评论