diff --git a/_incl_data/class/Core/TOTP.php b/_incl_data/class/Core/TOTP.php
new file mode 100644
index 00000000..c984b62b
--- /dev/null
+++ b/_incl_data/class/Core/TOTP.php
@@ -0,0 +1,69 @@
+base32_decode($this->secret);
+ $binaryTime = pack('N*', 0) . pack('N*', $time);
+ $hash = hash_hmac('sha1', $binaryTime, $secretKey, true);
+ $offset = ord($hash[strlen($hash) - 1]) & 0x0F;
+ $otp = (
+ ((ord($hash[$offset]) & 0x7F) << 24) |
+ ((ord($hash[$offset + 1]) & 0xFF) << 16) |
+ ((ord($hash[$offset + 2]) & 0xFF) << 8) |
+ (ord($hash[$offset + 3]) & 0xFF)
+ ) % 10 ** $digits;
+ return str_pad((string)$otp, $digits, '0', STR_PAD_LEFT);
+ }
+
+ private function base32_decode(string $input): string
+ {
+ $base32charsFlipped = array_flip(str_split(self::BASE32CHARS));
+ $output = '';
+ $v = 0;
+ $vbits = 0;
+
+ for ($i = 0, $j = strlen($input); $i < $j; $i++) {
+ $v <<= 5;
+ if ($input[$i] == '=') continue;
+ $v += $base32charsFlipped[$input[$i]];
+ $vbits += 5;
+
+ if ($vbits >= 8) {
+ $vbits -= 8;
+ $output .= chr(($v & (0xFF << $vbits)) >> $vbits);
+ }
+ }
+ return $output;
+ }
+}
diff --git a/_incl_data/class/User/Confirmation.php b/_incl_data/class/User/Confirmation.php
index e4d0fc25..37dec423 100644
--- a/_incl_data/class/User/Confirmation.php
+++ b/_incl_data/class/User/Confirmation.php
@@ -6,30 +6,24 @@ use Core\Config;
use Core\Db;
use Helper\Mail;
use PassGen;
-use UserIp;
class Confirmation
{
/**
* Для однотипных писем с подтверждением.
* @param array $userinfo Данные из (User)->info.
- * @param mixed $value Новое значение
+ * @param string $value Новое значение
* @param ?int $code Проверочный код
* @param string $type Тип меняемого значения. С маленькой буквы, именительный падеж.
* @return void
*/
- public static function byEmail(array $userinfo, string $type, $value, ?int $code = null)
+ public static function byEmail(array $userinfo, string $type, string $value, ?int $code = null): void
{
- if ($type === 'pass2' && is_null($code)) {
- self::pass2ByEmailCustom($userinfo, $value);
- return;
- }
$ip = UserIp::get();
$date = date('d.m.y H:i');
$https = Config::get('https');
$support = Config::get('support');
- $activationLink = 'https://' . $userinfo['city'] . Config::get('host') .
- "/confirm.php?id={$userinfo['id']}&code=$code";
+ $activationLink = Config::get('https') . "/confirm.php?id={$userinfo['id']}&code=$code";
$fulllogin = $userinfo['login'] . "[{$userinfo['level']}]";
Mail::send(
$userinfo['mail'],
@@ -55,31 +49,7 @@ class Confirmation
);
}
- private static function pass2ByEmailCustom(array $userinfo, string $pass2)
- {
-
- $ip = UserIp::get();
- $fulllogin = $userinfo['login'] . "[{$userinfo['level']}]";
- Mail::send(
- $userinfo['mail'],
- <<
-
-
- Ошибка!!
+ $returnLink = Config::get('https');
+ $html = <<
+
-
-
- ' . $e . '
-
-
-
-
-'
- );
+ HTML;
+ exit($html);
}
$u = Db::getRow(
@@ -60,259 +55,154 @@ $u = Db::getRow(
users.login,
auth,
pass,
- pass2,
- users.city,
+ totp,
users.ip,
ipreg,
admin,
online,
banned,
- host_reg,
- timereg,
- securetime,
users_delo.text as block_reason
from users
left join users_delo on users.id = users_delo.uid
where users.login = ?',
- [$_POST['login']]
+ [$login]
);
-$auth = Db::getValue('select id from logs_auth where uid = ? and ip = ?', [$u['id'], IP]);
-if (!isset($u['id'])) {
- error('Логин "' . $_POST['login'] . '" не найден в базе.');
-} elseif ($u['banned'] > 0) {
- $blockstr = "Персонаж
{$u['login']} заблокирован.";
- $blockstr .= $u['block_reason'] ? "Причина блокировки: {$u['block_reason']}
" : '
';
- error($blockstr);
-} elseif (!Password::isGood($_POST['pass'], $u['pass'], $u['login'])) {
- error("Неверный пароль к персонажу {$u['login']}.");
- Db::sql(
- 'insert into logs_auth (uid, ip, browser, type, time) values (?,?,?,3,unix_timestamp())',
- [$u['id'], IP, $_SERVER['HTTP_USER_AGENT']]
- );
-} else {
-
- //Второй пароль
- if (!empty($u['pass2'])) {
- $_SESSION['login'] = $_POST['login'];
- $_SESSION['pass'] = $_POST['pass'];
- $good2 = false;
- $koko = '';
- if (password_verify($_POST['code'], $u['pass2'])) {
- $good2 = true;
- unset($_SESSION['login'], $_SESSION['pass']);
- } else {
- if (isset($_POST['code'])) {
- $koko = 'Неверный второй пароль
';
- }
- setcookie('login', '', time() - 60 * 60 * 24, '', Config::get('host'));
- }
-
- if ($koko) {
- $koko = '
' . $koko . ' ';
- }
- if (!$good2) {
- ?>
-
-
-
-
-
-
-
Второй пароль
-
-
-
Запрос второго пароля к персонажу.
- = $koko ?>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 0) {
+ $blockstr = "Персонаж
{$u['login']} заблокирован.";
+ $blockstr .= $u['block_reason'] ? "Причина блокировки: {$u['block_reason']}
" : '
';
+ error($blockstr);
+ } elseif (!Password::isGood($password, $u['pass'], $u['login'])) {
Db::sql(
- 'insert into logs_auth (uid, ip, browser, type, time) VALUES (?,?,?,1,unix_timestamp())',
- [$u['id'], $_COOKIE['ip'], $_SERVER['HTTP_USER_AGENT']]
+ 'insert into logs_auth (uid, ip, browser, type, time) values (?,?,?,3,unix_timestamp())',
+ [$u['id'], IP, $_SERVER['HTTP_USER_AGENT']]
);
+ error("Неверный пароль к персонажу {$u['login']}.");
}
- setcookie('login', $_POST['login'] ?? '', time() + 60 * 60 * 24 * 7, '', Config::get('host'));
- setcookie('ip', IP, time() + 60 * 60 * 24 * 150, '');
-
- if ($u['online'] < time() - 520) {
- $sp = Db::getRows('select room, city, login from users where online > unix_timestamp() - 600 and id in (select user from friends where friend = ?)', [$u['id']]);
- foreach ($sp as $usr) {
- $chatDto = new ChatMessage();
- $chatDto->setRoom($usr['room']);
- $chatDto->setCity($usr['city']);
- $chatDto->setTo($usr['login']);
- $chatDto->setText('Вас приветствует:
' . $u['login'] . ' .');
- $chatDto->setType(6);
- $chat->sendMsg($chatDto);
- }
+ $_SESSION['login'] = $u['login'];
+ if (!empty($u['totp'])) {
+ $_SESSION['totp'] = new TOTP($u['totp']);
}
-
- $apu = '';
- Db::sql('update dump set ver = 1, upd = 2 where uid = ?', [$u['id']]);
-
- if (
- $u['auth'] != md5($u['login'] . 'AUTH' . IP) ||
- $_COOKIE['auth'] != md5($u['login'] . 'AUTH' . IP) ||
- $u['auth'] == '' || $u['auth'] == '0'
- ) {
- if (
- $u['auth'] != '' &&
- $u['auth'] != '0' &&
- $u['ip'] != IP
- ) {
- $cmsg = new ChatMessage();
- $cmsg->setTo($u['login']);
- $cmsg->setText('В предыдущий раз этим персонажем заходили с другого компьютера ' . date('d.m.Y H:i', $u['online']) . "(Предыдущий ip: %{$u['ip']})");
- $cmsg->setType(6);
- $chat->sendMsg($cmsg);
- }
- $apu = "auth = '" . md5($u['login'] . 'AUTH' . IP) . "',";
- setcookie('auth', md5($u['login'] . 'AUTH' . IP), time() + 60 * 60 * 24 * 365, '', Config::get('host'));
- }
-
- $ipnew = IP;
-
- Db::sql('insert into logs_auth (uid, ip, browser, time) values (?,?,?,unix_timestamp())', [
- $u['id'], IP, $_SERVER['HTTP_USER_AGENT'],
- ]);
-
- Db::sql("update users set $apu ip = ?, dateEnter = ?, online = unix_timestamp() where id = ?", [$ipnew, $_SERVER['HTTP_USER_AGENT'], $u['id']]);
-
- $_SESSION['uid'] = $u['id'];
- header('location: /bk');
- exit();
}
+
+if (!empty($_SESSION['totp']) && !empty($_SESSION['login'])) {
+ if (empty($otp)) {
+ ?>
+
+
+
+
Второй пароль
+
+
+
+
+
+ generate() !== $otp) {
+ unset($_SESSION['login'], $_SESSION['totp']);
+ error('Неверный одноразовый код!');
+ }
+}
+
+if (!Db::getValue('select count(*) from stats where id = ?', [$u['id']])) {
+ Db::sql('insert into stats (id, stats) values (?,?)', [$u['id'], 's1=3|s2=3|s3=3|s4=3|rinv=40|m9=5|m6=10']);
+}
+if (!Db::getValue('select count(*) from online where uid = ?', [$u['id']])) {
+ Db::sql('insert into online (uid, timeStart) values (?,unix_timestamp())', [$u['id']]);
+}
+
+if (isset($_COOKIE['login'])) {
+ setcookie('login', '', time() - 60 * 60 * 24, '', Config::get('host'));
+}
+
+//мульты
+if ($u['admin'] === 0) {
+ $ipm1 = Db::getValue(
+ 'select ip from logs_auth where uid = ? and ip != ? order by id limit 1',
+ [$u['id'], $u['ip']]
+ );
+ $ppl = Db::getRows(
+ 'select * from logs_auth where ip != ? and (ip = ? or ip = ? or ip = ? or ip = ? or ip = ?)',
+ ['', $u['ip'], $ipm1, $u['ipreg'], IP, $_COOKIE['ip']]
+ );
+ foreach ($ppl as $item) {
+ $ml = Db::getValue(
+ 'select id from mults where (uid = ? and uid2 = ?) or (uid = ? and uid2 = ?) limit 1',
+ [$item['uid'], $u['id'], $u['id'], $item['uid']]
+ );
+ if (!$ml && $item['ip'] !== '' && $item['ip'] !== '127.0.0.1') {
+ Db::sql('insert into mults (uid, uid2, ip) VALUES (?,?,?)', [$u['id'], $item['uid'], $item['ip']]);
+ }
+ }
+}
+
+if (isset($_COOKIE['ip']) && $_COOKIE['ip'] != IP) {
+ Db::sql(
+ 'insert into logs_auth (uid, ip, browser, type, time) VALUES (?,?,?,1,unix_timestamp())',
+ [$u['id'], $_COOKIE['ip'], $_SERVER['HTTP_USER_AGENT']]
+ );
+}
+
+setcookie('login', $_POST['login'] ?? '', time() + 60 * 60 * 24 * 7, '', Config::get('host'));
+setcookie('ip', IP, time() + 60 * 60 * 24 * 150, '');
+
+if ($u['online'] < time() - 520) {
+ $sp = Db::getRows('select room, login from users where online > unix_timestamp() - 600 and id in (select user from friends where friend = ?)', [$u['id']]);
+ foreach ($sp as $usr) {
+ $chatDto = new ChatMessage();
+ $chatDto->setRoom($usr['room']);
+ $chatDto->setTo($usr['login']);
+ $chatDto->setText('Вас приветствует:
' . $u['login'] . ' .');
+ $chatDto->setType(6);
+ $chat->sendMsg($chatDto);
+ }
+}
+
+$apu = '';
+Db::sql('update dump set ver = 1, upd = 2 where uid = ?', [$u['id']]);
+
+if (
+ $u['auth'] != md5($u['login'] . 'AUTH' . IP) ||
+ $_COOKIE['auth'] != md5($u['login'] . 'AUTH' . IP) ||
+ $u['auth'] == '' || $u['auth'] == '0'
+) {
+ if (
+ $u['auth'] != '' &&
+ $u['auth'] != '0' &&
+ $u['ip'] != IP
+ ) {
+ $cmsg = new ChatMessage();
+ $cmsg->setTo($u['login']);
+ $cmsg->setText('В предыдущий раз этим персонажем заходили с другого компьютера ' . date('d.m.Y H:i', $u['online']) . "(Предыдущий ip: %{$u['ip']})");
+ $cmsg->setType(6);
+ $chat->sendMsg($cmsg);
+ }
+ $apu = "auth = '" . md5($u['login'] . 'AUTH' . IP) . "',";
+ setcookie('auth', md5($u['login'] . 'AUTH' . IP), time() + 60 * 60 * 24 * 365, '', Config::get('host'));
+}
+
+$ipnew = IP;
+
+Db::sql('insert into logs_auth (uid, ip, browser, time) values (?,?,?,unix_timestamp())', [
+ $u['id'], IP, $_SERVER['HTTP_USER_AGENT'],
+]);
+
+Db::sql("update users set $apu ip = ?, dateEnter = ?, online = unix_timestamp() where id = ?", [$ipnew, $_SERVER['HTTP_USER_AGENT'], $u['id']]);
+
+$_SESSION['uid'] = $u['id'];
+
+unset($_SESSION['login'], $_SESSION['totp']);
+
+header('location: /bk');
+exit();
diff --git a/gate.php b/gate.php
deleted file mode 100644
index 5a83f035..00000000
--- a/gate.php
+++ /dev/null
@@ -1,110 +0,0 @@
- 300000 ) {
- $_GET['exp'] = 300000;
- }
-
- if( $_GET['clan'] == 1 ) {
- $_GET['clan'] = 0;
- $_GET['align'] = 0;
- $_GET['clan_prava'] = 0;
- }
- if( $_GET['clan'] > 1 ) {
- $_GET['clan'] += 2;
- }
-
- $usr = mysql_fetch_array(mysql_query('SELECT * FROM `users` WHERE `login` = "'.mysql_real_escape_string($_GET['login']).'" LIMIT 1'));
- if(isset($usr['id']) && isset($_GET['in'])) {
- unset($_GET['in']);
- setcookie('login',$_GET['login'], (time()+60*60*24*7) , '' , '.new-combats.com' );
- setcookie('pass',$_GET['pass'], (time()+60*60*24*7) , '' , '.new-combats.com' );
- setcookie('login',$_GET['login'], (time()+60*60*24*7) );
- setcookie('pass',$_GET['pass'], (time()+60*60*24*7) );
- header('location: /enter.php?login='.$_GET['login'].'&pass='.$_GET['pass'].'');
- die();
- }
-
- }
-
- if( isset($_GET['in']) ) {
-
- //Создаем персонажа
- if( (int)$_GET['ref'] > 0 ) {
- mysql_query("UPDATE `users` SET `referals` = `referals` + 1 WHERE `id` = '".mysql_real_escape_string((int)$_GET['ref'])."' LIMIT 1");
- }
- $pass = md5($pass);
- mysql_query('INSERT INTO `users` (`real`,`online`,`align`,`clan`,`clan_prava`,`win`,`lose`,`nich`,`sex`,`bithday`,`host_reg`,`pass`,`ip`,`ipreg`,`city`,`cityreg`,`room`,`timereg`) VALUES (
- "1",
- "'.time().'",
- "'.mysql_real_escape_string($_GET['align']).'",
- "'.mysql_real_escape_string($_GET['clan']).'",
- "'.mysql_real_escape_string($_GET['clan_prava']).'",
- "'.mysql_real_escape_string($_GET['win']).'",
- "'.mysql_real_escape_string($_GET['lose']).'",
- "'.mysql_real_escape_string($_GET['nich']).'",
- "'.mysql_real_escape_string($_GET['sex']).'",
- "'.mysql_real_escape_string($_GET['bithday']).'",
-
- "'.mysql_real_escape_string(0+$_GET['ref']).'",
- "'.mysql_real_escape_string($pass).'",
- "'.mysql_real_escape_string(GetRealIpTest()).'",
- "'.mysql_real_escape_string(GetRealIpTest()).'",
- "capitalcity",
- "capitalcity",
- "0",
- "'.time().'"
- )');
- $uid = mysql_insert_id();
- if( $uid > 0 ) {
-
- mysql_query('UPDATE `users` SET `login` = "'.mysql_real_escape_string($login).'" WHERE `id` = "'.$uid.'" LIMIT 1');
- //Создаем статы персонажа
- mysql_query("INSERT INTO `online` (`uid`,`timeStart`) VALUES ('".$uid."','".time()."')");
- mysql_query("INSERT INTO `stats` (`id`,`stats`,`exp`) VALUES ('".$uid."','s1=3|s2=3|s3=3|s4=3|rinv=40|m9=5|m6=10','".mysql_real_escape_string($_GET['exp'])."')");
-
- //мульты
- $ipm1 = mysql_fetch_array(mysql_query('SELECT * FROM `logs_auth` WHERE `uid` = "'.mysql_real_escape_string($uid).'" AND `ip`!="'.mysql_real_escape_string(GetRealIpTest()).'" ORDER BY `id` ASC LIMIT 1'));
- $ppl = mysql_query('SELECT * FROM `logs_auth` WHERE `ip`!="" AND (`ip` = "'.mysql_real_escape_string(GetRealIpTest()).'" OR `ip`="'.mysql_real_escape_string($ipm1['ip']).'" OR `ip`="'.mysql_real_escape_string($_COOKIE['ip']).'")');
- while($spl = mysql_fetch_array($ppl))
- {
- $ml = mysql_fetch_array(mysql_query('SELECT `id` FROM `mults` WHERE (`uid` = "'.$spl['uid'].'" AND `uid2` = "'.$uid.'") OR (`uid2` = "'.$spl['uid'].'" AND `uid` = "'.$uid.'") LIMIT 1'));
- if(!isset($ml['id']) && $spl['ip']!='' && $spl['ip']!='127.0.0.1')
- {
- mysql_query('INSERT INTO `mults` (`uid`,`uid2`,`ip`) VALUES ("'.$uid.'","'.$spl['uid'].'","'.$spl['ip'].'")');
- }
- }
- mysql_query("INSERT INTO `logs_auth` (`uid`,`ip`,`browser`,`type`,`time`,`depass`) VALUES ('".$uid."','".mysql_real_escape_string(GetRealIpTest())."','".mysql_real_escape_string($_SERVER['HTTP_USER_AGENT'])."','1','".time()."','')");
-
- //Обновяем таблицы
- mysql_query("UPDATE `users` SET `online`='".time()."',`ip` = '".mysql_real_escape_string(GetRealIpTest())."' WHERE `uid` = '".$uid."' LIMIT 1");
-
- if(!setcookie('login',$login, (time()+60*60*24*7) , '' , '.new-combats.com' ) || !setcookie('pass',$pass, (time()+60*60*24*7) , '' , '.new-combats.com' )) {
- die('Ошибка сохранения cookie.');
- }
- header('location: /enter.php?login='.$_GET['login'].'&pass='.$_GET['pass'].'');
- }
- }
-?>
\ No newline at end of file
diff --git a/index.php b/index.php
index 4b40967b..6681932e 100644
--- a/index.php
+++ b/index.php
@@ -6,11 +6,6 @@ if (!defined('GAME_VERSION')) {
require_once '_incl_data/autoload.php';
}
-if (isset($_GET['time'])) {
- echo time() . '
' . date('d.m.Y H:i:s', (int)$_GET['time']);
- die();
-}
-
header("Cache-Control: max-age=3600");
?>
@@ -30,6 +25,7 @@ header("Cache-Control: max-age=3600");
flex-direction: column;
margin-top: 50px;
}
+
hr.incontent {
width: 32%;
border: 1px #1c1c1c solid;
@@ -43,7 +39,7 @@ header("Cache-Control: max-age=3600");
Ваш Никнейм
Ваш Пароль
-
+
diff --git a/modules_data/_changepass.php b/modules_data/_changepass.php
index d227e67a..23377210 100644
--- a/modules_data/_changepass.php
+++ b/modules_data/_changepass.php
@@ -3,6 +3,8 @@
/* @var $u User */
use Core\Config;
+use Core\Db;
+use Core\TOTP;
use User\Email;
use User\Password;
@@ -14,23 +16,18 @@ $password = new Password($u->info);
$email = new Email($u->info);
$status = null;
-if ($_POST['oldpsw2']) { // remove psw2
- if (password_verify((int)$_POST['oldpsw2'], $u->info['pass2'])) {
- $u->info['pass2'] = $password->changeSecond(null)['pass2'];
- $status = "Второй пароль выключен. ";
- } else {
- $status = "Введен не верный второй пароль! ";
- }
+if ($_POST['removetotp']) {
+ // Удаление ключа ТОТР
+ $u->info['totp'] = '';
+ Db::sql('update users set totp = ? where id = ?', [$u->info['totp'], $u->info['id']]);
+ $status = "Секретный ключ удалён. ";
}
-if ($_POST['num_count']) { //add psw2
- $arr = $password->changeSecond((int)$_POST['num_count']);
- $status = "Второй пароль: {$arr['pass2']}.
- Запомните или запишите, т.к. он не высылается на email и его нельзя как-либо узнать.
- Потеряв второй пароль, вы потеряете персонажа!
- Этот пароль выслан на ваш email.
- ";
- $u->info['pass2'] = $arr['hash'];
+if ($_POST['newtotp']) {
+ // Создание ключа ТОТР
+ $u->info['totp'] = TOTP::otpSecret($u->info['id']);
+ Db::sql('update users set totp = ? where id = ?', [$u->info['totp'], $u->info['id']]);
+ $status = "Секретный ключ создан. ";
}
if (
@@ -66,7 +63,7 @@ if (
}
?>
-
+
Настройки безопасности
@@ -180,41 +177,18 @@ if (
- Второй уровень защиты
- Настоятельно рекомендуем включить второй уровень защиты.
- На компьютере может быть установлен клавиатурный шпион, который записывает все нажатия клавиш, таким
- образом,
- могут узнать ваш пароль.
- Возможно, в сети компьютеров установлен "сетевой снифер", перехватывающий все интернет пакеты, который легко
- покажет все пароли. Чтобы обезопасить себя, вы можете установить своему персонажу второй пароль, который
- можно
- вводить при помощи мышки (клавиатурным шпионом не перехватить) и который передается на игровой сервер в
- зашифрованном виде, не поддающимся расшифровке ("сетевой снифер" не сможет перехватить его).
- Будьте внимательны! Второй пароль отправляется на email один раз,при установке второго уровня защиты!
-
- info['pass2'])) {
- echo "Второй пароль установлен.
- Введите второй пароль
- ";
- } else {
- ?>
- Длина пароля:
-
- 4 знака
-
-
- 6 знаков
-
-
- 8 знаков
-
-
-
-
+ TOTP
+ TOTP (Time-based One-Time Password) - это метод двухфакторной аутентификации, который генерирует одноразовый пароль на основе текущего времени.
+ Устанавливается для повышения безопасности вашего аккаунта, так как помогает защитить его от несанкционированного доступа.
+ Вы можете использовать TOTP приложения, такие как Google Authenticator или Authy, чтобы генерировать и отображать временные одноразовые пароли на вашем мобильном устройстве.
+
+ Будьте внимательны! Секретный ключ генерируется только один раз и не подлежит восстановлению. Его можно только удалить или заменить новым.
+ info['totp'])): ?>
+ Секретный ключ:
+ {$u->info['totp']}
+
+
+