练习记录
复现代码:
index.php
// index.php
<?php
include 'flag.php';
if ("POST" == $_SERVER['REQUEST_METHOD'])
{
$password = $_POST['password'];
if (0 >= preg_match('/^[[:graph:]]{12,}$/', $password))
{
echo 'Wrong Format';
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');
foreach ($ps as $pt)
{
if (preg_match("/[[:$pt:]]+/", $password))
$c += 1;
}
if ($c < 3) break;
if ("42" == $password) echo $flag;
else echo 'Wrong password';
exit;
}
}
highlight_file(__FILE__);
?>
flag.php
// flag.php
<?php $flag = "HRCTF{Pr3g_R3plac3_1s_Int3r3sting}";?>
漏洞分析:
进入网站:
http://10.211.55.5/PHPcode/day6/index.php
发现页面正常,可以进行操作了。
这道题目实际上考察的是大家是否熟悉PHP正则表达式
的字符类,当然还涉及到一些弱类型比较问题。大家可以先查阅一下PHP手册对这些字符类的定义,具体可点 这里 。
题目中总共有三处正则匹配.。
第一处的正则(第6行) /^[[:graph:]]{12,}$/
为:
if (0 >= preg_match('/^[[:graph:]]{12,}$/', $password))
匹配到可打印字符12个以上(包含12)
,^
号表示必须以某类字符开头,$
号表示必须以某类字符结尾。
第二处正则表达式(13-15行):
$reg = '/([[:punct:]]+|[[:digit:]]+|[[:upper:]]+|[[:lower:]]+)/';
if (6 > preg_match_all($reg, $password, $arr))
break;
表示字符串中,把连续的符号
、数字
、大写
、小写
,作为一段,至少分六段
,例如我们输入 H0ng+Ri
则匹配到的子串为H
0
ng
+
R
i
。
第三处的正则表达式(17-23行):
$ps = array('punct', 'digit', 'upper', 'lower');
foreach ($ps as $pt)
{
if (preg_match("/[[:$pt:]]+/", $password))
$c += 1;
}
if ($c < 3) break;
表示为输入的字符串至少含有符号
、数字
、大写
、小写
中的三种类型。然后题目最后将 $password
与42
进行了弱比较。
所以我们的payload
为:
password=42.00e+00000
password=420.00000e-1