前言:
目标是ak靶场,然后换书。同时也是加深我对于web题目的熟练度和见识。
简单
简单难度基本都是秒杀,很多都比较基础且没意思,题目后面跟#的是比较有意义的题。
swp#
描述:无
考点:swp文件泄露、strpos()、PCRE回溯次数限制绕过正则
dirsearch直接扫出swp文件
访问得到源码
审计一下源码,先是判断输入的内容是否为数组,然后用strpos()
判断输入的内容是否包含sys nb
。但是单单输入sys nb
还不够。上面还有一个正则匹配sys
开头,后面跟任意字符 .*
,然后以nb
结尾。原本我以为空格也算一个字符直接输入sys nb
就能得到flag了,但是发现没绕过去。
这里就需要用到PCRE回溯次数限制来绕过正则
PCRE回溯次数限制:通过发送超长字符串的方式让回溯次数超过最大限制就可以使
preg_match()
函数返回false
,从而绕过限制,使正则执行失败。中文的回溯次数在100万次就会崩溃
1 | import requests |
运行后得到flag
简单rce#
描述:无
考点:rce绕过
就是个命令执行绕过,system
用passthru
替代,cat用\
绕过,空格用%09
。
蜜雪冰城吉警店
描述:无
考点:js修改
本来看源代码我还以为是js反混淆,后面发现没法解出来。
尝试在查看器改了一下id为9。
改完再点击一下相应的按钮就得到flag
召唤神龙
描述:无
考点:js源码泄露、JSFuck解码
好玩爱玩,玩归玩闹归闹,还是来正经做题。
dirsearch扫描发现一个main.js
查看发现一段可疑的JSFuck码
解码得到flag
seek flag
描述:无
考点:信息搜集
dirsearch扫描发现robots.txt
访问得到第三部分flag
本来看源码的提示被误导了,真的写了个脚本爬了1000行数据以为有隐藏的。后面发现cookie处的id=0
,尝试改成id=1
就出来了。
本来是想抓包爆破一下cookie里的id的无意中发现flag2(逆天题)
将三段拼在一起得到完整flag
jwt#
描述:无
考点:jwt伪造
进入是一个登录界面,去注册admin用户,发现已存在。再结合题目jwt可以大概猜出这题要伪造admin用户登录。
先尝试一下爆破admin的密码但是没爆出来(爆出来估计就非预期了)
既然爆不出密码,那就先顺便注册一个用户登录
先查看一下JWT的header和payload
利用jwt-cracker爆破JWT的secret
1 | jwt-cracker -t eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6IlRHMXUifQ.E6_aosK_r4woX4_yxoxoSjA7L-vvwjqPSmRxAaNnjEo |
得到secret为SYSA
伪造jwt
1 | eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIn0.9avq5ApZ-XZul2kbon8z2cB6Y4bNru_0nnIZfJ1mO50 |
将其填回到cookie中,进入admin的个人中心得到flag
login
描述:无
考点:bp爆破
进入后根据源码的提示登录成功,但是没发现什么东西
尝试更换一下学号(一般就改最后几位就行),发现得到一个f
那么接下来就是爆破一下后面两位就行
使用Pitchfork模式
先爆破0到10,前缀加上零
再爆破10到99
最后得到flag
1 | flag{dlcg} |
iphone
描述:无
考点:ua伪造
根据源码提示直接伪造ua为手机或者ipad的就行
1 | Mozilla/5.0 (iPhone; CPU iPhone OS 14_7_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Mobile/15E148 Safari/604.1 |
浮生日记#
描述:无
考点:xss构造闭合+script双写绕过
根据源码提示发现需要弹窗
但是用弹窗发现没法弹,script没了
尝试把value给闭合了,并且script双写绕过就行了
1 | "><scrscriptipt>alert(123)</scrscriptipt> |
$$
描述:无
考点:全局变量
传入c的值后变为
1 | eval("var_dump($$_GET['c']);"); |
本来想用变量覆盖的,但是发现_
被过滤,并且可以发现传入的地方还有个var_dump
,所以就不想着命令执行了。
尝试用var_dump
打印一下全局变量就出来了
1 | ?c=GLOBALS |
爆破
描述:无
考点:md5构造
分析一下代码,输入的密码要满足以下两个条件就可以得到flag
- 第 2 位、第 15 位和第 18 位字符相同
(intval(第 2 位) + intval(第 15 位) + intval(第 18 位)) / intval(第 2 位) == intval(第 32 位)
那么就很简单了,写个脚本就可以构造了
1 | import hashlib |
传入422得到flag
XFF#
描述:无
考点:XFF
直接伪造XFF就行了
rce1#
描述:无
考点:空格过滤
直接命令执行,用${IFS}
绕过空格
1 | 127.0.0.1|cat${IFS}fllllaaag.php |
发现成功了但是没找到flag,查看一下源码发现flag
GET-POST
描述:无
考点:GET、POST传参
真就最基础的get、post传参
被黑掉的站
描述:无
考点:bp爆破
看他页面提示感觉是有后门,直接用dirsearch扫描发现两个文件
访问shell.php
需要输入密码,访问index.php.bak
应该是密码本
直接bp抓包爆破
签到题#
描述:无
考点:绕过
../
直接disearch扫描
访问data
绕过../读取flag.php
1 | /data/?file=php://filter/convert.base64-encode/resource=..././..././..././flag |
解码得到flag
但是这题我估计非预期了一下,前面data得到其实是要改cookie
解码得到文件路径,后面打法就一样了。
签到
描述:无
考点:POST传参
有个框但是无法提交,F12查看发现POST传参,参数为key
随便传个值发现需要传入ilovejljcxy,传入后直接得到flag了
session文件包含#
描述:无
考点:恶意session文件包含
随便登录个用户,用php伪协议读/etc/passwd
1 | /action.php?file=php://filter/convert.base64-encode/resource=/etc/passwd |
解码
但是发现这个flag是假的(交半天我还以为哪里错了。。。)
看题目是session文件包含,那就应该是要构造恶意的session文件
查看一下action.php
发现可以通过POST传入name的值构造恶意session然后包含session文件从而命令执行
那么就要先找到session文的存储位置
Session文件的存储位置:Session文件默认以文件的形式保存在服务器硬盘上,每个Session一个文件,文件名通常为
sess_[phpsessid]
命令执行查看一下环境变量,发现一个flag结果又是假的(不是一天天的这么喜欢fakeflag)
直接ls /
查看,然后抓flag
Don’t touch me
描述:无
考点:无
一直查看源码根据提示访问2.php
再访问3.php
再访问fla.php
就得到了。。。
robots
描述:无
考点:robots.txt
甚至不用dirsearch扫就知道访问robots.txt
了。。。
访问fl0g.php
得到flag
php very nice#
描述:无
考点:php反序列化
看到unserialize就知道要打反序列化了
1 |
|
1 | ?a=O:7:"Example":1:{s:3:"sys";s:23:"system('tac flag.php');";} |
ezupload#
描述:无
考点:文件上传MIME类型绕过
随便传个php文件用bp抓包发现只能传gif文件,修改一下MIME直接就绕过了
本来想偷点懒直接打结果发现找不到flag,老老实实连蚁剑了
在/var/www/flag.php
找到flag
cookie欺骗
描述:无
考点:cookie伪造
进入就发现给了提示只有admin用户可以得到flag
直接bp抓包修改uer为admin就得到flag了
upload#
描述:无
考点:文件上传后缀双写绕过
查看源代码有提示,访问?action=show_code得到源码
可以看到黑名单限制了一堆后缀,并且移除上传文件的黑名单中的后缀,然后移动到目标路径生成随机前缀。
用bp抓包,直接双写绕过
得到上传文件的路径和名称后,直接打但是还是找不到。再次老实连蚁剑
在/var/www/flag.php
找到flag
干正则#
描述:无
考点:parse_str()变量覆盖、rce
可以利用parse_str()
打变量覆盖,然后用|
分隔开。
1 | ?id=a[0]=www.polarctf.com&cmd=| tac f* |
cool#
描述:无
考点:system替代函数
system()
用passthru()
替代
1 | ?a=passthru('tac f*'); |
uploader#
描述:无
考点:无上传点的文件上传
使用客户端 IP 地址的 MD5 哈希值作为沙盒目录名称,并且将文件上传到生成的沙盒目录中。
在自己本地起个文件上传的网站
1 |
|
上传文件
可以发现已经给出目录了,直接打flag
覆盖
描述:无
考点:parse_str()变量覆盖、rce
跟上面干正则一模一样。。。
PHP反序列化初试#
描述:无
考点:php反序列化、
__toString()
这里需要触发__toString()
,也就是需要把对象当成字符串调用
所以直接把new Evil()
赋给name,从而通过echo new Evil()
触发__toString()
,此时就可以调用Evil里的evil并赋值就可以进行命令执行了。
1 | <?php |
1 | ?easy=O:4:"Easy":1:{s:4:"name";O:4:"Evil":2:{s:4:"evil";s:12:"tac [email protected]";s:9:" Evil env";N;}} |
机器人
描述:无
考点:
robots.txt
还是一样直接访问robots.txt
直接得到一半flag
除此之外,还发现一个目录访问显示禁止,直接用dirsearch扫描一下
访问得到另一半flag
扫扫看
描述:无
考点:泄露
dirsearch直接扫到flag了
访问在源代码得到flag
debudao
描述:无
考点:xss
xss弹cookie直接出
1 | <script>alert(document.cookie)</script> |
审计#
描述:无
考点:md5碰撞
md5要0e开头,并且输入又只能是数字,那就直接md5碰撞就得到flag了
1 | ?xxs=240610708 |
upload1
描述:无
考点:文件上传
查看源代码得到上传逻辑
随便上传个文件bp抓包,发现上传.php
的话抓不到,就改为.jpg
上传
上传后直接改后缀为.php
就行
直接打flag
rapyiquan#
描述:无
考点:
[
替代_
、命令执行\
绕过
可以看到_
被过滤了,用[
替代。下面命令执行禁了一堆但是\
没禁直接用`绕过得到`flag
1 | ?c[md=ta\c /fl\ag.php |
bllbl_ser1#
描述:无
考点:php反序列化
页面上看不清楚,直接在源代码里查看
很明显打php反序列化
1 | <?php |
1 | ?blljl=O:5:"bllbl":1:{s:5:"qiang";O:7:"bllnbnl":1:{s:2:"er";s:20:"system('cat /flag');";}} |
查看源代码找到flag
1ncIud3
描述:无
考点:flag替换字母、绕过
../
纯恶心人的题
dirsearch扫描发现flag.php
,其他几个没啥用。
用?page=flag
访问flag.php
提示说需要替换字母f1ag、fl4g、fla9、fl49、f1a9、f1ag、f14g、f149
尝试了好几种发现都不行,尝试用../
进行目录穿越也不行。
再回到flag.php
发现提示说过滤了符号,感觉应该../
被过滤了,用..././
绕过
1 | ?page=..././..././f1a9 |
投喂#
描述:无
考点:php序列化
看题目要求发现需要我们对用户名和is_admin
进行序列化
1 | <?php |
1 | data=O:4:"User":2:{s:8:"username";N;s:8:"is_admin";b:1;} |
狗黑子的RCE#
描述:无
考点:双写绕过
str_replace()
gouheizi会被str_replace()
替换为空,所以用双写绕过。命令执行没禁用\
直接用\
绕过
1 | GET: ?gouheizi1=ta\c /fl\ag.php |
button
描述:无
考点:js泄露
直接查看网站的js脚本,发现可以直接读到flag
访问/proxy.php?file=flag
,在源代码里找到flag
井字棋#
描述:无
考点:POST请求伪造、控制台函数调用
法一:POST请求伪造
查看源代码可以得到获取flag的条件
直接伪造请求得到flag
法二:控制台函数调用
可以看到declareWinner()
通过参数who来控制谁获胜
直接通过控制台调用一下declareWinner()
,给后端传递我们获胜的信息
1 | declareWinner("您赢了!"); |
简单的导航站
描述:无
考点:md5强比较数组绕过、bp爆破
尝试登录管理员但是发现登不进去,注册一个普通用户登录,查看用户列表
直接数组绕过md5强比较得到用户字典
1 | ?user1[]=1&user2[]=2 |
bp抓包爆破管理员用户和密码,但是发现没爆出来。
看了一下wp发现密码在源代码里(纯恶心人)
爆破用户名,得到管理员用户和密码P0la2adm1n/Admin1234!
登录后进入文件上传界面,上传.php
成功但是没找到路径,盲猜是uploads
连接蚁剑
找到一个flag字典(无语)
导航页面有个验证flag的地方,抓包爆破得到正确的flag
中等
中等题基本上都是比较有意义的知识点,并且中等难度有些题理解起来还是有点难度的,这些题在题目后面跟上X。
到底给不给flag呢X
描述:无
考点:
foreach()
+动态变量$$
实现变量覆盖
这题理解起来还是有点麻烦的,得好好分析一下。
进来就给个flag,可惜是假的。。。
分析一下代码重点看这一段
1 | foreach ($_POST as $key => $value) { |
foreach循环会依次处理 $_POST
和$_GET
数组中的每个键值对。很明显是需要我们打变量覆盖,接下来分别分析一下POST和GET
POST和GET传入的值会被重新变为变量
假设POST传入的值为a=flag
,传入后$_POST
数组如下:
1 | $_POST = [ |
则$$key = $value
就变为$a = flag
,所以很明显这里没法通过POST进行变量传递。
假设GET传入的值为a=flag
,传入后$_GET
数组如下:
1 | $_GET = [ |
则$$key = $$value
就变为$a = $$flag
两个问题:
为什么这里不是
$a = $flag
?这就涉及到动态变量
$$
的基本概念:在 PHP 中,$$
是动态变量的语法。它的作用是根据一个变量的值作为另一个变量的名称。这里的
$$key
为什么不是变为$$a
而是$a
?因为这里的a不是通过
$$
变量得到的,而是直接赋值为a,所以就直接是变量$a
此时如果传入a=flag&flag=a
,传入后$_GET
数组如下:
1 | $_GET = [ |
此时会经历两轮循环
第一轮:
1 | $key = 'a' |
此时$flag
的值假flag:flag{f73da0c8e7c774d488a6df0fec2890d9}
已经被覆盖掉了,而真正的flag值被赋给了$a
变量,也就是$a=true flag
。
第二轮:
1 | $key = 'flag' |
此时$flag
的值等于$a
变量的值,也就是$flag=true flag
所以最后echo $flag
就是输出true flag
所以payload为
1 | ?a=flag&flag=a |
查看源代码得到flag
补充:为什么不用传入POST?(刚开始有点误导我)
第一段逻辑:
1
2
3 if(!isset($_GET['flag']) && !isset($_POST['flag'])){
exit($qwq);
}此时需要两边都是
true
才会exit($qwq)
,我们传入了GET,所以isset($_GET['flag'])
为true
而!isset($_GET['flag'])
为false
;我们没有传入POST,所以isset($_POST['flag'])
为false
而!isset($_POST['flag'])
就为true
。所以就传入一个GET就行了。
写shell
描述:无
考点:
file_put_contents()
、php伪协议base64解密绕过exit()
就是用file_put_contents
写入木马
但是可以发现这里由于有个exit();
直接结束了后面代码的执行,所以我们需要绕过exit();
法一:base64解码
直接将代码以base64的形式写入到1.php
中,并且使用php伪协议进行解码。这样就将<?php exit();".
这部分给解密为乱码,从而执行我们后面写入的代码。
但是这里还有一点要注意的是base64解码是将每4个字节转换成3个字节,而
<?php exit();".
有15个字符,所以我们需要随便加上一个字符筹齐16个字符进行base64解码。
1 | GET: ?filename=php://filter/convert.base64-decode/resource=1.php |
法二:strip_tags
去除xml标签代码+base64解码
通过strip_tags
去除xml标签代码,即去除<??>
的部分,所以我们需要在POST的paylaod前加上?>
闭合前面<?php exit();".
,防止后面我们添加的<??>
也被去除标签了。
1 | GET: ?filename=php://filter/string.strip_tags|convert.base64-decode/resource=1.php |
注入
描述:无
考点:xpath常规注入
进入后点击,发现跳转得到一个用户名,并且变为?id=1
但是试了半天sql注入没试出来,爆破了一下id也只是得到了几个用户名
看了一下wp才发现是xpath注入
直接打payload访问xml文档的所有节点就得到flag了
1 | ?id=']|//*|//*[' |
某函数的复仇
描述:无
考点:
create_function()
命令执行
第一个正则验证 shaw是否只包含小写字母和下划线,第二个过滤了一些命令执行的关键字
动态掉用函数,这里shaw直接用create_function()
满足第一个正则条件,并且参数也符合。
create_function()
:用于动态创建匿名函数。语法类似于eval()
,会解析传入的字符串为可执行的 PHP 代码。
用;}
结束了原本的函数体,后面直接命令执行,用/*
开始注释忽略后续的代码。
1 | GET: ?root=;}system('more /f*');/* |