题目地址: http://123.206.87.240:9009/5.php
整理一下代码如下:
if (isset ($_GET['password'])) {
if (ereg ("^[a-zA-Z0-9]+$", $_GET['password']) === FALSE)
{
echo '<p>You password must be alphanumeric</p>';
}
else if (strlen($_GET['password']) < 8 && $_GET['password'] > 9999999)
{
if (strpos ($_GET['password'], '*-*') !== FALSE)
{
die('Flag: ' . $flag);
}
else
{
echo('<p>*-* have not been found</p>');
}
}
else
{
echo '<p>Invalid password</p>';
}
}
由代码可得知有以下三个重要条件:
(1) ereg ("^[a-zA-Z0-9]+$", $_GET['password']) === FALSE
(2) strlen($_GET['password']) < 8 && $_GET['password'] > 9999999
(3) strpos ($_GET['password'], '-') !== FALSE
分析代码得知,要使条件(1)不满足,条件(2)(3)满足,才会 die('Flag: ' . $flag);
从而得到flag。
条件(1):
涉及到正则表达式的知识:这里的^[a-zA-Z0-9]+$
表示匹配由一个或者多个 数字、大小写字母 组成的字符串。
ereg()函数:字符串对比解析,区分大小写。
这整句代码意思是说:限制了password格式,只能是一个或者多个数字、大小写字母。
条件(2):
strlen函数返回字符串 的长度。
此句代码意思是:判断是不是长度< 8且大小 >9999999
条件(3):
strpos() 函数:查找字符串在另一字符串中 第一次出现的位置,对大小写敏感
此句代码意思是:判断是不是有“ - ”
方法1:利用数组绕过这两个函数
ereg() 只能处理字符串,遇到数组会返回null,null !== false,也就是说满足了 让条件(1)不成立。
strpos() 的参数同样不能够是数组,遇到数组也会返回null,null !== false,即条件(3)成立
strlen() 遇到数组时也返回null,而null长度小于8,返回True,而另外一个判断条件是否大于 9999999,它这里是整数类型,数组类型要大于整数,所以也返回TRUE。即条件(2)成立。。
故 Payload:http://123.206.87.240:9009/5.php?password[]=1
方法2:%00截断绕过正则匹配
条件(2)(3)成立即: password 长度必须 <8 且 大小>9999999,并且包含 有“-”
条件(1)不成立,即:password 只能是一个或者多个数字、大小写字母
%00截断:ereg函数 读到 %00 的时候,就截止了。
第(2)个条件:长度小于8大小大于99999999,可以用科学计数法来绕过,构造10的7次方 10000000>9999999
构造 ?password=1e7%00- 显示:
最终答案为:?password=1e7%00*-*
Flag: flag{bugku-dm-sj-a12JH8}