Переустановка пароля админа и угадывание его
Уязвимы все версии.
Для эксплуатации нужно:
Админское мыло(по умолчанию отображается в профиле)
много времени.
В чем суть:
/components/registration/frontend.php
PHP код:
$sql = "SELECT * FROM cms_users WHERE email = '$email' LIMIT 1";
$result = $inDB->query($sql) ;
if ($inDB->num_rows($result)>0){
$usr = $inDB->fetch_assoc($result);
$newpassword = substr(md5(microtime()), 0, 6);
$inDB->query("UPDATE cms_users SET password = '".md5($newpassword)."' WHERE id = ".$usr['id']) ;
$mail_message = $_LANG['HELLO'].', ' . $usr['nickname'] . '!'. "\n\n";
$mail_message = $_LANG['HELLO'].', ' . $usr['nickname'] . '!'. "\n\n";
$mail_message .= $_LANG['REMINDER_TEXT'].' "'.$inConf->sitename.'".' . "\n\n";
$mail_message .= $_LANG['OUR_PASS_IS_MD5'] . "\n";
$mail_message .= $_LANG['OUR_PASS_IS_MD5_TEXT'] . "\n\n";
$mail_message .= '########## '.$_LANG['YOUR_LOGIN'].': ' .$usr['login']. "\n\n";
$mail_message .= '########## '.$_LANG['YOUR_NEW_PASS'].': ' .$newpassword . "\n\n";
$mail_message .= $_LANG['YOU_CAN_CHANGE_PASS']."\n";
$mail_message .= $_LANG['IN_CONFIG_PROFILE'].': '. cmsUser::getProfileURL($usr['login']) . "\n\n";
$mail_message .= $_LANG['SIGNATURE'].', '. $inConf->sitename . ' ('.HOST.').' . "\n";
$mail_message .= date('d-m-Y (H:i)');
$inCore->mailText($email, $inConf->sitename.' - '.$_LANG['REMINDER_PASS'], $mail_message);
Этот скрипт восстанавливает пароль рассеяным юзерам. Но как он это делает.
1) Проверяет есть ли мыльник в бд.
2) Скрипт не церемонясь присваивает значение паролю равному первым шести символам хеша от значения, которое генерирует функция microtime().
Код:
Функция microtime() возвращает текущую метку времени с микросекундами. Эта функция
доступна только
на операционных системах, в которых есть системная функция gettimeofday().
При вызове без необязательного параметра, возвращается строка в формате "msec sec",
где sec - это количество секунд, прошедших с начала Эпохи
Unix (The Unix Epoch, 1 января 1970, 00:00:00 GMT), а msec - это дробная часть.
она генерирует что-то на подобии.
0.xxxxxx00 [1273589840]
где xxxxxx-доли секунды
то что в квадратных скобках-это количество секунд, прошедших с начала Эпохи Unix.
Как юзать уязвимость:
Отсылаем запрос на восстановление пароля и сниффаем пакет. смотрим в ответе на запрос дату.
Там что-то вроде.
Tue, 11 May 2010 20:39:23 GMT
узнаем на локальной машине сколько прошло с момента 1970, 00:00:00 GMT.
2) А вот микросекунды придется брутить, их мы никак не узнаем. Список
создаем вида
0.xxxxxx00 [время в секундах прошедшее от момента "Unix" до момента отправки запроса на восстановление пароля]
пример: 0.30001200 1273589840
всесто xxxxxx вставляем все возможные комбинации из цифр, их 1 млн. Затем преобразуем их к виду.
substr(md5(значение), 0, 6)
возвращаем мд5 каждого получившегося значения и отрезаем от хеша символы после шестого знака.
Пример: 1a512b
Получился словарь 1млн слов. Один из этих слов-сгенерированный пассворд. Брутим веб форму.
У меня на дедике многопоточный брут дает до 11 ппс.
1000000/11=90.909 - то есть в худшем случае пароль мы узнаем через сутки. Геморно, а че поделать. На количество попыток залогиниться ограничений не стоит в форме авторизации.
P.S. Оказывается секунда-это много.
Этот баг не яркий пример приятной эксплуатации. Но все же он ведет к успеху. Т.К. В сгенерированном большом словаре
100% содержится правильный пассворд. И если ничего не остается, как вариант можно юзать.
Нарушение криптостойкости паролей
еще этот баг открывает новую опасность. Сгенерированный пароль сразу попадает в бд. Что это дает? Допустим стянул ты пароль админа через sql inj. А он не расшифровывается, пароль трудный. Что мы делаем:
1) Переустанавливаем пароль той же фичей. Напоминаю пароль состоит из 6 символов, которые являются цифрами или буквами.
2) Стягиваем через sql inj md5 и расшифровываем уже сгенерированный пароль. (думаю пароль из 6 символов [букв и цифр] расшифровать не трудно)
все
Видео с примером использования уязвимости:
https://forum.antichat.ru/threadedpost2138119.html#post2138119