【攻防世界】Web系列之lottery

【攻防世界】Web系列之lottery

打开题目环境后,需要先注册账号继续操作

接着就进入如下页面,让你输入7个数字与题目给出的7个数字作对比,符合几个就有分

然后用得到的prize去购买flag

这里可以看到要想买flag,靠前面的去爆破得到的prize会很少,题目中还有附件中可以去审计代码看看漏洞点

先来审计buy.php,看看其代码逻辑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?php include('check_register.php');include('header.php'); ?>


<h2>Buy a lottery!</h2>

<form method="POST">
<input type="text" name="numbers" id="numbers" minlength="7" maxlength="7" pattern="\d{7}" required placeholder="7 numbers">
<button type="button" id="btnBuy">Buy!</button>
</form>
<script type="text/javascript" src="js/buy.js"></script>
<p id="wait" class="alert alert-info" style="display: none;">Please wait...</p>
<div id="result" style="display: none;">
<p id="info" class="alert alert-info">Prize: <span id="prize"></span></p>
<p>
<span style="width: 10em; display: inline-block;">Winning numbers:</span>
<div id="win">

</div>
</p>
<p>
<span style="width: 10em; display: inline-block;">Your numbers:</span>
<div id="user">
<span class="number-ball number-ball-red">1</span>
<span class="number-ball number-ball-gray">6</span>
</div>
</p>
</div>

<?php include('footer.php'); ?>

可以看到这里面有段js代码,将输入的numbers调用buy.js进行处理

1
<script type="text/javascript" src="js/buy.js"></script>

下面为buy.js代码,在buy()函数中请求了api.php中的buy进一步处理numbers

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
function buy(){
$('#wait').show();
$('#result').hide();
var input = $('#numbers')[0];
if(input.validity.valid){
var numbers = input.value;
$.ajax({
method: "POST",
url: "api.php",
dataType: "json",
contentType: "application/json",
data: JSON.stringify({ action: "buy", numbers: numbers })
}).done(function(resp){
if(resp.status == 'ok'){
show_result(resp);
} else {
alert(resp.msg);
}
})
} else {
alert('invalid');
}
$('#wait').hide();
}

function show_result(resp){
$('#prize').text(resp.prize);
var numbers = resp.numbers;
var win_numbers = resp.win_numbers;
var numbers_result = '';
var win_numbers_result = '';
for(var i=0; i<7; i++){
win_numbers_result += '<span class="number-ball number-ball-red">' + win_numbers[i] + '</span>';
if(numbers[i] == win_numbers[i]){
numbers_result += '<span class="number-ball number-ball-red">' + numbers[i] + '</span>';
} else {
numbers_result += '<span class="number-ball number-ball-gray">' + numbers[i] + '</span>';
}
}
$('#win').html(win_numbers_result);
$('#user').html(numbers_result);
$('#money').text(resp.money);
$('#result').show();
$('#numbers').select()
}

$(document).ready(function(){
$('#btnBuy').click(buy);
$('form').submit(function( event ) {
buy();
return false;
});
})

下面为api.php中的buy()函数,大致意思是将输入的numbers和随机生成的数字进行比较,根据两个数字相等个数来返回prize给用户

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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]);
}

上面代码关键的漏洞点就是php代码中的**弱比较==**,如果==两边数据类型不一样,则需要将字符串转换为数字再进行比较,true和任意数字都相等。所以这里将输入的numbers每个元素都修改为true,则全都相等,获得最高的奖励

使用burp拦截buy.php的请求,修改请求报文如下,请求成功

我们多重放几次上述请求,刷新一下,看看此时自己的prize增加了很多

直到可以购买flag为止,点击购买flag

打赏
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2021-2024 John Doe
  • 访问人数: | 浏览次数:

让我给大家分享喜悦吧!

微信