Life has its own fate, and meeting may not be accidental.

0%

正则限制加科学计数法绕过

比赛遇到一题源码泄露的题,思路没拓展开+经验不足,希望以后能发散性思维,吸取教训!

大门就是gedit备份泄露

gedit写代码时,目录下有后面带”~”的备份文件

![来自RoarNya](1.png %}

第一关

username必须要等于1024并且要小于1024,因为是==,所以可以用四舍五入绕过

php中四舍五入精度要求很高,我这边用了14个9

第二关

1
2
3
if(0>= preg_match('/^[[:graph:]]{12,}$/', $password)

意思是匹配到除空格符(空格键与[TAB]键)之外的所有按键,大于等于12

第三关

进去while
[[:punct:]] 任何标点符号
[:digit:] 任何数字
[[:upper:]] 任何大写字母
[[:lower:]] 任何小写字母

1
2
3
4
5
$reg = '/([[:punct:]]+|[[:digit:]]+|[[:upper:]]+|[[:lower:]]+)/';
if(6 > preg_match($reg, $password,$arr)){
break;
}
匹配到的不同字符不能大于6

第四关

[[:punct:]] 任何标点符号
[:digit:] 任何数字
[[:upper:]] 任何大写字母
[[:lower:]] 任何小写字母

以上四种匹配要大于三次,否则break

并且password 的值==2048

1
2
3
4
5
6
7
8
9
10
11
12
13
$c =0;
$ps = array('punct','digit','upper','lower');
foreach ($ps as $pt){
if(preg_match("/[[:$pt:]]+/",$password)) {
$c += 1;
}
}
echo "\n".$c;
if($c<3){
echo "小于三个";
}
if("2048" == $password)
echo "\n".$flag;

用科学计数法来绕,e代表10,+后面的数字代表几位

所以最后的payload

1
2
username=1023.99999999999999999
password=2048.00e+0000

我的模拟代码= =

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
$flag="flag{nice}";
$username="chenzidu";
$password="2048.00e+0000";
if(0>= preg_match('/^[[:graph:]]{12,}$/', $password))
echo "yes"."\n";

$reg = '/([[:punct:]]+|[[:digit:]]+|[[:upper:]]+|[[:lower:]]+)/';
echo preg_match($reg, $password,$arr);

$c =0;
$ps = array('punct','digit','upper','lower');
foreach ($ps as $pt){
if(preg_match("/[[:$pt:]]+/",$password)) {
$c += 1;
}
}
echo "\n".$c;
if($c<3){
echo "小于三个";
}
if("2048" == $password)
echo "\n".$flag;