signed

QiShunwang

“诚信为本、客户至上”

bugku 数字验证正则绕过

2021/3/21 0:57:56   来源:

bugku 数字验证正则绕过

<?php
error_reporting(0);
$flag = 'flag{test}';
if ("POST" == $_SERVER['REQUEST_METHOD'])
	{
	$password = $_POST['password'];
	if (0 >= preg_match('/^[[:graph:]]{12,}$/', $password)) //preg_match — 执行一个正则表达式匹配
		{
		echo 'flag';
		exit;
		}
	while (TRUE)
		{
		$reg = '/([[:punct:]]+|[[:digit:]]+|[[:upper:]]+|[[:lower:]]+)/';
		if (6 > preg_match_all($reg, $password, $arr))
		break;
		$c = 0;
		$ps = array('punct', 'digit', 'upper', 'lower'); //[[:punct:]] 任何标点符号 [[:digit:]] 任何数字 [[:upper:]] 任何大写字母 [[:lower:]] 任何小写字母
		foreach ($ps as $pt)
			{
			if (preg_match("/[[:$pt:]]+/", $password))
			$c += 1;
			}
		if ($c < 3) 
		break;//>=3,必须包含四种类型三种与三种以上
			if ("42" == $password) echo $flag;
			else echo 'Wrong password';
			exit;
			}
		}
?>
  • POST" == $_SERVER['REQUEST_METHOD']
    是判断提交的数据是否是POST方式传来的.
  • 0 >= preg_match('/^[[:graph:]]{12,}$/', $password)
    输入的内容必须为12个以上,不包括空格和tab键
  • $reg = '/([[:punct:]]+|[[:digit:]]+|[[:upper:]]+|[[:lower:]]+)/';
    [[:punct:]] 任何标点符号, [[:digit:]] 任何数字, [[:upper:]] 任何大写字母 , [[:lower:]] 任何小写字母
  • if (6 > preg_match_all($reg, $password, $arr))
    匹配到的次数要大于6次才能绕过。连续的大写或小写字母都只能算是一次。
$c = 0;
$ps = array('punct', 'digit', 'upper', 'lower'); //[[:punct:]] 任何标点符号 [[:digit:]] 任何数字 [[:upper:]] 任何大写字母 [[:lower:]] 任何小写字母
foreach ($ps as $pt)
{
 if (preg_match("/[[:$pt:]]+/", $password))
 $c += 1;
}
if ($c < 3) 
break;

要满足>=3时才不会break,即必须包含大小写字母,数字,字符内容三种或三种以上。

  • "42" == $password
    最后输入的内容还得和42相等
  • preg_match_all是全局匹配,每匹配成功一次就加1,一直匹配到字符串结束,最后返回匹配成功的次数;
  • if ("42" == $password) echo $flag;
    这里是一个弱类型比较,如果前两位是数字42,后面是字母等其它字符,比较时会强制转化成数字,于是,’42aaAaa2;aaaa’ 完全可以用来绕过

解题思路:

发现在hackbar里面无论password构造成什么样都回显错误,故这道题环境有问题,掌握代码即可

题目正常时解法