Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР #87, МАРТ 2006 г.

"Неслучайные" баги

eto’o

Хакер, номер #087, стр. 087-152-2


[общие идеи]

Первым делом надо продумать, где и каким образом мы будем размещать жуков. Их форма и содержание — отдельный разговор. Сейчас давай решим, в каком месте программы мы будем их прятать. Любая php-система обычно состоит из множества файлов. Всегда есть несколько файлов с описанием классов или функций - такие сценарии просто инклудятся скриптами, в которых используются описанные классы и процедуры. Наших жуков лучше всего прятать внутри именно файлов с описаниями функций, поскольку они, как правило, довольно здоровые, и отыскать вручную одну ядовитую строку - сложная штука.

Будет круто, если нам удастся обойтись без «хакерских» словечек вроде «include» и «system» :). Я думаю, лучше всего вписать в код программы не тупого жука вроде system($_GET[cmd]), а какую-то сложную для понимания логическую ошибку, которую автоматическими средствами отыскать никак нельзя. Об этом мы тоже поговорим, но сперва рассмотрим идеи несколько иного толка.

[ошибки сравнения]

Во многих скриптах есть места, где производится аутентификация пользователя. В общем случае делается примерно так. Выбирается из таблицы запись, соответствующая введенному пользователем логину, после чего смотрится, вернулась ли запись, и сравниваются введенный и оригинальный пароли (или хэши паролей). Ты, наверное, сейчас подумал, что я тебе сейчас расскажу об sql-injection. Но это совершенно не так. Первый наш трюк заключается в использовании оператора сравнения ==. Скажи, ты уверен, что знаешь, как он работает? Давай протестируем тебя. Подумай как следует и скажи, что вернет следующий код?

if(0==”aa1”) {return 1;} else {return 0;}

Большинство людей рассчитывают, что он вернет 0, так как ноль не равен строке “aa1”. А код вернет единицу. С точки зрения оператора ==, число 0 «равно» строке “aa1”. Дело все в том, что PHP, как язык без ярко выраженной типизации данных, предоставляет программистам большую свободу, но и награждает взамен некоторым геморроем. Так, при сравнении оператором == целого и строки, строка будет приведена к типу int и окажется нулем. Поэтому какую бы строку ты ни сравнивал с нулем оператором ==, она всегда будет «равна» нулю.

Эту фишку можно заюзать, чтобы внедрить в твою систему потаенную дверцу. Скажем, вот так:

if(ereg("^[0-9]$",$_GET[passwd])) $passwd=(int)$_GET[passwd]; else $passwd=$_GET[passwd];

if($_GET[login]=="user_name" && $passwd=="T9s8)jdy67") {

echo "hello";

}

В этом примере просто сравниваются переменные с жесткими значениями. Однако такой код выведет заветное «hello», вопреки ожиданиям, в двух случаях: если в поле passwd будет пароль (T9s8)jdy67) или… число 0.

Похожий баг, кстати, недавно светился в багтрак-лентах. Его нашли, естественно, в phpBB, если я ничего не путаю.

[шутки с eval]

Неплохой способ спрятать внутри кода бэкдор — заяюзать функцию eval. Как ты знаешь, эта функция занимается тем, что выполняет переденный ей php-код. Код передается в виде обыкновенной строки, что-то вроде того:

Назад на стр. 087-152-1  Содержание  Вперед на стр. 087-152-3