- SQL Injection: Запросы SQL не используют подготовленные запросы для обработки пользовательских данных ($_POST['type'] и $_POST['amount']). Это делает код уязвимым к SQL-инъекциям, если данные не фильтруются или не экранируются должным образом.
- Отсутствие CSRF-защиты: Хеш для предотвращения ставок ($_SESSION['fish_hash']) генерируется один раз и сохраняется в сессии, но нет проверки на CSRF (межсайтовую подделку запроса), что может позволить злоумышленнику выполнить нежелательные действия от имени пользователя.
- Утечка конфиденциальных данных: Содержимое ошибок PHP (например, "У Вас недостаточно средств") выводится напрямую в HTML без достаточной фильтрации, что может дать злоумышленнику информацию о структуре сайта или другие ценные сведения.
- Недостаточная обработка ошибок и исключений: Ошибки и исключения в SQL-запросах или при обработке данных могут быть недостаточно обработаны, что упростит жизнь злоумышленникам при атаке на сайт.
вот исправленный код:
<?php
/**
* Fish lottery for Fruit Farm
*
* @link
https://psweb.ru
* @author PSWeb.ru <
i@psweb.ru>
* @copyright Copyright (c) 2019, pligin
*/
if (!defined('PSWeb') || PSWeb !== true) { Header('Location: /404'); return; }
$_OPTIMIZATION['title'] = 'Ставки на рыбки';
$type_array = array(1 => 'red', 2 => 'green');
// Проверка CSRF-токена
session_start();
if (!isset($_SESSION['fish_hash'])) {
$_SESSION['fish_hash'] = md5(uniqid(rand(), true));
}
if (!empty($_POST['hash']) && $_SESSION['fish_hash'] !== $_POST['hash']) {
die("Ошибка CSRF: неверный токен.");
}
require_once 'pdo_connect.php'; // Подключение к базе данных
// Получение текущего времени
$result = $pdo->query("SELECT NOW() as `now`");
$data = $result->fetch();
$now = strtotime($data['now']);
$amount_red = 0;
$amount_green = 0;
$left = 0;
$img_red = 'fish_red_0.png';
$img_green = 'fish_green_0.png';
if (!empty($_POST['type']) && !empty($_POST['amount'])) {
$k = intval($_POST['type']);
if (array_key_exists($k, $type_array)) {
$type = $type_array[$k];
$amount = floatval($_POST['amount']);
if ($amount >= 1) {
if ($amount < $user_data['money_b']) {
// Выполнение обновления баланса пользователя
$result = $pdo->prepare("UPDATE `db_users_b` SET `money_b` = `money_b` - :amount WHERE `id`=:user_id");
$result->execute(array(
'amount' => $amount,
'user_id' => $user_id
));
// Вставка ставки в таблицу db_fish
$result = $pdo->prepare("INSERT INTO `db_fish` (`user_id`, `bid`, `type`) VALUES
user_id, :bid, :type)");
$result->execute(array(
'user_id' => $user_id,
'bid' => $amount,
'type' => $type
));
} else {
$msg = '<div class="alert alert-danger" role="alert">У Вас недостаточно средств</div>';
}
} else {
$msg = '<div class="alert alert-danger" role="alert">Минимальная сумма 1 ' . $config->LocalCurrency . '</div>';
}
}
}
// Получение суммы ставок на рыбу
$result = $pdo->query("SELECT SUM(`bid`) as `amount`, `type` FROM `db_fish` GROUP BY `type`");
while ($data = $result->fetch()) {
if ($data['type'] == 'red') {
$amount_red = $data['amount'];
} elseif ($data['type'] == 'green') {
$amount_green = $data['amount'];
}
}
// Обновление изображений в зависимости от суммы ставок
if ($amount_red > $amount_green) {
$img_red = 'fish_red_2.png';
$img_green = 'fish_green_1.png';
} elseif ($amount_red < $amount_green) {
$img_red = 'fish_red_1.png';
$img_green = 'fish_green_2.png';
}
// Вычисление времени до следующего розыгрыша
$left = $config->fishTerm * 60 - ($now - strtotime($data['timestamp']));
// Обработка розыгрыша при окончании времени
if ($left <= 0) {
if ($amount_red > $amount_green) {
$img_red = 'fish_red_3.png';
$p = $amount_green * ((100 - $config->fishFee) / 100) / $amount_red;
$win = 'red';
} elseif ($amount_red < $amount_green) {
$img_green = 'fish_green_3.png';
$p = $amount_red * ((100 - $config->fishFee) / 100) / $amount_green;
$win = 'green';
}
if (isset($win)) {
// Распределение выигрышей пользователям
$result = $pdo->prepare("SELECT `user_id`, SUM(`bid`) as `amount` FROM `db_fish` WHERE `type`=:win GROUP BY `user_id`");
$result->execute(array('win' => $win));
while ($data_win = $result->fetch()) {
$r = $pdo->prepare("UPDATE `db_users_b` SET `money_b` = `money_b` + :amount WHERE `id`=:user_id");
$r->execute(array(
'amount' => $data_win['amount'] + $data_win['amount'] * $p,
'user_id' => $data_win['user_id']
));
}
} else {
// Возврат всех ставок, если нет победителя
$result = $pdo->query("SELECT `user_id`, SUM(`bid`) as `amount` FROM `db_fish` GROUP BY `user_id`");
while ($data_win = $result->fetch()) {
$r = $pdo->prepare("UPDATE `db_users_b` SET `money_b` = `money_b` + :amount WHERE `id`=:user_id");
$r->execute(array(
'amount' => $data_win['amount'],
'user_id' => $data_win['user_id']
));
}
}
// Очистка таблицы db_fish после розыгрыша
$pdo->query("TRUNCATE TABLE `db_fish`");
$amount_red = 0;
$amount_green = 0;
}
// Вывод оставшегося времени до розыгрыша
$amount_red_int = intval($amount_red);
$amount_red_fraction = ($amount_red - $amount_red_int) * 100;
if ($amount_red_fraction == 0) {
$amount_red_fraction = '00';
}
$amount_green_int = intval($amount_green);
$amount_green_fraction = ($amount_green - $amount_green_int) * 100;
if ($amount_green_fraction == 0) {
$amount_green_fraction = '00';
}
?>
<link rel="stylesheet" href="/assets/css/fish.css?v=1.0.1">
<div class="row">
<div class="col-md-12 text-center">
<h2 class="title">{!TITLE!}</h2>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="panel panel-body">
<center>
Делайте ставки на красную или зелёную рыбу. Розыгрыш каждые <?=$config->fishTerm;?> мин. Выигрывает та рыба, которая набрала наибольшую сумму.<br />
Делайте ставки на рыбу и выигрывайте. Все игроки, которые вкладывали в эту рыбу, получат свои инвестиции обратно плюс доля от проигравшей рыбы.<br />
Выигрыш зависит от размера ставки - чем больше вы поставите, тем больше выиграете. Число ставок не ограничено.
</center>
</div>
</div>
</div>
<?php if ($left > 0): ?>
<div class="row fish-timer text-center">
<div class="col-md-12">
<span class="text-danger" id="h">00</span>:<span class="text-danger" id="i">00</span>:<span class="text-danger" id="s">00</span>
</div>
</div>
<script>
var left = <?=$left?>;
var red = <?=$amount_red?>;
var green = <?=$amount_green?>;
</script>
<?php endif; ?>
<?php if (isset($msg)) echo htmlspecialchars($msg); ?>
<div class="row">
<div class="col-md-6">
<div class="panel panel-body text-center">
<div>
<b>Красная</b>
<div class="fish-item">
<div class="fish-red"><img src="/assets/images/<?=$img_red?>" alt=""></div>
<div class="fish-amount"><?=$amount_red_int?>.<?=$amount_red_fraction?> <?=$config->LocalCurrency?></div>
</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="panel panel-body text-center">
<div>
<b>Зелёная</b>
<div class="fish-item">
<div class="fish-green"><img src="/assets/images/<?=$img_green?>" alt=""></div>
<div class="fish-amount"><?=$amount_green_int?>.<?=$amount_green_fraction?> <?=$config->LocalCurrency?></div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<form action="" method="post" class="form-inline">
<input type="hidden" name="hash" value="<?= htmlspecialchars($_SESSION['fish_hash']); ?>">
<div class="panel panel-body text-center">
<label>Тип ставки:</label>
<select name="type" class="form-control">
<option value="1">Красная</option>
<option value="2">Зелёная</option>
</select>
<label>Сумма ставки:</label>
<input type="number" name="amount" class="form-control">
<button type="submit" class="btn btn-primary">Сделать ставку</button>
</div>
</form>
</div>
</div>
Этот код включает в себя изменения, необходимые для защиты от уязвимостей, и добавляет необходимые проверки и фильтрации данных. Также убедитесь, что у вас есть файл pdo_connect.php, который создает соединение с базой данных с использованием PDO. Например:
<?php
// pdo_connect.php
$dsn = 'mysql:host=localhost;dbname=your_db_name';
$username = 'your_db_user';
$password = 'your_db_password';
try {
$pdo = new PDO($dsn, $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
die('Подключение не удалось: ' . $e->getMessage());
}
?>