Форум АНТИЧАТ

Форум АНТИЧАТ (https://forum.antichat.xyz/index.php)
-   Песочница (https://forum.antichat.xyz/forumdisplay.php?f=189)
-   -   logintoken и попытка брута moodl'a через burp suite и thc hydra (https://forum.antichat.xyz/showthread.php?t=482064)

1fort23 06.12.2020 18:18

Можно ли узнать пароль от аккаунта?

В BS имеется строка logintoken. Есть подозрение, что из за нее не выходит узнать правильность ввода данных. Через гидру так же, 0 правильных паролей..

Есть мысли? На что обратить внимание при бруте и реально ли это сделать? (скриншот bs кинул)

fandor9 07.12.2020 13:32

Цитата:

Сообщение от 1fort23
1fort23 said:

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

Начиная с версий 3.1.15, 3.3.9, 3.4.6, 3.5.3, 3.6.0 используется logintoken, как дополнительная защита CSRF от атак. Вот тут в функции get_login_token вы видите как генерируется токен,

.SpoilerTarget" type="button">Spoiler: get_login_token

PHP код:

PHP:
[
COLOR="#000000"][COLOR="#0000BB"][/COLOR][COLOR="#FF8000"]/**
* 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.
*/
[/COLOR][COLOR="#007700"]public static function[/COLOR][COLOR="#0000BB"]get_login_token[/COLOR][COLOR="#007700"]() {
global[/COLOR][COLOR="#0000BB"]$CFG[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$SESSION[/COLOR][COLOR="#007700"];

[/
COLOR][COLOR="#0000BB"]$state[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]false[/COLOR][COLOR="#007700"];

if (!isset([/COLOR][COLOR="#0000BB"]$SESSION[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]logintoken[/COLOR][COLOR="#007700"])) {
[/
COLOR][COLOR="#0000BB"]$SESSION[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]logintoken[/COLOR][COLOR="#007700"]= [];
}

if ([/COLOR][COLOR="#0000BB"]array_key_exists[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]self[/COLOR][COLOR="#007700"]::[/COLOR][COLOR="#0000BB"]$logintokenkey[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$SESSION[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]logintoken[/COLOR][COLOR="#007700"])) {
[/
COLOR][COLOR="#0000BB"]$state[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]$SESSION[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]logintoken[/COLOR][COLOR="#007700"][[/COLOR][COLOR="#0000BB"]self[/COLOR][COLOR="#007700"]::[/COLOR][COLOR="#0000BB"]$logintokenkey[/COLOR][COLOR="#007700"]];
}
if (empty([/COLOR][COLOR="#0000BB"]$state[/COLOR][COLOR="#007700"])) {
[/
COLOR][COLOR="#0000BB"]$state[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]self[/COLOR][COLOR="#007700"]::[/COLOR][COLOR="#0000BB"]create_login_token[/COLOR][COLOR="#007700"]();
}

[/
COLOR][COLOR="#FF8000"]// Check token lifespan.
[/COLOR][COLOR="#007700"]if ([/COLOR][COLOR="#0000BB"]$state[/COLOR][COLOR="#007700"][[/COLOR][COLOR="#DD0000"]'created'[/COLOR][COLOR="#007700"]] [/COLOR][COLOR="#0000BB"]sessiontimeout[/COLOR][COLOR="#007700"])) {
[/
COLOR][COLOR="#0000BB"]$state[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]self[/COLOR][COLOR="#007700"]::[/COLOR][COLOR="#0000BB"]create_login_token[/COLOR][COLOR="#007700"]();
}

[/
COLOR][COLOR="#FF8000"]// Return the current session login token.
[/COLOR][COLOR="#007700"]if ([/COLOR][COLOR="#0000BB"]array_key_exists[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#DD0000"]'token'[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$state[/COLOR][COLOR="#007700"])) {
return[/COLOR][COLOR="#0000BB"]$state[/COLOR][COLOR="#007700"][[/COLOR][COLOR="#DD0000"]'token'[/COLOR][COLOR="#007700"]];
} else {
return[/COLOR][COLOR="#0000BB"]false[/COLOR][COLOR="#007700"];
}
}[/COLOR][/COLOR

а вот собственно и сама функция authenticate_user_login проверки данных.

.SpoilerTarget" type="button">Spoiler: authenticate_user_login

PHP код:

PHP:
[
COLOR="#000000"][COLOR="#0000BB"][/COLOR][COLOR="#FF8000"]/**
* 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
*/
[/COLOR][COLOR="#007700"]function[/COLOR][COLOR="#0000BB"]authenticate_user_login[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$username[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$password[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$ignorelockout[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]false[/COLOR][COLOR="#007700"], &[/COLOR][COLOR="#0000BB"]$failurereason[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]null[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$logintoken[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]false[/COLOR][COLOR="#007700"]) {
global[/COLOR][COLOR="#0000BB"]$CFG[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$DB[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$PAGE[/COLOR][COLOR="#007700"];
require_once([/COLOR][COLOR="#DD0000"]"[/COLOR][COLOR="#0000BB"]$CFG[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]libdir[/COLOR][COLOR="#DD0000"]/authlib.php"[/COLOR][COLOR="#007700"]);

if ([/COLOR][COLOR="#0000BB"]$user[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]get_complete_user_data[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#DD0000"]'username'[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$username[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$CFG[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]mnet_localhost_id[/COLOR][COLOR="#007700"])) {
[/
COLOR][COLOR="#FF8000"]// we have found the user

[/COLOR][COLOR="#007700"]} else if (!empty([/COLOR][COLOR="#0000BB"]$CFG[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]authloginviaemail[/COLOR][COLOR="#007700"])) {
if ([/COLOR][COLOR="#0000BB"]$email[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]clean_param[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$username[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]PARAM_EMAIL[/COLOR][COLOR="#007700"])) {
[/
COLOR][COLOR="#0000BB"]$select[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#DD0000"]"mnethostid = :mnethostid AND LOWER(email) = LOWER(:email) AND deleted = 0"[/COLOR][COLOR="#007700"];
[/
COLOR][COLOR="#0000BB"]$params[/COLOR][COLOR="#007700"]= array([/COLOR][COLOR="#DD0000"]'mnethostid'[/COLOR][COLOR="#007700"]=>[/COLOR][COLOR="#0000BB"]$CFG[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]mnet_localhost_id[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#DD0000"]'email'[/COLOR][COLOR="#007700"]=>[/COLOR][COLOR="#0000BB"]$email[/COLOR][COLOR="#007700"]);
[/
COLOR][COLOR="#0000BB"]$users[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]$DB[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]get_records_select[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#DD0000"]'user'[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$select[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$params[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#DD0000"]'id'[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#DD0000"]'id'[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]2[/COLOR][COLOR="#007700"]);
if ([/COLOR][COLOR="#0000BB"]count[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$users[/COLOR][COLOR="#007700"]) ===[/COLOR][COLOR="#0000BB"]1[/COLOR][COLOR="#007700"]) {
[/
COLOR][COLOR="#FF8000"]// Use email for login only if unique.
[/COLOR][COLOR="#0000BB"]$user[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]reset[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$users[/COLOR][COLOR="#007700"]);
[/
COLOR][COLOR="#0000BB"]$user[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]get_complete_user_data[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#DD0000"]'id'[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$user[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]id[/COLOR][COLOR="#007700"]);
[/
COLOR][COLOR="#0000BB"]$username[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]$user[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]username[/COLOR][COLOR="#007700"];
}
unset([/COLOR][COLOR="#0000BB"]$users[/COLOR][COLOR="#007700"]);
}
}

[/
COLOR][COLOR="#FF8000"]// Make sure this request came from the login form.
[/COLOR][COLOR="#007700"]if (!\[/COLOR][COLOR="#0000BB"]core[/COLOR][COLOR="#007700"]\[/COLOR][COLOR="#0000BB"]session[/COLOR][COLOR="#007700"]\[/COLOR][COLOR="#0000BB"]manager[/COLOR][COLOR="#007700"]::[/COLOR][COLOR="#0000BB"]validate_login_token[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$logintoken[/COLOR][COLOR="#007700"])) {
[/
COLOR][COLOR="#0000BB"]$failurereason[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]AUTH_LOGIN_FAILED[/COLOR][COLOR="#007700"];

[/
COLOR][COLOR="#FF8000"]// Trigger login failed event (specifying the ID of the found user, if available).
[/COLOR][COLOR="#007700"]\[/COLOR][COLOR="#0000BB"]core[/COLOR][COLOR="#007700"]\[/COLOR][COLOR="#0000BB"]event[/COLOR][COLOR="#007700"]\[/COLOR][COLOR="#0000BB"]user_login_failed[/COLOR][COLOR="#007700"]::[/COLOR][COLOR="#0000BB"]create[/COLOR][COLOR="#007700"]([
[/
COLOR][COLOR="#DD0000"]'userid'[/COLOR][COLOR="#007700"]=> ([/COLOR][COLOR="#0000BB"]$user[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]id[/COLOR][COLOR="#007700"]??[/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"]),
[/
COLOR][COLOR="#DD0000"]'other'[/COLOR][COLOR="#007700"]=> [
[/
COLOR][COLOR="#DD0000"]'username'[/COLOR][COLOR="#007700"]=>[/COLOR][COLOR="#0000BB"]$username[/COLOR][COLOR="#007700"],
[/
COLOR][COLOR="#DD0000"]'reason'[/COLOR][COLOR="#007700"]=>[/COLOR][COLOR="#0000BB"]$failurereason[/COLOR][COLOR="#007700"],
],
])->[/COLOR][COLOR="#0000BB"]trigger[/COLOR][COLOR="#007700"]();

[/
COLOR][COLOR="#0000BB"]error_log[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#DD0000"]'[client '[/COLOR][COLOR="#007700"].[/COLOR][COLOR="#0000BB"]getremoteaddr[/COLOR][COLOR="#007700"]().[/COLOR][COLOR="#DD0000"]"][/COLOR][COLOR="#0000BB"]$CFG[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]wwwroot[/COLOR][COLOR="#DD0000"]Invalid Login Token:[/COLOR][COLOR="#0000BB"]$username[/COLOR][COLOR="#DD0000"]"[/COLOR][COLOR="#007700"].[/COLOR][COLOR="#0000BB"]$_SERVER[/COLOR][COLOR="#007700"][[/COLOR][COLOR="#DD0000"]'HTTP_USER_AGENT'[/COLOR][COLOR="#007700"]]);
return[/COLOR][COLOR="#0000BB"]false[/COLOR][COLOR="#007700"];
}
.....
[/
COLOR][/COLOR

При этом опять-таки вызывается функция validate_login_token

.SpoilerTarget" type="button">Spoiler: validate_login_token

PHP код:

PHP:
[
COLOR="#000000"][COLOR="#0000BB"][/COLOR][COLOR="#FF8000"]/**
* 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.
*/
[/COLOR][COLOR="#007700"]public static function[/COLOR][COLOR="#0000BB"]validate_login_token[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$token[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]false[/COLOR][COLOR="#007700"]) {
global[/COLOR][COLOR="#0000BB"]$CFG[/COLOR][COLOR="#007700"];

if (!empty([/COLOR][COLOR="#0000BB"]$CFG[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]alternateloginurl[/COLOR][COLOR="#007700"]) || !empty([/COLOR][COLOR="#0000BB"]$CFG[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]disablelogintoken[/COLOR][COLOR="#007700"])) {
[/
COLOR][COLOR="#FF8000"]// 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.
[/COLOR][COLOR="#007700"]return[/COLOR][COLOR="#0000BB"]true[/COLOR][COLOR="#007700"];
}
if ([/COLOR][COLOR="#0000BB"]$token[/COLOR][COLOR="#007700"]===[/COLOR][COLOR="#0000BB"]false[/COLOR][COLOR="#007700"]) {
[/
COLOR][COLOR="#FF8000"]// 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.
[/COLOR][COLOR="#007700"]return[/COLOR][COLOR="#0000BB"]true[/COLOR][COLOR="#007700"];
}

[/
COLOR][COLOR="#0000BB"]$currenttoken[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]self[/COLOR][COLOR="#007700"]::[/COLOR][COLOR="#0000BB"]get_login_token[/COLOR][COLOR="#007700"]();

[/
COLOR][COLOR="#FF8000"]// We need to clean the login token so the old one is not valid again.
[/COLOR][COLOR="#0000BB"]self[/COLOR][COLOR="#007700"]::[/COLOR][COLOR="#0000BB"]create_login_token[/COLOR][COLOR="#007700"]();

if ([/COLOR][COLOR="#0000BB"]$currenttoken[/COLOR][COLOR="#007700"]!==[/COLOR][COLOR="#0000BB"]$token[/COLOR][COLOR="#007700"]) {
[/
COLOR][COLOR="#FF8000"]// Fail the login.
[/COLOR][COLOR="#007700"]return[/COLOR][COLOR="#0000BB"]false[/COLOR][COLOR="#007700"];
}
return[/COLOR][COLOR="#0000BB"]true[/COLOR][COLOR="#007700"];
}
[/
COLOR][/COLOR

в которой проверяется сам login_token, но при этом мы видим что если параметр login_token будет иметь значение false (которое он будет получаеть по дефолту), то функция будет возврашать true и мы обходим функцию проверки токена. В общем если я не ошибаюсь, то если убрать его совсем из POST-запроса, то он дефолтом будет получать значение false, при этом обходится проверка этого самого токена и перебор должен идти. Если же оставить значение login_token, то он будет действительнен в течение 8 часов и обновлятся при каждой проверке данных.

1fort23 07.12.2020 19:11

Как понял, disablelogintoken поможет обойти это дело смотря по коду.

Но вот проблема во времени.. Hydra справляется шустрее при подборе. Как я понимаю, для нее следует скачивать отдельные lib файлы и прописывать другую команду?

fandor9 07.12.2020 20:32

Цитата:

Сообщение от 1fort23
1fort23 said:

Как понял, disablelogintoken поможет обойти это дело смотря по коду.
Но вот проблема во времени.. Hydra справляется шустрее при подборе. Как я понимаю, для нее следует скачивать отдельные lib файлы и прописывать другую команду?

ну если у вас есть возможность изменять конфиг, то тогда мне не понятно о чём вопрос. Но в принципе да, если вы можете прописать в конфиге

Код:

Code:
disablelogintoken = true

то тогда проверка тоже не выполняется.

Я не знаю что у вас не хватает, но в принципе что-то вроде

Код:

Code:
hydra -l  -P /usr/share/wordlists/rockyou.txt  https-post-form "/day/login/index.php:username=^USER^&password=^PASS^:F=Login failed!"

должно работать

1fort23 07.12.2020 21:27

Пример, который пробовал я:

hydra -l -P -o result.log –V –s 443 https-post-form "/day/login/index.php:username=^USER^&password=^PASS^:F=”

Даже при таком раскладе выдает 0 действительных паролей.


Время: 20:56