Авторизация в Ghtweb(5.1.3)

Martali

Путник
Пользователь
Сообщения
22
Розыгрыши
0
Репутация
0
Реакции
1
Баллы
75
Хроники
  1. Chaotic Throne: High Five
Исходники
Присутствуют
Сборка
jts 2018
Доброго времени суток.
Не могу разобраться, как работает связь обвязки Ghtweb 5.1.3 (взята с Github'a) и ява-сборки jts 2018 года. Сам логин и игровой сервер запущены и работают.
Развернул и настроил Ghtweb 5, отображает онлайн сервера, список игроков, топ ПВП/ПК.
Проблема с созданием аккаунта на сайте. После успешной регистрации, учётные данные принимаются сайтом. Стоит зайти на логин сервер, даже до выбора сервера, в ЛК на сайт уже не попасть.
Опытным путём и чтением результатов запроса в Гугл, причиной считаю разную генерацию хэшей БД сайта и логин сервера.
При авторизации на сайте хэш имеет такой вид: faf200037c7b4290662d57f0ee59a450 (поле hash_auth), на логин сервере — fEqNCco3Yq9h5ZUglD3CZJT4lBs=(поле password). После авторизации на логин сервере значение поле password становится вида — sha1:1000:BKUtFOSowxjReuJ2InqAesCMSOOmUo3q:RckmG3A/AGEG3TODiYTgsCWjz6+/UqyW и зайти в ЛК на сайте больше нельзя.
В настройках логин-сервера на ghtweb стоит тип шифрования sha1, в конфиге логин сервера, так же стоит sha1. Менял настройки на whirpool и в ght и в логин сервере. Поведение не поменялось, только в указанных выше полях поначалу меняется вид строки хэша.
Кто сталкивался с подобным, прошу подсказать, как исправить или куда копать?
Прикрепляю файл LoginForm, так как там в коде встречается passwordEncrypt


PHP:
 // Аккаунт на сервере найден
                if ($account) {
                    if ($account['password'] == $l2->passwordEncrypt($this->getPassword())) {
                        // Аккаунта на сайте нет, создаю его так как на сервере он уже есть
                        if (!$siteAccount) {
                            $email = null;

                            $columnNames = $l2->getDb()
                                ->getSchema()
                                ->getTable('accounts')
                                ->getColumnNames();

                            if (is_array($columnNames)) {
                                foreach ($columnNames as $column) {
                                    if (strpos($column, 'mail') !== false && isset($account[$column])) {
                                        $email = $account[$column];
                                    }
                                }
                            }

                            // В таблице с аккаунтами нет поля с Email. Нет смысла регать дальше аккаунт на сайте
                            if (!$email) {
                                throw new Exception('Аккаунт не найден');
                            }

                            // Создаю аккаунт на сайте
                            $userModel = Users::create($login, $email, Users::STATUS_ACTIVATED, $lsId, Users::ROLE_DEFAULT);
                            $userModel->save(false);

                            $siteAccountUserId = $userModel->user_id;
                        }

                        $found = true;
                    }
                }

                // Аккаунт не найден
                if (!$found) {
                    if ($siteAccountUserId) {
                        UsersAuthLogs::model()->addErrorAuth($siteAccountUserId);
                    }

                    $this->incrementBadAttempt();
                    $this->addError($attr, 'Неправильный Логин или Пароль.');
                }
            } catch (Exception $e) {
                $this->addError('login', $e->getMessage());
            }
        }
 

Вложения

  • LoginForm.zip
    2,4 КБ · Просмотры: 2
Martali, самое быстрое решение проблемы, это отладка скрипта modules/login/models/LoginForm.php после входа через LS
Если после входа в LS пароль изменяется, скорее всего надо будет добавить проверку пароля из логин сервере в ght. В коде выше, который вы скинули, пароль с логин сервера судя по всему подтягивается в переменную - $account['password'] далее идёт сравнение пароля с LS и текущего сырого пароля (переданный юзером), который хэшируется на лету здесь - $l2->passwordEncrypt($this->getPassword()). Функция хэширования находится в файл - /components/Lineage.php#L226

Нужно понять что генерирует jts в этой строке - sha1:1000:BKUtFOSowxjReuJ2InqAesCMSOOmUo3q:RckmG3A/AGEG3TODiYTgsCWjz6+/UqyW
Собственно в LoginForm.php добавить проверку на такую строку и генерацию сырого пароля под JTS на лету с сравнением

hash_auth / auth_hash - задействован чисто для куки и авторизации как я понял, на него можно не обращаться внимания, он роли не играет.
 
Спасибо, что перевели код, ElectroMyStyle. С программированием я на «Вы». Открыл свой Lineage.php, похоже, у меня несколько другой порядок строк. В прикреплённом фрагменте кода, как я понимаю, стоит проверка типа алгоритма? Могли бы взглянуть и сказать, что он делает?

Не совсем понял, насчёт изменения пароля. После пропадания возможности авторизоваться в ЛК сайта, связка логин-пароль продолжает работать для логин сервера. Я могу заходить, создавать чара, играть.
Я предполагаю, что из-за неправильного или отличающегося алгоритма проверки хэша на сайте от алгоритма в ЛС, сайт получает результат — неправильный пароль.

PHP:
#
/**
     * Шифровка пароля
     *
     * @param $password
     *
     * @return string
     */
    public function passwordEncrypt($password)
    {
        if ($this->config('password_type') == Ls::PASSWORD_TYPE_WHIRLPOOL) {
            return base64_encode(hash('whirlpool', $password, true));
        }

        return base64_encode(pack('H*', sha1(utf8_encode($password))));
    }
,


JavaScript:
# Автоматическое создание аккаунтов
    "AutoCreateAccounts" : "true",
    # Шаблон для логина и пароля
    "AccountTemplate" : "[A-Za-z0-9]{4,14}",
    "PasswordTemplate" : "[A-Za-z0-9]{4,16}",

    # Кеширование ключей
    "BlowFishKeys" : "20",
    "RSAKeyPairs" : "10",

    # Хеш для паролей
    # Поддерживаемые устаревшие методы, например sha1 (l2jserver), whirlpool (overworld)
    "LegacyPasswordHash" : "sha1",
 

Вложения

  • Lineage.zip
    3 КБ · Просмотры: 3
Martali, Со строками я в прошлый раз ошибся, там 209 строка, всё это я смотрел на . Судя по всему у JTS не просто sha1 крипт, вы же сами кидали пароль после входа на сервер через LS:
Код:
sha1:1000:BKUtFOSowxjReuJ2InqAesCMSOOmUo3q:RckmG3A/AGEG3TODiYTgsCWjz6+/UqyW
Как видите здесь несколько параметров и все они разделены ':'
1. sha1
2. 1000
3. BKUtFOSowxjReuJ2InqAesCMSOOmUo3q
4. RckmG3A/AGEG3TODiYTgsCWjz6+/UqyW

Посмотрел я исходники JTS, которые у меня есть и судя по ним я могу сказать, что они используют алгоритм шифрования пароля: PBKDF2WithHmacSHA1, собственно под этот алгоритм и надо переписать код авторизации в Ghtweb. Вот и всё решение вашего вопроса.
 
Martali, Со строками я в прошлый раз ошибся, там 209 строка, всё это я смотрел на . Судя по всему у JTS не просто sha1 крипт, вы же сами кидали пароль после входа на сервер через LS:
Код:
sha1:1000:BKUtFOSowxjReuJ2InqAesCMSOOmUo3q:RckmG3A/AGEG3TODiYTgsCWjz6+/UqyW
Как видите здесь несколько параметров и все они разделены ':'
1. sha1
2. 1000
3. BKUtFOSowxjReuJ2InqAesCMSOOmUo3q
4. RckmG3A/AGEG3TODiYTgsCWjz6+/UqyW

Посмотрел я исходники JTS, которые у меня есть и судя по ним я могу сказать, что они используют алгоритм шифрования пароля: PBKDF2WithHmacSHA1, собственно под этот алгоритм и надо переписать код авторизации в Ghtweb. Вот и всё решение вашего вопроса.
 
ElectroMyStyle, спасибо, что ответили и на другом форуме тоже =)) Переписывать код авторизации не моего уровня Кунг-фу.
Перешёл на 4 версию ghtweb'a. Там логика: один мастер аккаунт на сайте и в нём игровые аккаунты. Отключил авторегистрацию аккаунтов на ЛС. Теперь игровые аккаунты создаются в мастер аккаунте, там же можно поменять им пароль. Если попытаться присоединить аккаунт созданные через ЛС, то снова сообщение о несоответствии пароля. Хотя раньше, вроде, работала привязка аккаунтов.
В исходниках ЛС нашёл папку Crypt и файл LoginConfig.java, в них идёт шифрование, по-моему. Но не вижу явного указания на алгоритм PBKDF2WithHmacSHA1. Просто вы писали, что либо переписать регистрацию, авторизацию, восстановление пароля в ghtweb'e, либо в только авторизацию в JTS. Что на ваш взгляд проще реализовать?
 

Вложения

  • crypt.zip
    13,1 КБ · Просмотры: 2
  • LoginConfig.zip
    1,7 КБ · Просмотры: 0
Martali, сложно сказать что лучше и быстрее, кому как удобнее. По поводу PBKDF2WithHmacSHA1, в исходниках LS есть пакет клиента RequestAuthLogin.java собственно в нём происходит проверка пароля при авторизации и генерация нового хэша при автореге аккаунтов через LS. Там же можно найти строки с классом и функциями, которые генерируют хэш и проверяю его:
Код:
final String passwordHash = PBKDF2Hash.createHash(password);

boolean passwordCorrect = PBKDF2Hash.validatePassword(password, account.getPasswordHash());

По идее проще создать новый класс в исходниках JTS, который будет заниматься проверкой пароля и генерацией хэша при автореге. Вызвать трижды два реализованных метода в пакете RequestAuthLogin.java и вроде бы всё должно работать.

Вот примерный код класса, который надо поместить в исходники JTS - commons/src/main/java/org/mmocore/commons/crypt/SHA1Hash.java
Java:
package org.mmocore.commons.crypt;

import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.io.UnsupportedEncodingException;

public class SHA1Hash {
    public static String createHash(final String password)
        throws NoSuchAlgorithmException, UnsupportedEncodingException {
        MessageDigest digest = MessageDigest.getInstance("SHA-1");
        digest.reset();
        digest.update(password.getBytes("utf8"));
        String sha1 = String.format("%040x", new BigInteger(1, digest.digest()));
        return sha1;
    }
    
    public static boolean validatePassword(final String password, final String correctHash)
        throws NoSuchAlgorithmException, UnsupportedEncodingException {
        String newPasswordHash = createHash(password);
        return newPasswordHash.equals(correctHash);
    }
}
За код и возникшие последствия я не ручаюсь, я не Java программист, так что используйте всё на свой страх и риск.

Дальше идёте в пакет RequestAuthLogin.java подключаете класс:
Java:
import org.mmocore.commons.crypt.SHA1Hash;

Ищите название класса PBKDF2Hash заменяете на SHA1Hash. В теории это всё, осталось пересобрать исходники и должно работать с паролями движка Ghtweb, но это не точно :D
 
Обратите внимание, что данный пользователь заблокирован! Не совершайте с ним никаких сделок! Перейдите в его профиль, чтобы узнать причину блокировки.
Жосский оффтоп
Вот не могу понять людей которые берут такие вещи из шары тратят просто уйму времени на настройку за которое могли бы заработать денег и купить все что нужно
 
Отвечая на вопрос что проще и быстрее: добавить алогритм шифрования в конфиг для гхтвеб (назовем его foo), далее сделать elseif($method == 'foo') в encryptpassword где будет return hash_pbkdf2(); или какой там у вас алгоритм
 
Разве для этого не достаточно будет отредактировать данный метод, и добавить новый тип хеширования паролей?

Сюда добавить новый тип хеширования

Реализовать его в Lineage.php, а точнее, еще один if в котором описать алгоритм хеширования.
 
Разве для этого не достаточно будет отредактировать данный метод, и добавить новый метод хеширования паролей?
так я о чем и говорю ж
Код:
if ($this->config('password_type') == Ls::PASSWORD_TYPE_WHIRLPOOL) {
}
нам нужно завести новую константу в классе Ls, назвать её PASSWORD_TYPE_FOO к примеру и сделать elseif к ней, который вернет нужный нам хеш. Ну это если делать по уму. Можно вообще всё удалить и поставить return нужный хеш, тут каждый на что горазд
 
Martali, Со строками я в прошлый раз ошибся, там 209 строка, всё это я смотрел на . Судя по всему у JTS не просто sha1 крипт, вы же сами кидали пароль после входа на сервер через LS:
Код:
sha1:1000:BKUtFOSowxjReuJ2InqAesCMSOOmUo3q:RckmG3A/AGEG3TODiYTgsCWjz6+/UqyW
Как видите здесь несколько параметров и все они разделены ':'
1. sha1
2. 1000
3. BKUtFOSowxjReuJ2InqAesCMSOOmUo3q
4. RckmG3A/AGEG3TODiYTgsCWjz6+/UqyW

Посмотрел я исходники JTS, которые у меня есть и судя по ним я могу сказать, что они используют алгоритм шифрования пароля: PBKDF2WithHmacSHA1, собственно под этот алгоритм и надо переписать код авторизации в Ghtweb. Вот и всё решение вашего вопроса.
algorytm : iterations : salt : hash

Что-то подобное.
PHP:
$password = "password"; // Пароль.
$algorytm = "sha1"; // Алгоритм хеширования.
$iterations = 1000; // Количество итераций для формирования хеша.
$salt = "BKUtFOSowxjReuJ2InqAesCMSOOmUo3q";  // Случайно сгенерированная строка. 32 символа.
$hash = hash_pbkdf2($algorytm, $password, $salt, $iterations, 32); // Хеш. 32 символа.
$result =  $algorytm . ":" . $iterations . ":" . $salt . ":" . $hash; // Результат.

так я о чем и говорю ж
Код:
if ($this->config('password_type') == Ls::PASSWORD_TYPE_WHIRLPOOL) {
}
нам нужно завести новую константу в классе Ls, назвать её PASSWORD_TYPE_FOO к примеру и сделать elseif к ней, который вернет нужный нам хеш. Ну это если делать по уму. Можно вообще всё удалить и поставить return нужный хеш, тут каждый на что горазд
Да не совсем по уму, зачем выпиливать работающий функционал? Лучше расширить имеющийся.

upd: тупнул, всё верно=)))
 
В целом в JTS есть функция проверки хэша пароля sha1 (как минимум она работает, потому что там после проверки пароля с помощью pbkdf2, если зафейлилась проверка, тогда запускается цикл со старыми реализациями алгоритма хэширования, если один из алгоритмов совпал, тогда генерируется набор параметров с помощью pbkdf2 и эти же параметры записываются в БД, всё собственно как вы и описывали в первом посте: рега -> всё норм -> входите в игру и хэш пароля перезаписывается). Можно попробовать подтянуть проверку хэша sha1 из реализации движка, но это надо разбираться и переписывать логику авторизации, а вы не владеет программированием, хотя в текущий момент поднимать слитый сервак с исходником без знания программирования наверное тяжко и как вы будете его администрировать я хз.

Возможно, и правда будет проще переписать генерацию хэша в PHP, а точнее только проверку пароля при авторизации. Вот до чего я додумался. Можно просто в авторизации дописать логику - если в хэше есть : тогда разбиваем пароль на 4 параметра, проверяем переданный пароль с паролем с LS, если совпадает, тогда авторизуем юзера (просто переменной $found присвоить true. Эту логику можно глянуть в модуле - /modules/login/models/LoginForm.php. Скажу так, такой вариант имеет право на жизнь хоть это и лютый костыль :D Потому что при регистрации у вас будет пароль в виде sha1, после входа на сервак LS проверит хэш пароля в виде sha1 и сгенерирует свой хэш пароля в виде 4 параметров и перезапишет ваш sha1 в БД. Собственно при последующей авторизации через сайт, у вас уже будет логика проверки хэша пароля с 4 параметрами. При восстановлении пароля ghtweb запишет обычный sha1, на сайте и на сервере он же будет проверяться старым алгоритмом (если вы его не удалите) .При входе в игру с новым паролем LS перезапишет sha1 на свои 4 параметра и в игру вы собственно сможете входить. Скажем так это наверное самое быстрое решение проблемы: исходники сервера не надо пересобирать, просто дописать кусок кода в PHP с проверкой JTS пароля и можно играть :cool:
 
Что то состряпал, тестируйте и отписывайте:

1) Добавлен новый тип паролей: PBKDF2WithHmacSHA1
2) Переписан метод для хеширования паролей, теперь реагирует на PBKDF2WithHmacSHA1.
3) Добавлен метод для сравнения паролей checkHash(), сравнивает чистый пароль с хешированным. Если точнее, хеширует чистый пароль и сравнивает его с другим хешем. Метод необходим для корректной работы с PBKDF2WithHmacSHA1.
4) Везде в условных операторах где встречался метод passwordEncrypt(), то есть происходило сравнивание паролей, начал использоваться новый метод checkHash();

ВНИМАНИЕ! Необходимо тестирование, весь код писался вслепую.

Код с гита, с изменениями:
 
Mex-Vision,
Зачем кидать весь архив, не проще было бы просто патч сделать?)
 
Друзья, я не ожидал такого подгона. Огромное спасибо. Как писал ранее, вернулся на 4ую версию. Но сейчас создам ещё один контейнер и разверну ghtweb5 от Mex-Vision в нём. В субботу-воскресение дам обратную связь.
ElectroMyStyle, отдельная благодарность, что не прошёл мимо и не бросил после первого ответа. =)
 
Mex-Vision, поведение не поменялось =)
algorytm : iterations : salt : hash — может мне надо найти salt в исходниках jts сборки и его использовать в вашей правке?

Я использую proxmox-контейнеры для своих хостов. ОС Ubuntu 20.04 LTS без GUI. Когда ElectroMyStyle предложил отладку кода, я дочитался до установки xdebug пакета для моей версии Php. Но дальше этого дело не пошло. Если подскажите, какими инструментами можно собрать информацию для нахождения причины проблемы на этот раз, буду признателен.
 

Вложения

  • 1650664462910.png
    1650664462910.png
    143 КБ · Просмотры: 30
Есть 1 ошибка. Попробуйте перезалить данный файл в protected\components.

И посмотрите, изменяется ли пароль при входе в игру.

Mex-Vision, поведение не поменялось =)
algorytm : iterations : salt : hash — может мне надо найти salt в исходниках jts сборки и его использовать в вашей правке?

Я использую proxmox-контейнеры для своих хостов. ОС Ubuntu 20.04 LTS без GUI. Когда ElectroMyStyle предложил отладку кода, я дочитался до установки xdebug пакета для моей версии Php. Но дальше этого дело не пошло. Если подскажите, какими инструментами можно собрать информацию для нахождения причины проблемы на этот раз, буду признателен.
Соль генерируется своя для каждого пароля, именно поэтому она и храниться вместе с ним.
 
Mex-Vision, к сожалению, поведение не поменялось. После создания на сайте, учетные данные подходят к логин серверу. После входа в логин сервер, попасть в ЛК сайта нельзя.
Пароль в БД логин сервера становится:
sha1:1000:M41D3k4j8RbG52wZwjZQf4qVuRNJQ2Nd:G4s0uhWFYEj45nwjnbFXlO6+TCewwUJj
 
Назад
Сверху Снизу