目录
一、信息搜集
打开题目链接后只有一个滑稽??(那就看看它里面有啥吧)
想啥呢,是审查源码啦
可以看到有注释source.php,访问后可以看到其源码
又发现一个hint.php文件,先访问再说
提示我们flag在ffffllllaaaagggg里面,此时题目已经完成一半啦
二、分析
接着看回source.php源码
可以看到最后的include 是可以动态构造参数的,那应该就是解题关键了
不过要经过三个判断
第一个:检查一个变量是否为空
第二个:是否为字符串
第三个:通过函数checkFile来检查
我们要构造的payload本身就满足前两点所以无视
重要是第三点的这个函数
函数作用是分三步检查传进来的参数是否满足白名单:
$whitelist = ["source"=>"source.php","hint"=>"hint.php"];
第一步:
只要我们传的参数是source.php或者hint.php则返回真(因为这一步写死了参数只能为白名单的值,所以无法利用)
如果不满足继续往下判断
第二步:
仔细看mb_strpos的第一个参数是:$page.'?',这结果就是在参数后面拼接一个'?'
接着第二个参数'?',就是要查找第一个参数字符串中首次出现'?'的下标,如下图
获得下标就是为了利用mb_substr提取page参数中第一个?前面的字符串
思考:如果我们在mb_strpos函数执行前就对参数page添加'?'会怎么样呢
最后将得到新的值进行白名单判断
如果还不满足继续往下判断
第三步:
先把传进的参数做urldecode
接着就和第二步一样
都不满足就输出"you can't see it"并且返回假
总结:我们需要得到checkFile函数返回true且需要带上
三、构造payload
要想满足这些条件那我们传的参数就只能是这种形式
($_REQUEST 是通过 GET,POST 和 COOKIE 输入机制来传递参数,下面偷懒就用get方式传值)
1、通过第二步来构造payload
payload_1:source.php?file=source.php?(文件包含路径)
payload_2:source.php?file=hint.php?(文件包含路径)
解析:自己悟
通过前面的分析结合下图应该不难理解,你是最棒的(ง •_•)ง
2、通过第三步来构造payload
如果闲着无聊也可以满足第三种,就是双重url编码,传过去的时候会自动解码一次,再加上函数的一次就会满足条件
http://111.198.29.45:48818/source.php?file=source.php%253f(%253f就是?的两次url编码)
http://111.198.29.45:48818/source.php?file=hint.php%253f
符合条件后include得到得值就变成:
include source.php?(payload)
因为source.php?(或hint.php?)是固定不能改的,那么我们能利用的漏洞只有本地文件包含了
(本人技术比较菜也只能想出这种了,如果还有别的方法还望大佬们赐教)
四、获取Flag
flag文件名也知道了就差路径不知道,一个一个试可以得到
source.php(或hint.php)?/../../../../../../ffffllllaaaagggg
ok!flag get√
五、为啥能执行成功
可能会有疑问为啥include source.php(或hint.php)?/../../../../../../ffffllllaaaagggg能执行成功
看官方对include的定义
重点在于这两句话:
被包含文件先按参数给出的路径寻找,如果没有给出目录(只有文件名)时则按照include_path 指定的目录寻找。
如果定义了路径——不管是绝对路径(在 Windows 下以盘符或者
\
开头,在 Unix/Linux 下以/
开头)还是当前目录的相对路径(以.
或者..
开头)——include_path 都会被完全忽略
include_path,简单理解就是类似系统中的PATH环境变量,在文件包含在没有指出路径就会在前面补充这个include_path,从而形成完整的绝对路径
比如:include_path设置为/var/www/,在执行include "flag.txt",路径就是/var/www/flag.txt
由于我们构造的payload:”source.php?/../../../../../../ffffllllaaaagggg“包含路径
所以会忽略include_path直接按照我们路径去寻找。没错虽然这个payload很奇怪但对于include来说就是一个路径,由于不是/开头,所以还是个相对路径,过程如下
假设source.php所在目录为:/1/2/3/4/5/var/www/html/source.php
1、"source.php(或hint.php)?/":进入这个目录,是的哪怕这个目录不存在,因为include会一直尝试到最后才会报错。这样我们当前路径为:"/1/var/www/html/source.php?/"
可能这个时候又有聪明的小伙伴疑问:啊?这个"?"不会当成参数吗?
我们可以看到官方对include定义的这句话:
进到include_path定义后就会发现:string
所以你加
tm一百个问号都是string当成路径解析
2、"../":返回上一级,当前目录为"/1/var/www/html/",回到了php所在路径
3、"../":同理,当前路径为"/1/var/www/"
4、"../":同理,当前路径为"/1/var/"
5、"../":同理,当前路径为"/1/"
6、"../":同理,当前路径为"/",回到根目录,最后找到ffffllllaaaagggg这个文件
可以配合我复现的环境来理解:
环境版本:php5.6.36+Apache2.4.55
可以看到我的source.php是和1.txt同目录/var/www/html/下,而且没有1这个文件夹
路径:1/../1/../1.txt
根据前面的分析,include解析步骤就是
1、/var/www/html/1
2、/var/www/html
3、/var/www/html/1
4、/var/www/html
最后找到1.txt
再来一个环境版本:php8.3.0beta1+Apache2.4.55
路径:1/../zhe shi php830/../1.txt
根据前面的分析,include解析步骤就是
1、/var/www/html/1
2、/var/www/html
3、/var/www/html/zhe shi php830
4、/var/www/html
最后找到1.txt
当理解了这个之后,你就能有更骚的路径:
payload:source.php?要不是为了过白名单谁想这样开头/../../../真无语啊这题/../../让我测了这么多环境/../下头!/../不过CTF Fun!/../../ffffllllaaaagggg
-----------------------------------------------------------------我是分割线--------------------------------------------------------------
看完了觉得不错就点个赞或者评论下吧,感谢!!!
如果本文哪里有误随时可以提出了,收到会尽快更正的