这题是很简单的,那我们先看源码,首先变量auth=100,然后是一个extract函数,里面的传参是$_GET
,那么做过变量覆盖靶场的同学应该不陌生,这个函数可以把数组中键和值生成相应的变量,可以用来做变量覆盖。
那可以看到输出flag的条件是需要auth变量值为1000,此时我们就可以传参?auth=1000
,便可以成功拿到flag了
payload:?auth=1000
源码中不难看出,解题的关键点还是extract函数,我们能通过该函数覆盖的变量有,ac和fn,但我们需要让ac全等于变量f,f的来源是由file_get_contents
函数读取的文件内容,去掉空格,而该文件就是我们传入的fn变量。
然后看我们最后一行的提示,目录下有一个txt文件,那么猜测可能是flag.txt,为了验证猜测,我们去访问一下。
访问成功,内容为flags,所以我们可以让fn变量等于flag.txt
,这样最终变量f的值就会等于flags
,那很显然,ac变量也就应该等于flags,这样我们就可以拿到flag了
payload:?ac=flags&fn=flag.txt
需要满足什么:num通过is_numeric的检测,并且不等于36,去空后依然不等于36,经过过滤方法后依然等于36
我们可以用跑一下
得到:%0C %2B(+) - . 0 1 2 3 4 5 6 7 8 9
<?php
for($i = 0; $i<129; $i++){
$num=chr($i).'36';
if(trim($num)!=='36' && is_numeric($num) && $num!=='36'){
echo urlencode(chr($i))."\n";
}
}
?>
payload:?num=%0C36
该题有两种解法
php特性:
preg_match不识别数组,否则返回false,匹配一次返回1,没有返回0
if(0===flase)返回值为false,0不是强等于false的
stripos函数对数组不识别,遇到数组会返回false
方法一
payload:?f=zkaqzkaq[]
方法二:
采用数组绕过的方法,stripos函数会返回null,null!=false,所以可以绕过stripos函数
payload:?f[]=666
首先可以看到,第一层if,需要我们给变量number赋值
然后第二层if,要求number不等于123
最后第三层if,要求经过intval()函数处理的number,等于123,否则给你错误的flag
所以重点就是intval() 函数,通过查阅资料可以得知,这是一个把变量转为整型的函数
成功了返回转换以后的数,失败了返回0,这样我们可以给number赋值 123(随便加点字符),然后经过intval处理以后就会返回123,成功拿到正确的flag
payload: ?num=123xxxxxx
我们看本题的代码,首先我们需要给num变量赋值
然后看is_numeric()函数,该函数用来判断传入的变量是否为数字
是数字的话返回TRUE,不是数字返回FALSE
也就是说如果我们传入的是数字,就会直接die掉,并且告诉我们不允许数字
然后else if中,又要求我们的num变量大于1024
也就是说num变量既不能是数字,又要大于1024,我们才能拿到flag
这时候我们就需要了解PHP的特性了
当一个数字与一个字符串/字符进行大小比较时,首先系统尝试将此字符串/字符转换为整型/浮点型,然后进行比较,如’12bsd’转型为12,’a’转型为0,注意是数字和字符串/字符比较
那我们这里就可以给num变量赋值,12345abc,当num与1024比较时,系统首先将12345abc强转成数字12345,然后再与1024比较
这样我们就成功拿到了flag
payload: ?num=12345abc
这题的代码也很好理解,首先strlen函数用来判断变量的长度,也就是num变量的长度必须小于3,
然后是strcmp函数,该函数用来比较两个变量
strcmp(string1,string2)该函数返回:
0 - 如果两个字符串相等
<0 - 如果 string1 小于 string2
>0 - 如果 string1 大于 string2
其实很简单,这两个函数也是不能处理数组的,我们随便给num传个数组,strlen函数处理以后报错,返回FALSE,与数字比较会被认为是0
0肯定是小于3的,然后strcmp函数处理数组也报错,返回FALSE,与0比较也是相等的,这样就可以成功拿到flag
payload:?number[]=0
这题我们需要满足的条件是,num变量的长度小于等于4,并且num+1转成整型以后大于500000
这里我们可以用到科学计数法,5e5 表示 5乘以10的5次方,也就是500000,加1以后就是500001
自然是比500000大了,并且满足长度小于等于4,这里我们只要输入的数据大于等于5e5就可以了
payload: num=5e5
这题是很简单的题目了,只需要让序列化以后的fun与传入的un变量相等即可
可以复制代码以后在本地执行,输出ser变量,得到的就是我们需要的字符串
payload: ?un=O:3:"Fun":3:{s:4:"name";s:5:"vFREE";s:3:"age";s:2:"19";s:4:"look";s:8:"handsome";}
访问发现他让我们先登录,我们尝试传参username=admin&password=admin
结果提示用户名密码不能一样,好嘛那就不一样username=admin&password=root
结果提示无效的密码,这可犯了难,看看F12。
很好,有发现,使用sha1函数处理以后的用户名和密码只要相等,就会得到flag
但我们又不能让用户名和密码相同。
其实sha1函数,也是不能处理数组的,当我们传入的是一个数组,那么就会返回FALSE,所以这里我们可以用户名和密码都传数组
这样就是FALSE===FALSE,自然就是TRUE了
payload: username[]=admin&password[]=root
首先要满足a是一个数字,然后要满足a的长度小于7,最后要满足$a*$a也就是变量a的平方等于0
此题可以用到科学计数法
php有一个特性是,小数点后超过161位做平方运算时会被截断,我们可以用科学计数法来代替,即1e-162
payload: a=1e-162
一道很简单的题目。
首先我们要搞清楚strpos函数的作用
strpos() 函数查找字符串在另一字符串中第一次出现的位置。
然后往下看发现,我们需要让res变量等于1,也就是让strpos函数返回1
这里需要注意,大部分语言,下标都是从0开始的,也就是说,如果我们要让strpos返回1
那我们就要让strpos需要查找的字符串出现在第二个位置上
payload: ?str=1zkaq
首先看代码,可以看到,如果没给变量num赋值,或者变量num的长度为0,就会直接die掉
那么肯定是得给num传点东西的,然后继续往下走,变量b等于json_decode($num),然后$y = $b === NULL,最后是 变量y全等于TRUE,才能拿到flag
也就是说,我们要让 $b === NULL 返回TRUE,这样 $y 才会等于TRUE,所以我们要让json_decode函数返回NULL,但我们并不能不给num变量赋值
所以我们就要另辟蹊径了,这里有几种方法, num=NULL 或者 num=%20(get传参才行)或者 num= (一个空格,可以burp抓包改)
payload: num=NULL || num=%20 || num= (空格)
考察点:php伪协议绕过is_file+highlight_file对于php伪协议的使用
函数介绍:
is_file — 判断给定文件名是否为一个正常的文件
is_file ( string $filename ) : bool
我们的目的是不能让is_file检测出是文件,并且 highlight_file可以识别为文件。这时候可以利用php伪协议。
可以直接用不带任何过滤器的filter伪协议
file=php://filter/resource=flag.php
也可以用一些没有过滤掉的编码方式和转换方式
file=php://filter/read=convert.quoted-printable-encode/resource=flag.php
file=compress.zlib://flag.php
还有一些其他的,可以参考:https://www.php.net/manual/zh/mbstring.supported-encodings.php
payload:?file=php://filter/resource=flag.php
首先看源码,变量num等于get传参的num
第一层if需要我们给num变量赋值,第二层if需要变量num不等于0
第三层if,是变量num经过md5编码的以后,等于FALSE
前面两个好说,主要就是md5编码以后等于FALSE,通过查阅资料可以发现
md5函数如果是对数组进行编码,便会报错,此时它会返回FALSE
那么答案就很明显了。
payload: ?num[]=1
本题的考点是数组key溢出
通过PHP创建关联数组的时候,键值Key如果是数值型(可通过is_numeric()判断)
则会在int有效范围内被自动转换为int型,如果超过int有效范围就会有问题,这就涉及到数组键值Key作为int型时的有效范围判断。
PHP的int型数据取值范围,与操作系统相关,32位系统上为2的31次方,即-2147483648到2147483647,64位系统上为2的63次方,即-9223372036854775808到9223372036854775807。
一般来说,我们往数组里插入一个值是可以正常插入的,当我们的数组下标key足够大的时候,9223372036854775807,这个时候想要再往里面插入元素,就会报错
而这一点正是这道题最内层if语句的考点
这时候往里a传参9223372036854775806,要比上面提到的那个数字小1
因为题目是++$a,先加上1,变成9223372036854775807,然后执行最内层的if时,因为没有地方可以开数组了,就返回NULL,即false,这样一来就可以执行else里的语句
payload: a=9223372036854775806
(php 7.3+)
有关file_get_contents()函数的一个trick,可以看作是SSRF的一个黑魔法
当PHP的 file_get_contents() 函数在遇到不认识的伪协议头时候会将伪协议头当做文件夹
造成目录穿越漏洞,这时候只需不断往上跳转目录即可读到根目录的文件。
此处限制我们只能读http开头的路径,但利用这个特性我们可以构造:
?a=httpsss://../../../../../flag
或 httpsssss://abc../../../../../../flag
访问发现只有一个时间,F12查看源码发现,GET: ?source= ,尝试get传参source,出现源码
不包含source就可执行反序列化,试一下文件读取
先访问一下flag.php,发现文件存在,那我们读取一下flag.php
<?php
class HelloPhp
{
public $a;
public $b;
public function __construct(){
$this->a = 'flag.php';
$this->b = "highlight_file";
}
}
$abc=new HelloPhp;
echo serialize($abc);
读取成功!
payload: ?data=O:8:"HelloPhp":2:{s:1:"a";s:8:"flag.php";s:1:"b";s:14:"highlight_file";}
在php中,所有变量都是若类型的,在使用if判等的时候要格外小心,使用特殊的参数可能会使本来不相等的if判断位相等
上面只要传入参数a=s1885207154a,b=s1836677006a,即可,为什么呢?看一下这两个字符串的md5值可以返现分别如下:
MD5值:
md5(“s1885207154a”) => 0e509367213418206700842008763514
md5(“s1836677006a”) => 0e481036490867661113260034900752
二者都是0e开头,在php中0e会被当做科学计数法,就算后面有字母,其结果也是0,所以上面的if判断结果使true,成功绕过!
payload: ?a=s1885207154a&b=s1836677006a
首先看题,首先是第一层if,要求get传参的a和get传参的b不相等
然后第二层if是,md5加密后的传参a和b,全等。
那么第一层if肯定是简单的,随便传两个不一样的数据就行,主要就是第二层
前面的题目中也有类似的,md5函数在传入数组以后,会报错,此时返回的就是FALSE,所以我们可以a和b都传数组
这样FALSE===FALSE,那么自然就是TRUE了,所以我们传两个值不相等的数组就可以了。
payload: ?a[]=&b[]=1
打赏我,让我更有动力~
© 2016 - 2024 掌控者 All Rights Reserved.
十二梦
发表于 2021-11-22
这个哪里的ctf呀
评论列表
加载数据中...