ENG GER GER pl
PCproxy mail RSS




Регистрация | Вход

Меню сайта

Форма входа

Последние новости

Наши друзья

Наш опрос
Вы часто бываете на ITsecure.org.ua?
Всего ответов: 453

Наши друзья



Главная » Статьи » Безопасность » Защищаем |

IT безопасность IT безопасность Windows 9x/NT Защищаем
Unix/Linux Безопасность в Internet Криптография Другое



Неслучайные числа: Ultimate-баг движка PHP
Затравка

В PHP 4 и PHP 5 <= 5.2.0 присутствует следующая недоработка: любой seed, вызываемый mt_srand(), либо присваиваемый автоматически, имеет разрядность всего 31 бит, так как последний бит всегда устанавливается равным одному. Таким образом, для брутфорса семени нам нужно перебрать 2147483648 комбинаций. Уже лучше, но все-таки для эксплуатации такого бага времени потратить придется немало. В последующих версиях PHP эту недоработку залатали, но оставили другую. В PHP 4 и PHP <= 5.2.5 всякий раз, когда 26 последних бит становятся равными нулю, seed также принудительно становится равным нулю (либо 1, в зависимости от установки принудительных бит системой). Это правило действует для 32‑битных систем. На 64‑битных системах ситуация чуть лучше — сид просто становится 24‑битным.
Принудительная генерация seed

Выше я раскрыл одну сторону бага, а теперь — самое вкусное! Если ты любишь покопаться в сорцах бесплатных PHP-цмсок, то, наверняка, знаешь, что их кодеры очень любят инициализировать генераторы псевдослучайных чисел при помощи функций srand() и mt_srand():

mt_srand(time());

mt_srand((double) microtime() * 100000);

mt_srand((double) microtime() * 1000000);

mt_srand((double) microtime() * 10000000);

Такая инициализация не криптоустойчива, потому что:

1. функция time() не является случайной. Ее значение будет известно хакеру. Даже если админы намеренно установят локальное время сервера ошибочным, — его точное значение всегда будет возвращаться в HTTP-заголовках;

2-4. первое слагаемое (double) microtime() будет равно 0, либо 1, а второе — соответственно, от 100000 до 10000000. В итоге, получаем для брутфорса все то же число: от 100000 до 10000000 значений. При 1000000 значений процесс брутфорса сида займет всего несколько секунд!
Keep-alive соединения

Материал был бы бесполезным, если бы не тот факт, что Keep-alive HTTP-соединения всегда обслуживаются одним и тем же процессом на удаленном веб-сервере! Это означает, что seed, сгенерированный единожды на одном домене этого сервера, будет таким же и для другого домена на этом сервере! То есть, если какой-либо php-скрипт выведет сгенерированные случайные числа, мы сможем определить по ним сид, — и остальные случайные числа генерить на его основе! Правило, как ты уже понял, относится не только к одному хосту, но и ко всем хостам на удаленном сервере. Нельзя не заметить, что это действует только для PHP, запущенного как модуль Апача, а вот для cgi генераторы псевдослучайных чисел всегда будут инициализироваться заново. Но cgi, скорее, исключение из правил, так что не будем брать его в расчет. Кстати, Стефан Эссер подсказал здесь хинт. Если ты хостишься на одном сервере с жертвой, то можешь принудительно запустить скрипт на своем хосте с srand(0) или mt_srand(0). Сид у жертвы будет, соответственно, 0 :).
От теории к практике

Настало время обобщить все сказанное. Итак, запусти следующий скрипт:

<?php

mt_srand(31337);

print mt_rand()."\n";

print mt_rand()."\n";

print mt_rand()."\n";

print mt_rand();

?>

При каждом выводе mt_rand() тебе будут показаны одинаковые числа, так как seed везде один и тот же. Теперь запусти другой скрипт:

<?php

print rand()."\n";

print rand();

?>

Допустим, ты получил числа 11834 и 2795. Снова запускай данный код, но теперь в качестве сида укажи первое получившееся число:

<?php

srand(11834);

print rand()."\n";

print rand();

?>

В итоге ты получишь числа 2795 и 28744. Обрати внимание на предыдущий результат :). Эту особенность генератора обнаружил raz0r (ссылки на его адвисори смотри в конце статьи).
Cross Application Attacks

Некоторые веб-приложения сами инициализируют seed, а затем выводят полученные на его основе псевдослучайные числа конечному пользователю. Пример такого приложения — phpBB2. Вот код из search.php:

mt_srand ((double) microtime() * 1000000);

$search_id = mt_rand();

Проблема в этом примере заключается в том, что количество комбинаций составляет всего 1000000, плюс в html-исходнике страницы мы увидим вывод значения $search_id. Как ты уже понял, зная сгенерированное случайное число, мы, фактически, знаем и seed! Тем более, на сравнение 1000000 результатов работы генератора с полученным $search_id уйдет совсем немного времени. Простор для действий тут очень большой. Можно создать rainbow-таблицы со всего лишь 1000000 значений.

Ситуация верна для PHP 5 => 5.2.1. А в случае с PHP 4 и PHP 5 <= 5.2.0 она становится еще лучше! Для них количество вариантов сокращается почти в два раза, то есть до 2 в 19 степени. Причину я описал в первых абзацах. Ты спросишь, почему же в этом примере утечка сгенерированного числа является проблемой безопасности? Вот почему:
Запуск генератора случайных чисел влияет не только на представленный в примере phpBB2, но и на остальные веб-приложения, установленные на этом сервере;
Псевдослучайные числа, сгенерированные на основе предыдущего seed, будут предсказуемыми;
Остальные приложения на этом же сервере могут создавать пароли, сессии и т.д. на основе полученного ранее seed.

Теперь рассмотрим ситуацию, когда phpBB2 и любимый мной WordPress установлены на одном сервере. Отталкиваясь от полученной выше информации, Стефан описывает такой алгоритм атаки на веб-приложения (Cross Application Attacks):
Запускаем keep-alive соединение к поиску phpBB2 и ищем любое часто встречающееся слово, вроде «a», «the» и т.д;
Если запрос вернул более 30 результатов поиска, то смотрим html-исходник страницы. В ссылке на следующую страницу форум должен вывести случайное число в параметре search_id, — запоминаем его;
Запускаем брутфорс по найденному псевдослучайному числу из search_id для определения изначального seed. Для этого raz0r предлагает функцию:

function search_seed($rand_num) {

$max = 1000000;

for($seed=0;$seed<=$max;$seed++){

mt_srand($seed);

$key = mt_rand();

if($key==$rand_num) return $seed;

}

return false;

}

4. Запускаем mt_srand() с полученным значением seed и отбрасываем первое число — тот самый search_id;
В том же keep-alive соединении отправляем запрос на смену пароля админа блога;
На основе полученного сида генерируем случайное число для активационного ключа смены пароля, который блог должен был выслать на мыло админа;
Снова все в том же keep-alive соединении переходим по сгенерированной эксплойтом активационной ссылке. Это должно привести к смене пароля администратора;
Генерируем пароль той же функцией, с помощью которой получили активационный ключ, и заходим в админскую часть WordPress :). Кстати, если на сервере-жертве стоит PHP 4 или PHP 5 <= 5.2.0, то желательно генерировать псевдослучайные числа на той же версии PHP; то же самое относится и к PHP 5 >= 5.2.1. Эксплойт, основанный на этом алгоритме, написал все тот же raz0r.
часто встречающееся слово, вроде «a», «the» и т.д; Ссылку смотри ниже.
Снова WordPress

Попробуем подойти к описанной уязвимости с другой стороны и рассмотреть последний эксплойт для WordPress, названный Wordpress 2.6.1 (SQL Column Truncation) Admin Takeover Exploit. Алгоритм эксплойта основан сразу на двух глобальных уязвимостях: на, собственно, предсказуемости псевдослучайных чисел и на SQL Column Truncation — усечении данных в MySQL.

Сделаю небольшое отступление и расскажу об этом пресловутом усечении данных в мускуле. Уже известный тебе Стефан Эссер опубликовал в своем блоге очередную advisory, посвященную новой уязвимости. Она связана с особенностями сравнения строк и автоматического усечения данных в MySQL. Известно, что любой столбец в таблице имеет определенную длину. Допустим, существует поле varchar(60) (как в WordPress <= 2.6.1 для логина пользователя). Что будет, если записать в это поле любое значение, которое превысит обозначенные 60 символов? Лишние символы отсекутся! В поле останутся первые 60 символов, которые мы попытались туда записать. Дальше. Если у нас есть поле в базе данных со значением «admin», и мы попытаемся сравнить это значение, например, с «admin » (admin и 2 пробела), то мускул это проделает и скажет, что поля равны. Эта особенность MySQL работает в дефолтной конфигурации, — что открывает новый вектор атаки на веб-приложения!

Подробнее о уязвимости советую прочитать по адресам, указанным в конце статьи. Но вернемся к нашему эксплойту.

Принцип его работы изложен ниже:
Регистрируем нового пользователя с логином admin[55 пробелов]x. Далее конечный символ «x» отсекается, и в базе мы получаем пользователя admin с 55 пробелами, что для мускула фактически будет равно просто логину «admin»;
Запрашиваем линк сброса пароля на свое мыло и получаем уникальный ключ из параметра key, который был сгенерирован функцией mt_rand();
Сбрасываем пароль администратора с полученным ключом. В итоге, новый пароль уйдет только на мыло админа;
На основе полученного ранее ключа ищем сид для вновь сгенерированного пароля. Тут можно сгенерировать rainbow-таблицы для поиска, которые будут весить примерно 4294967296 (строк, возможных значений сида, номер строки=seed) * 20 (количество символов кея для смены пароля) = 85899345920 байт или 80 гигабайт. Для версий PHP 4, PHP 5 <= 5.2.0 и PHP 5 >= 5.2.1 нужно генерировать отдельные таблицы. В эксплойте также есть возможность искать seed и без применения радужных таблиц, но процесс займет очень долгое время. Делается это следующей функцией:

function getseed($resetkey) {

echo "[-] calculating rand seed for $resetkey (this will take a looong time)";

$max = pow(2,(32‑BUGGY));

for($x=0;$x<=$max;$x++) {

$seed = BUGGY ? ($x << 1) + 1 : $x;

mt_srand($seed);

$testkey = wp_generate_password(20,false);

if($testkey==$resetkey) {

echo "o\n"; return $seed;

}

if(!($x % 10000)) echo ".";

}

echo "\n";

return false;

}

Параметр BUGGY — не что иное, как вышеописанный баг, когда 26 последних бит сида становятся равными нулю, то есть число всех значений для перебора будет равным 2 в 31 степени. Вычисляется бажность генератора так:

mt_srand(2); $a = mt_rand(); mt_srand(3); $b = mt_rand();

define('BUGGY', $a == $b);

Изучив исходник этого эксплойта, ты сможешь более подробно вникнуть в суть уязвимостей, найденных Стефаном Эссером.

Пока что эксплойты на вышеописанных багах не очень распространены. Я думаю, это из-за того, что для многих эксплуатация уязвимостей генераторов псевдослучайных чисел может показатьсячересчур сложной. На самом деле, это не так. Хакеру я посоветовал бы изучить исходники эксплойтов, ссылки на которые есть в сноске, и написать на основе полученной информации свои мегапробивные релизы. А для админов и просто юзеров — обновить свой PHP до последней версии и поставить Suhosin-патч от Стефана Эссера.

Good luck!

Ссылки

http://www.suspekt.org/2008/08/17/mt_srand-and-not-sorandom-numbers — оригинальное advisory Стефана Эссера на тему mt_rand()
http://www.suspekt.org/2008/08/18/mysql-and-sql-columntruncation-vulnerabilities — MySQL and SQL Column Truncation Vulnerabilities
http://milw0rm.com/exploits/6421 — Wordpress 2.6.1 (SQL Column Truncation) Admin Takeover Exploit
http://raz0r.name/wp-content/uploads/2008/08/wp1.html — Wordpress 2.5 <= 2.6.1 through phpBB2 Reset Admin Password Exploit
http://raz0r.name/articles/predskazyvaem-sluchajnye-chisla-v-php — исследование raz0r’а на тему предсказуемости случайных чисел в mt_rand()
http://raz0r.name/vulnerabilities/sql-column-truncation-security — исследование raz0r’а на тему усечения данных в MySQL
http://raz0r.name/articles/magiya-sluchajnyx-chisel-chast-2 — исследование raz0r’а на тему предсказуемости случайных чисел в rand()
http://raz0r.name/vulnerabilities/uyazvimosti-v-simple-machinesforum — уязвимости SMF на основе предсказуемости случайных чисел.

Источник

Категория: Защищаем | Добавил: sepos (16.01.2009) | Автор: sepos
Просмотров: 1312 | Рейтинг: 5.0/2 |
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Реклама на сайте

Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0

Наши друзья

Счетчики
  • Каталог Луганских сайтов
  • МЕТА - Украина. Рейтинг сайтов
  • Rambler's Top100
Ваш IP: 216.73.216.165

При полном или частичном копировании материалов с сайта, ссылка на ITsecure.org.ua обязательна!
ITsecure.org.ua ©2008-2025