ctfshow(91,96,97)--PHP特性
Web91
源代码:
show_source(__FILE__);
include('flag.php');
$a=$_GET['cmd'];
if(preg_match('/^php$/im', $a)){if(preg_match('/^php$/i', $a)){echo 'hacker';}else{echo $flag;}
}
else{echo 'nonononono';
}Notice: Undefined index: cmd in /var/www/html/index.php on line 15
nonononono
审计
GET传参cmd,保存到变量a.
preg_match()函数查询变量a中的php字符串。
preg_match(str $pattern,str $var)
第一个参数是字符串类型的搜索模式。
第二个参数是输入的字符串。
该函数的作用就是匹配输入的字符串中的目标字符,且只匹配一次,匹配成功一次后将不再向后继续匹配。
如果成功匹配,则返回1;匹配失败,则返回0.
分析本题中的函数:
preg_match('/^php$/im', $a)
^php$
表示匹配以php开头且以php结尾的字符串,其实就是匹配字符串php。
后面的i和m是模式修饰符,i表示匹配不区分大小写,m表示将含有换行符字符串视为多行,每行分别匹配。
思路
payload如下:
?cmd=p%0aphp //%0a是ASCII编码的换行符
第一个匹配函数preg_match('/^php$/im', $a)
,是多行模式匹配,第一行的p没有成功匹配,就会去第二行匹配,在第二行成功匹配到php,返回值为1.
第二个匹配函数preg_match('/^php$/i', $a)
,不是多行匹配,在第一行没有匹配到php,返回值0.
因此我们成功执行到 echo $flag;
,得到flag.
Web96
源代码:
highlight_file(__FILE__);if(isset($_GET['u'])){if($_GET['u']=='flag.php'){die("no no no");}else{highlight_file($_GET['u']);}
}
审计
GET传参u。
条件判断,如果u==‘flag.php’,结束程序执行。如果结果为false,显示u所指向的界面的源代码。
思路
flag显然在flag.php文件中,但是我们不能直接传参?u=flag.php
这里介绍一个网页目录的知识点:
假如网页根目录下有flag.php文件,查找文件使用 /flag.php 这里的 / 就是指根目录
同理, ./代表的是当前目录, …/ 代表的是上一级目录
这里的flag.php是在当前目录下,所以可以令:
?u=./flag.php
得到flag.
还有如下解法:
?u=/var/www/html/flag.php //使用了flag.php的绝对路径查询。一般情况下我们访问的网页目录都是/var/www/html目录
?u=php://filter/read=convert.base64-encode/resource=flag.php //使用php伪协议读取
Web97
源代码:
include("flag.php");
highlight_file(__FILE__);
if (isset($_POST['a']) and isset($_POST['b'])) {if ($_POST['a'] != $_POST['b']){if (md5($_POST['a']) === md5($_POST['b']))echo $flag;}else{print 'Wrong.';}
}
审计
POST 传参a,b
第一处条件判断:a != b
,返回值为true进入下一步。
第二次条件判断:md5($_POST['a']) === md5($_POST['b'])
,返回值为true,得到flag。
MD5是一种加密方式
由于MD5不能加密数组,如果输入数组,将会返回NULL
所以我们可以POST a,b为数组:
a[]=1&b[]=2
这样a!=b,但是在md5加密后的结果都为null,成功得到flag。