Использование базового TOTP через мобильное приложение вместо существующей реализации второго пароля на javascript.

This commit is contained in:
Ivor Barhansky 2024-05-09 19:19:14 +03:00
parent 85b74015b7
commit 244e081014
7 changed files with 260 additions and 494 deletions

View File

@ -0,0 +1,69 @@
<?php
namespace Core;
readonly class TOTP
{
private const BASE32CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'; // RFC 4648 Base32
public function __construct(private string $secret)
{
}
public static function otpSecret($uniqueString, $length = 20): string
{
// Уникальная строка + текущее время в микросекундах
$seed = $uniqueString . microtime(true);
// Хэшируем сид для более случайного распределения
$seed = hash('sha256', $seed);
$secret = '';
$max = strlen(self::BASE32CHARS) - 1;
// Генерируем случайную строку нужной длины
for ($i = 0; $i < $length; $i++) {
$index = hexdec(substr($seed, $i, 2)) % $max; // Получаем индекс символа из хэшированного сида
$secret .= self::BASE32CHARS[$index];
}
return $secret;
}
public function generate(int $digits = 6, int $timeStep = 30): string
{
$time = floor(time() / $timeStep);
$secretKey = $this->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;
}
}

View File

@ -6,30 +6,24 @@ use Core\Config;
use Core\Db; use Core\Db;
use Helper\Mail; use Helper\Mail;
use PassGen; use PassGen;
use UserIp;
class Confirmation class Confirmation
{ {
/** /**
* Для однотипных писем с подтверждением. * Для однотипных писем с подтверждением.
* @param array $userinfo Данные из (User)->info. * @param array $userinfo Данные из (User)->info.
* @param mixed $value Новое значение * @param string $value Новое значение
* @param ?int $code Проверочный код * @param ?int $code Проверочный код
* @param string $type Тип меняемого значения. С маленькой буквы, именительный падеж. * @param string $type Тип меняемого значения. С маленькой буквы, именительный падеж.
* @return void * @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(); $ip = UserIp::get();
$date = date('d.m.y H:i'); $date = date('d.m.y H:i');
$https = Config::get('https'); $https = Config::get('https');
$support = Config::get('support'); $support = Config::get('support');
$activationLink = 'https://' . $userinfo['city'] . Config::get('host') . $activationLink = Config::get('https') . "/confirm.php?id={$userinfo['id']}&code=$code";
"/confirm.php?id={$userinfo['id']}&code=$code";
$fulllogin = $userinfo['login'] . "[{$userinfo['level']}]"; $fulllogin = $userinfo['login'] . "[{$userinfo['level']}]";
Mail::send( Mail::send(
$userinfo['mail'], $userinfo['mail'],
@ -55,31 +49,7 @@ class Confirmation
); );
} }
private static function pass2ByEmailCustom(array $userinfo, string $pass2) public static function userRegistrationCodeByEmail(string $email, string $login): void
{
$ip = UserIp::get();
$fulllogin = $userinfo['login'] . "[{$userinfo['level']}]";
Mail::send(
$userinfo['mail'],
<<<HTML
<html lang="ru">
<head><title>Второй пароль от персонажа $fulllogin.</title></head>
<body>
Вами, с IP адреса - $ip, был установлен второй пароль в игре Бойцовский Клуб.<br>
Если это были не Вы, свяжитесь с администрацией сайта.<br><br>
------------------------------------------------------------------<br>
Ваш логин | {$userinfo['login']}<br>
Второй пароль | ' . $pass2 . '<br>
------------------------------------------------------------------<br>
<br><br>Желаем Вам приятной игры.<br><br><i>Администрация</i>
</body>
HTML,
"Второй пароль от персонажа $fulllogin"
);
}
public static function userRegistrationCodeByEmail(string $email, string $login)
{ {
$code = PassGen::intCode(4); $code = PassGen::intCode(4);
Db::sql('insert into secure_code (email, code, time) values (?,?,unix_timestamp())', [$email, $code]); Db::sql('insert into secure_code (email, code, time) values (?,?,unix_timestamp())', [$email, $code]);

View File

@ -57,28 +57,5 @@ class Password
} }
return $this->info['pass']; return $this->info['pass'];
} }
public function changeSecond(?int $passLength): array
{
if (in_array($passLength, [4, 6, 8])) {
$query = 'update users set pass2 = ? where id = ?';
$pass2 = PassGen::intCode($passLength);
$args = [
password_hash($pass2, PASSWORD_DEFAULT),
$this->info['id'],
];
Confirmation::byEmail($this->info, 'pass2', $pass2);
$hash = $args[0];
} else {
$query = 'update users set pass2 = default where id = ?';
$args = [$this->info['id']];
}
Db::sql($query, $args);
return [
'pass2' => $pass2 ?? '',
'hash' => $hash ?? null,
];
}
} }

430
enter.php
View File

@ -3,6 +3,8 @@
use Core\Config; use Core\Config;
use Core\Database; use Core\Database;
use Core\Db; use Core\Db;
use Core\TOTP;
use JetBrains\PhpStorm\NoReturn;
use User\Password; use User\Password;
use User\UserIp; use User\UserIp;
@ -15,43 +17,36 @@ require_once __DIR__ . DIRECTORY_SEPARATOR . '_incl_data/autoload.php';
Database::init(); Database::init();
define('IP', UserIp::get()); define('IP', UserIp::get());
$chat = new Chat(); $chat = new Chat();
$login = $_SESSION['login'] ?? '';
$password = '';
$otp = '';
if (isset($_GET['login'])) { if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$_POST['login'] = $_GET['login']; if (isset($_POST['login'])) {
$_POST['pass'] = $_GET['pass']; $login = $_POST['login'];
$_POST['code'] = $_GET['code']; }
if (isset($_POST['password'])) {
$password = $_POST['password'];
}
if (isset($_POST['otp'])) {
$otp = $_POST['otp'];
}
} }
if (isset($_POST['psw'])) { #[NoReturn] function error($e): void
$_POST['pass'] = $_POST['psw'];
}
if (isset($_SESSION['login'])) {
$_POST['login'] = $_SESSION['login'];
$_POST['pass'] = $_SESSION['pass'];
}
function error($e)
{ {
die( $returnLink = Config::get('https');
' $html = <<<HTML
<link rel="stylesheet" href="error.css"> <link rel="stylesheet" href="error.css">
<div class="text-wrapper"> <div class="text-wrapper">
<div class="title" data-content="Ошибка"> <div class="title" data-content="Ошибка">Ошибка!!</div>
Ошибка!! <div class="subtitle">$e</div>
<div class="buttons"><a class="button" href="$returnLink">Вернуться назад</a></div>
</div> </div>
HTML;
<div class="subtitle"> exit($html);
' . $e . '
</div>
<div class="buttons">
<a class="button" href="' . Config::get('https') . '">Вернуться назад</a>
</div>
</div>
'
);
} }
$u = Db::getRow( $u = Db::getRow(
@ -60,259 +55,154 @@ $u = Db::getRow(
users.login, users.login,
auth, auth,
pass, pass,
pass2, totp,
users.city,
users.ip, users.ip,
ipreg, ipreg,
admin, admin,
online, online,
banned, banned,
host_reg,
timereg,
securetime,
users_delo.text as block_reason users_delo.text as block_reason
from users from users
left join users_delo on users.id = users_delo.uid left join users_delo on users.id = users_delo.uid
where users.login = ?', 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'])) { if (empty($_SESSION['login'])) {
error('Логин "' . $_POST['login'] . '" не найден в базе.'); if (!isset($u['id'])) {
} elseif ($u['banned'] > 0) { error('Логин "' . $login . '" не найден в базе.');
$blockstr = "Персонаж <b>{$u['login']}</b> заблокирован."; } elseif ($u['banned'] > 0) {
$blockstr .= $u['block_reason'] ? "Причина блокировки: {$u['block_reason']}<br><br>" : '<br><br>'; $blockstr = "Персонаж <b>{$u['login']}</b> заблокирован.";
error($blockstr); $blockstr .= $u['block_reason'] ? "Причина блокировки: {$u['block_reason']}<br><br>" : '<br><br>';
} elseif (!Password::isGood($_POST['pass'], $u['pass'], $u['login'])) { error($blockstr);
error("Неверный пароль к персонажу {$u['login']}."); } elseif (!Password::isGood($password, $u['pass'], $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 = 'Неверный второй пароль<br>';
}
setcookie('login', '', time() - 60 * 60 * 24, '', Config::get('host'));
}
if ($koko) {
$koko = '<b style="color: red">' . $koko . '</b>';
}
if (!$good2) {
?>
<!Doctype html>
<HTML lang="ru">
<HEAD>
<link rel=stylesheet type="text/css">
<meta name="msapplication-config" content="browserconfig.xml"/>
<TITLE>Второй пароль</TITLE>
</HEAD>
<body style="background-color: #dfdfde;">
<H3>Запрос второго пароля к персонажу.</H3>
<?= $koko ?>
<div style="text-align: center">
<br>
<br>
<img id="pass" onClick="" width="295" src="i/pin/e0.png" alt="pass">
<br>
<br>
<img id="p1" onClick="" src="" alt="p1">
<img id="p2" onClick="" src="" alt="p2">
<img id="p3" onClick="" src="" alt="p3">
<br>
<img id="p4" onClick="" src="" alt="p4">
<img id="p5" onClick="" src="" alt="p5">
<img id="p6" onClick="" src="" alt="p6">
<br>
<img id="p7" onClick="" src="" alt="p7">
<img id="p8" onClick="" src="" alt="p8">
<img id="p9" onClick="" src="" alt="p9">
<br>
<img onClick="keypush(12);" src="i/pin/12.png" alt="back">
<img id="p0" name="image" onClick="" src="" alt="nan">
<img onClick="keypush(11);" src="i/pin/11.png" alt="ok">
<br>
</div>
</BODY>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>
var dopass = '';
var tdopass = '';
var lenth = 0;
randomp();
function randomp() {
var ss = [];
var n = 0;
while (n < 10) {
ss[n] = n;
n++;
}
var i = 0;
var k = 0;
var m = 0;
var tmpp = 0;
while (i < 10) {
k = getRandomInt(10);
m = getRandomInt(10);
if (k != m) {
tmpp = ss[k];
ss[k] = ss[m];
ss[m] = tmpp;
i++;
}
}
n = 10;
while (n > -1) {
n = n - 1;
document.getElementById('p' + n).setAttribute("src", "i/pin/" + ss[n] + ".png");
document.getElementById('p' + n).setAttribute("onClick", "keypush(" + ss[n] + ");");
}
}
function getRandomInt(max) {
return Math.floor(Math.random() * Math.floor(max));
}
function keypush(n) {
if (n == 12) {
if (lenth > 0) {
dopass = '';
lenth = 0;
document.getElementById('pass').setAttribute("src", "i/pin/e" + lenth + ".png");
}
} else if (n == 11) {
var $_POST = <?= json_encode($_POST); ?>;
window.location.replace("/enter.php?code=" + dopass + "&login=" + $_POST['login'] + "&pass=" + $_POST['pass']);
} else {
if (lenth < 8) {
dopass = dopass + '' + n;
lenth++;
document.getElementById('pass').setAttribute("src", "i/pin/e" + lenth + ".png");
}
}
}
</script>
</HTML>
<?php
die();
}
}
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( Db::sql(
'insert into logs_auth (uid, ip, browser, type, time) VALUES (?,?,?,1,unix_timestamp())', 'insert into logs_auth (uid, ip, browser, type, time) values (?,?,?,3,unix_timestamp())',
[$u['id'], $_COOKIE['ip'], $_SERVER['HTTP_USER_AGENT']] [$u['id'], IP, $_SERVER['HTTP_USER_AGENT']]
); );
error("Неверный пароль к персонажу {$u['login']}.");
} }
setcookie('login', $_POST['login'] ?? '', time() + 60 * 60 * 24 * 7, '', Config::get('host')); $_SESSION['login'] = $u['login'];
setcookie('ip', IP, time() + 60 * 60 * 24 * 150, ''); if (!empty($u['totp'])) {
$_SESSION['totp'] = new TOTP($u['totp']);
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('Вас приветствует: <b>' . $u['login'] . '</b>.');
$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'];
header('location: /bk');
exit();
} }
if (!empty($_SESSION['totp']) && !empty($_SESSION['login'])) {
if (empty($otp)) {
?>
<!doctype html>
<html lang="ru">
<head>
<title>Второй пароль</title>
</head>
<body>
<form method="post">
<label for="otp">Одноразовый код:</label><br>
<input name="otp" id="otp" minlength="6" maxlength="6" size="6" placeholder="000000" required><br>
<input type="submit">
</form>
</body>
</html>
<?php
exit();
}
if ($_SESSION['totp']->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('Вас приветствует: <b>' . $u['login'] . '</b>.');
$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();

110
gate.php
View File

@ -1,110 +0,0 @@
<?php
define('GAME',true);
include_once('_incl_data/__config.php');
include_once('_incl_data/class/__db_connect.php');
if( isset($_GET['md5']) ) {
$_GET['in'] = 1;
}
if( isset($_GET['in']) ) {
$_GET['ref'] = 7;
$login = $_GET['login'];
$pass = $_GET['pass'];
$md5 = md5( 'GATE_IN_DATA::'.$_GET['login'].$_GET['pass'].$_GET['exp'].$_GET['align'].$_GET['clan_prava'].$_GET['bithday'].$_GET['clan'].$_GET['sex'].$_GET['win'].$_GET['lose'].$_GET['nich'] );
if( $md5 != $_GET['md5'] ) {
unset($_GET['in']);
}else{
echo 'Нельзя создать т.к. не верный ключ и данные!';
}
if( $_GET['exp'] > 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'].'');
}
}
?>

View File

@ -6,11 +6,6 @@ if (!defined('GAME_VERSION')) {
require_once '_incl_data/autoload.php'; require_once '_incl_data/autoload.php';
} }
if (isset($_GET['time'])) {
echo time() . '<br>' . date('d.m.Y H:i:s', (int)$_GET['time']);
die();
}
header("Cache-Control: max-age=3600"); header("Cache-Control: max-age=3600");
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
@ -30,6 +25,7 @@ header("Cache-Control: max-age=3600");
flex-direction: column; flex-direction: column;
margin-top: 50px; margin-top: 50px;
} }
hr.incontent { hr.incontent {
width: 32%; width: 32%;
border: 1px #1c1c1c solid; border: 1px #1c1c1c solid;
@ -43,7 +39,7 @@ header("Cache-Control: max-age=3600");
<label for="first-name">Ваш Никнейм</label><br> <label for="first-name">Ваш Никнейм</label><br>
<input type="text" id="first-name" name="login" autocomplete="username"><br> <input type="text" id="first-name" name="login" autocomplete="username"><br>
<label for="last-name">Ваш Пароль</label><br> <label for="last-name">Ваш Пароль</label><br>
<input type="password" id="last-name" name="psw" autocomplete="current-password"> <input type="password" id="last-name" name="password" autocomplete="current-password">
<p> <p>
<input type="submit" value="Войти в игру" class="btn btn-default"> <input type="submit" value="Войти в игру" class="btn btn-default">
</form> </form>

View File

@ -3,6 +3,8 @@
/* @var $u User */ /* @var $u User */
use Core\Config; use Core\Config;
use Core\Db;
use Core\TOTP;
use User\Email; use User\Email;
use User\Password; use User\Password;
@ -14,23 +16,18 @@ $password = new Password($u->info);
$email = new Email($u->info); $email = new Email($u->info);
$status = null; $status = null;
if ($_POST['oldpsw2']) { // remove psw2 if ($_POST['removetotp']) {
if (password_verify((int)$_POST['oldpsw2'], $u->info['pass2'])) { // Удаление ключа ТОТР
$u->info['pass2'] = $password->changeSecond(null)['pass2']; $u->info['totp'] = '';
$status = "<b style='color: darkolivegreen'>Второй пароль выключен.</b><br>"; Db::sql('update users set totp = ? where id = ?', [$u->info['totp'], $u->info['id']]);
} else { $status = "<b style='color: darkolivegreen'>Секретный ключ удалён.</b><br>";
$status = "<b style='color: red'>Введен не верный второй пароль!</b><br>";
}
} }
if ($_POST['num_count']) { //add psw2 if ($_POST['newtotp']) {
$arr = $password->changeSecond((int)$_POST['num_count']); // Создание ключа ТОТР
$status = "<b style='color: red'>Второй пароль: {$arr['pass2']}.<br> $u->info['totp'] = TOTP::otpSecret($u->info['id']);
Запомните или запишите, т.к. он не высылается на email и его нельзя как-либо узнать. Db::sql('update users set totp = ? where id = ?', [$u->info['totp'], $u->info['id']]);
Потеряв второй пароль, вы потеряете персонажа!<br> $status = "<b style='color: darkolivegreen'>Секретный ключ создан.</b><br>";
Этот пароль выслан на ваш email.<br>
</b><br>";
$u->info['pass2'] = $arr['hash'];
} }
if ( if (
@ -66,7 +63,7 @@ if (
} }
?> ?>
<form action="main.php?security" method="post" id="security"></form> <form action="/main.php?security" method="post" id="security"></form>
<div> <div>
<h3>Настройки безопасности</h3> <h3>Настройки безопасности</h3>
@ -180,41 +177,18 @@ if (
</TABLE> </TABLE>
</FIELDSET> </FIELDSET>
<FIELDSET> <FIELDSET>
<LEGEND><B> Второй уровень защиты </B></LEGEND> <LEGEND><B> TOTP </B></LEGEND>
Настоятельно рекомендуем включить второй уровень защиты.<BR> TOTP (Time-based One-Time Password) - это метод двухфакторной аутентификации, который генерирует одноразовый пароль на основе текущего времени.
На компьютере может быть установлен клавиатурный шпион, который записывает все нажатия клавиш, таким Устанавливается для повышения безопасности вашего аккаунта, так как помогает защитить его от несанкционированного доступа.<br>
образом, Вы можете использовать TOTP приложения, такие как Google Authenticator или Authy, чтобы генерировать и отображать временные одноразовые пароли на вашем мобильном устройстве.
могут узнать ваш пароль.<BR> <br><br>
Возможно, в сети компьютеров установлен "сетевой снифер", перехватывающий все интернет пакеты, который легко <U>Будьте внимательны!</U> Секретный ключ генерируется только один раз и не подлежит восстановлению. Его можно только удалить или заменить новым.<br>
покажет все пароли. Чтобы обезопасить себя, вы можете установить своему персонажу второй пароль, который <?php if (!empty($u->info['totp'])): ?>
можно <br><b>Секретный ключ:</b>
вводить при помощи мышки (клавиатурным шпионом не перехватить) и который передается на игровой сервер в <pre>{$u->info['totp']}</pre><br><br>
зашифрованном виде, не поддающимся расшифровке ("сетевой снифер" не сможет перехватить его).<BR> <input form='security' type='submit' name='removetotp' value='Удалить секретный ключ' disabled><br>
<U>Будьте внимательны!</U> Второй пароль отправляется на email один раз,при установке второго уровня защиты!<BR> <?php endif; ?>
<input form='security' type='submit' name='newtotp' value='Создать новый секретный ключ' disabled><br>
<?php
if (!empty($u->info['pass2'])) {
echo "<BR><B>Второй пароль установлен.</B><BR><BR>
Введите второй пароль <INPUT TYPE=password NAME=oldpsw2 size=10 maxlength=8>
<INPUT form='security' TYPE=submit name=changepsw value=\"Выключить второй пароль\" onclick=\"return confirm('Выключить запрос второго пароля при входе в Бойцовский Клуб?')\">";
} else {
?>
Длина пароля:<BR>
<label>
<INPUT form="security" TYPE=radio NAME="num_count" value=4> 4 знака<BR>
</label>
<label>
<INPUT form="security" TYPE=radio NAME="num_count" checked value=6> 6 знаков<BR>
</label>
<label>
<INPUT form="security" TYPE=radio NAME="num_count" value=8> 8 знаков<BR>
</label>
<INPUT form="security" TYPE=submit name=changepsw value="Установить второй пароль"
onclick="return confirm('Система сама придумает вам второй пароль, он будет показан на этой странице, после того, как вы нажмете OK и продублирован на email, указанный при регистрации. Будьте внимательны.\nУстановить второй пароль?')">
<BR>
<?php
}
?>
</FIELDSET> </FIELDSET>
</div> </div>
</div> </div>