Архив номеров
Форум
Контакты

Небезопасная безопасная Java

Безопасность Java-технологий оказалась решающим аргументом при продвижении в сферу корпоративных enterprise-приложений с конкурентом в лице C#. Однако пограничная полоса, отделяющая рекламный маркетинг от реальной жизни, оказалась довольно тернистой. Java многое обещает, но каждый раз откладывает исполнение своих обещаний на неопределенный срок. Рассмотрим модель безопасности Java на макро-, микроуровнях и проанализируем сильные и слабые стороны этой технологии.

В «девичестве» Java называлась Oak, что в переводе с английского означает «дуб» и символизирует вовсе не тупость, а мощь.

Историческая справка

Java возникла в результате внутреннего проекта Stealth Project (позднее переименованного в Green Project), начатого в 1990 г. компанией Sun. Его целью которого было создание языка программирования для своей же операционной системы Green Operating System, используемой для управления встраиваемыми устройствами и бытовой электроникой.

Идея создания языка принадлежит Патрику Наутону, уставшему программировать микроконтроллеры на Си/Си++, преодолевая несовместимость различных компиляторов вкупе с их привязанностью к конкретному железу, для «отвязки» от которого он решил сделать эффективную системно-независимую виртуальную машину. Позднее к нему присоединились Джеймс Гослинг (придумавший имя Oak, но оно оказалось уже зарезервированной торговой маркой) и Майк Шеридан. Они завершили создание языка в 1992 г. и продемонстрировали успешную работу Green OS на PDA-компьютере типа Star7.

В 1994 г. порядком разросшийся коллектив программистов предпринял попытку проникновения на рынок Web-приложений. Они сфокусировались на вопросах безопасности и подготовили специальную редакцию языка HotJava (в «девичестве» WebRunner), предназначенную для встраивания в браузеры и ставшую доступной для публичного скачивания в 1995-м. Попытка оказалась успешной. И с момента поддержки HotJava браузером Netscape Web-серфинг перестал быть безопасным, а сам браузер превратился в один из основных объектов хакерских атак. Несмотря на это, Java просочилась практически во все сферы рынка и сегодня встречается повсеместно: от сотовых телефонов до enterprise-серверов и суперкомпьютеров.

Внедрение Java-технологий обычно происходит под эгидой лозунгов о повышении безопасности, а все дыры списываются на ошибки реализации конкретных виртуальных машин. Однако истинная причина в том, что Java уязвима на концептуальном уровне. Впрочем, у конкурентов дела обстоят не лучше и основной соперник Java — С# содержит еще больше лазеек, порой умышленно привнесенных разработчиками для достижения большей производительности в ущерб безопасности. Безопасность — весьма абстрактное понятие, не поддающееся измерению и не имеющее числового представления, в то время как тесты производительности — мощное маркетинговое средство.

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

Что такое enterprise-приложения

По сложившейся традиции enterprise-приложениями (от английского «enterprise» – предприятие) называются приложения, ориентированные на промышленное применение в больших организациях. Соответственно enterprise-серверы — это серверы, обслуживающие предприятия и включающие в себя: Web-серверы, серверы печати, базы данных и прочие жизненно важные для функционирования корпоративной сети службы. К ключевым характеристикам enterprise-приложений относят их отказоустойчивость, возможность быстрого восстановления после «падений» и, конечно, безопасность (подробнее — на http://en.wikipedia.org/wiki/Enterprise_server и http://wiki.debian.org/EnterpriseServer).

Многоликая Java

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

Общеизвестно, что Java является интерпретируемым языком, но он существенно отличается от большинства других интерпретируемых языков, таких, например, как Perl, PHP или Python. Если в Perl'е интерпретации подвергается непосредственно сам исходный код, то программа, написанная на Java, транслируется в байт-код, исполняемый на виртуальной Java-машине (далее — JVM).

Согласно терминологии, предложенной компанией Sun, реализатор JVM называется клиентом, и всякий клиент вправе исполнять байт-код так, как ему заблагорассудится (естественно, в рамках спецификации JVM). Наряду с программными реализациями JVM существуют и аппаратные, демонстрирующие производительность, ничуть не уступающую (а зачастую даже превосходящую в силу грамотной оптимизации байт-кода JVM) чистому машинному коду с процессором семейства x86, Alpha и др. С другой стороны, большую популярность завоевали JIT- компиляторы (Just-In-Time-компиляторы), на лету транслирующие байт-код в «нативный» (native) машинный код соответствующего процессора и сочетающие высокое быстродействие с дешевизной реализации.

Таким образом, Java-приложения представляют собой двоичные файлы, не имеющие ничего общего с исходными текстами, составленными на языке Java. Байт-код виртуальной машины предоставляет довольно богатый набор инструкций, описанный в спецификациях на JVM, что позволяет сторонним разработчикам создавать свои собственные трансляторы, работающие с отличными от Java языками программирования. Так, уже появились и завоевали популярность Жасмин (Java-ассемблер), Ephedra (компилятор, транслирующий Си/Си++ программы в байт-код JVM), Component Pascal (компилятор, транслирующий Pascal и Oberon программы в байт-код JVM). Имеются трансляторы и для других языков: Ада, Бейсик, Форт, Кобол и т. д.

Java представляет собой объективно-ориентированный язык программирования со строгим контролем типов, выполняемым на уровне JVM, что обеспечивает защиту как от «нечестных» трансляторов (не придерживающихся оригинальной спецификации), так и от прямой модификации байт-кода в hex-редакторе. В то же самое время такой подход существенно затрудняет трансляцию Си-программ, известных своим нецензурным кастингом (от английского «to cast» – явное преобразование типов) и вольным обращением с указателями.


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

Концептуальная модель безопасности

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

Изобилие переполняющихся буферов в Си-программах (приводящих к возможности удаленного захвата управления системой) носит фундаментальный характер, обусловленный природой самого языка программирования. Си поддерживает массивы лишь формально, и реально программистам приходится работать не с массивами, а с указателями на области памяти неизвестной длины. Язык не выполняет никакого контроля границ буферов, всецело полагаясь на программистов, а тем, как известно, свойственно ошибаться. Именно поэтому принципиальная возможность создания безопасных программ на Си практически никогда не достигается в конкретных реализациях, зачастую создаваемых в жестких временных рамках и протестированных на уровне «если запускается и не падает, значит работает». Еще ни один крупный проект, написанный на Си/Си++, не избежал ошибок проектирования. Достаточно взять SendMail или IE и подсчитать количество дыр, обнаруженных за время их существования.

Java в этом смысле выглядит весьма заманчиво. Встроенный контроль типов снимает с программиста бремя постоянных проверок границ массивов, делая их переполнение достаточно маловероятным событием. Автоматический сборщик мусора снижает актуальность проблемы утечек ресурсов и появления «висячих» указателей, хотя это достается дорогой ценой — снижением производительности и невозможностью создавать приложения реального времени. К тому же подчистка мусора освобождает лишь ресурсы, уходящие из области видимости, но не способна предотвратить «локальные» утечки памяти, которые сплошь и рядом рискуют обернуться глобальными. Достаточно, например, выделять память в бесконечном цикле вплоть до полного ее исчерпания.

Возьмем для наглядности FireFox, существенная часть которого написана с использованием Java, и сравним его с Оперой, реализованной на Си++. Лавинообразный рост дыр, обнаруживаемых в FireFox'е убедительно доказывает, что Java сам по себе от ошибок проектирования никак не спасает. Надежность программы в первую очередь зависит от профессионализма ее создателей, а уже потом от свойств выбранного языка программирования. Создавать надежную программу можно и на Си++, Опера — лучшее тому подтверждение. Это не только один из самых быстрых, но и один из самых надежных браузеров на сегодняшний день.

Складывается парадоксальная ситуация. При всей ненадежности языка Си/Си++, написанные на нем программы, как правило, намного надежнее своих Java-собратьев, хотя по логике все должно быть наоборот. Причина в том, что большинство старых (и опытных) программистов, освоивших Си/Си++, не видят никаких причин для перехода на Java-платформу, преимущественно выбираемую молодыми (более неопытными) программистами. И тот факт, что приложение написано на Java, еще не гарантирует его надежности.

Но оставим непредумышленные ошибки в стороне и перейдем к анализу целенаправленных атак на байт-код.

Микроуровень

JVM представляет собой виртуальную машину со встроенным контролем типов, прямым аналогом которой являются «железные» процессоры с теговой архитектурой (например, наш отечественный Эльбрус) — «заветная» мечта теоретиков от программирования, абстрагирующихся от реальных концепций. На макроуровне, действительно, можно работать с объектами, не задумываясь об их внутреннем представлении, но на микроуровне неизбежно приходится сталкиваться с физическими ограничениями объективно-ориентированного подхода. Для достижения приемлемой эффективности в исполнительную машину приходится включать «нечестные» механизмы, работающие в обход обозначенной системы типов. Применительно к JVM — это прямые вызовы машинного кода и класс sun.misc.Unsafe, реализующий небезопасные методы работы с памятью — getLong (чтение двойного слова из памяти по заданному адресу) и putLong (запись двойного слова в память по заданному адресу).

Начнем с прямого вызова машинного кода, являющегося документированной особенностью JVM, во всяком случае в ее реализациях от Sun вплоть до версии 1.5.6 (начиная с 1.5.6 возможность вызова машинного кода как будто бы исключена и информацию приходится добывать путем «обратного проектирования»). С каждым методом класса связана специальная структура, одним из полей которой является указатель на машинный код (точнее, псевдоуказатель). Если он равен нулю, то выполняется «родной» байт-код, расположенный в хвосте структуры, в противном случае управление передается по псведоуказателю. Изначально этот механизм задумывался для вызова внутренних RTL-функций, критичных к производительности, и для компиляции в память JIT-трансляторами.

Получается, что в Java изначально присутствовала дыра в безопасности. Ведь любой злоумышленник запросто может внедрить в байт-код настоящий машинный код, делающий все что угодно. На самом деле в Sun вовсе не дураки сидят: перед запуском Java-приложения среда исполнения тщательно проверяет байт-код, отбрасывая пользовательские классы с ненулевым указателем. Динамическая проверка менее щепетильна, и, хотя непосредственная модификация указателя на машинный код посредством метода putLong в большинстве случаев отлавливается средой исполнения, байт-код, откомпилированный в память, может беспрепятственно «хачить» указатели по своему усмотрению. И среда исполнения оказывается не в состоянии отличить «честную» модификацию указателя, выполненную JIT-компилятором, от «нечестной».

Впрочем, даже не прибегая к машинному коду с одними лишь методами getLong/putLong, можно существенно пошатнуть модель безопасности Java, произвольным образом модифицируя внутренние данные классов и меняя типы переменных вместе с атрибутами классов (public, final и т. п.). Что позволяет реализовать тот самый «нецензурный кастинг», приводящий к ошибкам переполнения (к умышленным, разумеется) и возможности удаленного захвата управления машиной с передачей управления на shell-код (только для функций, откомпилированных в память).

Важно понять, что методы getLong/putLong являются не функциями, поставляемыми вместе с библиотекой времени исполнения, а командами JVM. То есть заблокировать их вызов напрямую не получится, а если бы и получилось, многие штатные библиотеки тут же бы отказали в работе. Вообразить набор инструкций исполнительной машины без возможности низкоуровневой работы с отдельными ячейками памяти — нельзя! А раз так, у нас есть все основания полагать, что инструкции getLong/putLong — это надолго (если не навсегда) и потому следует присмотреться к ним повнимательнее.

Макроуровень

Начиная с версии 1.0, в JVM появилась метафора «песочницы» (sandbox) — изолированной среды, в которую помещаются потенциально опасные программы (например, Web-приложения, полученные из ненадежных узлов). Песочница как бы отрезана от файловой системы и может общаться только с тем узлом, с которого было загружено данное Java-приложение. «Как бы» — потому что не существует ни одной реализации JVM, отвечающей этому требованию не только на бумаге. Ряд атак на IE и FireFox как раз основан на возможности прорыва за пределы «песочницы» и перезаписи локальных файлов.


Решение проблемы заключается в запуске IE/FireFox от имени пользователя, которому недоступны никакие файлы, кроме тех, что требуются для работы браузера. Тем не менее атакующему по-прежнему доступны cookies, кэш страниц и другие данные, утечка которых крайне нежелательна, а в некоторых случаях недопустима и влечет к потере контроля над своими аккаунтами. Поэтому многие компании отказываются от Java, запрещая выполнение Java-приложений в браузере.

Хуже с Java-приложениями, находящимися на локальном диске. Они по умолчанию считаются безопасными и им доступны все ресурсы JMV, в том числе файлы, сетевые соединения и т. д. Создание компьютерного вируса на Java не только возможно, но и не сильно отличается от создания вирусов, написанных на остальных языках программирования (Си, Паскале, Ассемблере). Сказанное относится и к Web-страничкам, сохраненным на диск. При последующем открытии они уже считаются «безопасными» со всеми вытекающими отсюда последствиями. То есть для успешной атаки злоумышленнику достаточно заманить жертву на страницу с вредоносным Java-приложением и мотивировать сохранить данные на диск для последующего запуска. Вообще-то, при желании настройки браузера легко изменить, но тогда перестанут работать и все действительно безопасные приложения, нуждающиеся в доступе к файлам/сетевым соединениям.

Осознавая ущербность предложенной модели безопасности, компания Sun уже в JVM 1.1 ввела поддержку электронной подписи, благодаря которой вредоносный код потерял все шансы. Но опять только на бумаге, а в реальной жизни... Чтобы не терять совместимость с уже написанным программным обеспечением, проверка цифровой подписи по умолчанию была либо выключена, либо при загрузке неподписанного Java-приложения выдавала запрос на подтверждение, на который большинство пользователей отвечало утвердительно. Java-скриптов цифровая подпись вообще никак не коснулась, и при открытии сохраненной Web-страниws с диска они по-прежнему получали все права.


В следующей версии виртуальной машины политика безопасности была пересмотрена и существенно расширена. Деление на «ненадежные» и «надежные» приложения исчезло, уступив место правам доступа. Теперь приложения могли обращаться только к определенному перечню ресурсов, задаваемому администратором системы, что само по себе огромный прогресс, поскольку концепция «все или ничего» (т. е. «песочница» или «живая» среда) оказалась крайне негибкой. Трудно представить себе полновесное приложение, довольствующееся «песочницей». С другой стороны, если делегировать всем Java-приложениям права доступа ко всем ресурсам, то о какой «безопасности» может идти речь.

Введение селективного контроля за ресурсами потребовало реализации «контекста выполнения» — проверяя права доступа объекта к ресурсу, JVM вынуждена анализировать не только данный объект, но и предыдущие элементы стека вызовов, предоставляя доступ тогда и только тогда, когда нужным правом владеют все объекты в стеке (в терминологии Sun это называется принципом минимизации привилегий). Принцип минимизации привилегий, как легко видеть, вступает в противоречие с принципом инкапсуляции. Объект foo, опирающийся на объект bar, в «правильных» ООП-языках не знает о внутреннем устройстве bar, и потому bar может (при необходимости) пользоваться ресурсами, недоступными для foo. Классическим примером тому является системный вызов операционной системы, осуществляемый прикладной программой. Объект «файл», имеющий прямой доступ к диску, предоставляет остальным объектам набор методов для создания/удаления/чтения и записи файлов, гарантируя, что никакой другой объект не разрушит данные на диске. Если же следовать принципу минимизации привилегий, то прямой доступ к диску необходимо предоставить всем объектам, что абсурдно. Другими словами, если объект foo имеет право вызывать данный метод объекта bar с заданными аргументами, то bar обязан обслужить вызов, в противном случае пришлось бы учитывать возможный граф вызовов объектов, что требует огромных затрат памяти и процессорного времени.

Механизм, реализованный в JVM, обходит эту проблему путем создания привилегированного интервала, при выполнении которого контекст (т. е. предыдущие вызовы объектов) игнорируется, в результате чего становится возможным появление программ, нарушающих делегированные им права доступа (не важно, сознательно или нет). На это еще можно было бы закрыть глаза, если бы не тяжеловесность реализации и высокие накладные расходы. Как женщина не может быть «слегка» беременной, так и система не бывает «практически» безопасной.

Заключение

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

Изменения JVM

Структура байт-кода и набор инструкций JVM не остаются постоянными, а меняются от версии к версии, что существенно затрудняет как создание независимых трансляторов от сторонних производителей, так и реализацию атак на байт-код. Хакеру приходится либо фокусироваться на строго определенных версиях (которых может вообще не оказаться у жертвы), либо учитывать особенности каждой отдельно взятой реализации JVM, что весьма непросто. К тому же команды виртуальной машины медленно, но неуклонно движутся к изъятию потенциально опасных инструкций. В частности, из лексикона Java SE 6 исчезли команды JSR и JSR_W, представляющие собой отдаленный аналог Бейсик-команды GOSUB, передающей управление на процедуру. Sun по этому поводу пишет: «Верификатор запрещает выполнение инструкций JSR и RET. Эти инструкции используются для вызова подпрограмм при генерации try/finally-блоков. Вместо этого компилятор будет встраивать код программ непосредственно по месту вызова».

Верификатор

Верификатор байт-кода — неотъемлемая часть JVM, он проверяет каждую выполняемую инструкцию виртуальной машины (в том числе и добавленную динамически) для предотвращения поступления заведомо некорректной информации. Считается, что верификатор предотвращает следующие операции:

  • подделка указателей, например, получение указателя как результат выполнения арифметической операции (хотя инструкции getLong/putLong позволяют обращаться к любой ячейке памяти и верификатор им не помеха);
  • нарушение прав доступа к компонентам классов, в частности, присваивание переменной, снабженной описателем final (инструкции getLong/putLong без труда обходят это ограничение);
  • использование объектов в каком-либо другом качестве, например, применение к объекту метода другого класса (инструкции getLong/putLong позволяют обойти систему контроля типов).

Фактически, верификатор решает более скромные задачи, препятствуя:

  • вызову методов объектов с недопустимым набором параметров;
  • вызову инструкций JVM с недопустимым набором параметров;
  • некорректной операции с JVM-регистрами;
  • переполнению или исчерпанию стека.

Для достижения максимальной производительности верификатор совершает ряд допущений, смягчая проверку «мертвого» кода (кода, который по мнению верификатора никогда не получит управление). А реализация верификатора в JIT-компиляторах из динамической (выполняемой на каждом шаге) и вовсе вырождается в статическую (выполняемую до компиляции). В частности, проверка границ массивов, отнимающая много времени, опускается всякий раз, когда JIT-компилятор считает, что нарушения доступа на данном участке кода заведомо не происходит. Сравнивая реализации JVM от Sub и Microsoft, нельзя не заметить, что реализация Microsoft работает существенно быстрее, а реализация Sun выполняет намного больше проверок. А реализация JVM корпорации IBM обеспечивает достаточно высокую производительность без существенного ущерба для безопасности.

WWW


Крис Касперски
Специалист по компьютерной безопасности и сжатию цифрового аудио/видео, системный программист, участвующий во многих проектах (большей частью под NDA) по анализу вредоносного программного обеспечения, поиску “закладок”, разработке систем защиты информации от несанкционированного досту- па/копирования информации как в качестве рядового сотрудника, так и руководителя отдела. В настоящее время работает в компании Endeavor Security, Inc, а так же занимается преподавательской деятельностью.

Обсуждение статьи
Логин:
Пароль:
Регистрации на сервере не требуется. Если у вас есть форумный логин, вы можете использовать его.
Если нету, то вы можете зарегистрироваться на forum.itspecial.ru
Обсуждение этой статьи на forum.itspecial.ru
Для отправки сообщения введите код, указанный на картинке
Заголовок
Сообщение

Guest guest@gameland.ru Отправлено: 31.05.2009 11:32:37
RE: Небезопасная безопасная Java
Неверно, что в Python и Perl "интерпретации подвергается непосредственно сам исходный код". Там исходник JIT-компилируется в байткод. "FireFox, существенная часть которого написана с использованием Java". То есть как это "c использованием"? Там только С++, XUL и JavaScript.
Guest guest@gameland.ru Отправлено: 12.05.2010 9:26:05
RE: Небезопасная безопасная Java
Best wishes to your black lung I like this site very much replica watches are well sell these years. fake longines watch These
Guest guest@gameland.ru Отправлено: 11.10.2010 5:00:59
RE: Небезопасная безопасная Java
Pure White GHD
Benefit ghd
ghd Mini Styler
Kiss GHD
Pink GHD
Pure Black GHD
Rare GHD
cheap ghds
Cheap ghd straighteners
Ghd
ghd straighteners
Benefit ghd
ghd Mini Styler
Pink GHD
Pure Black GHD
Pure White GHD
Rare GHD
cheap ghds
Cheap ghd straighteners
Guest guest@gameland.ru Отправлено: 16.09.2011 18:35:22
RE: Небезопасная безопасная Java
Концепцию снижения стоимости эксплуатации ПО можно расширить и на офисные приложения. Не секрет, что Google ввел в эксплуатацию Web-аналоги приложений для обработки документов и электронных таблиц. Наличие.....
http://www.amerisleep.com/
Guest guest@gameland.ru Отправлено: 02.10.2011 7:00:45
RE: Небезопасная безопасная Java
Oh yeah, faubolus stuff there you!
Guest guest@gameland.ru Отправлено: 03.10.2011 11:23:07
RE: Небезопасная безопасная Java
x5UD1m , itenuobdtwcu, dzvdfwzszosk, http://dtkoggomrdfu.com/
Guest guest@gameland.ru Отправлено: 08.10.2011 9:11:41
RE: Небезопасная безопасная Java
car insurance %-O car insurence qrpn
Guest guest@gameland.ru Отправлено: 09.10.2011 5:08:45
RE: Небезопасная безопасная Java
colchicine mous prednisone tablets jmuwfy
Guest guest@gameland.ru Отправлено: 09.10.2011 14:16:59
RE: Небезопасная безопасная Java
cheapest car insurance >:-[ cheap california auto insurance kjq
Страницы: << 1 2 3 >>

Теги: Java, безопасность


Keywords: zPOSTz zMAIN_THEMEz z10098z
Для Авторов: edit Lock delete Lock

Автор: Крис Касперски
Дата: 15.05.2009 19:22:21©


Другие материалы номера
Java для SMB: Удобство решения определенных задач
Java vs .NET: почему .NET
JavaOne 2007. Репортаж с конференции
Новое - хорошо забытое старое: уязвимость Java-приложений
Будьте бдительны: Java-мидлеты
Сервер приложений и JavaBeans: современная альтернатива клиент-серверной технологии
Золотая рыбка GlassFish: сервер приложений от Sun с открытым исходным кодом
Искусственный интеллект на страже: применение самоорганизующихся карт для анализа инцидентов ИБ
Биометрическая идентификация в масштабах компании
Проблемы совместного доступа к данным в Oracle
IT-практикум: Delphi и AutoCAD. Организация связи двух популярных программных комплексов
Корпоративные сетевые хранилища данных
История одной сети
Дженнифер Трелевич: безопасность — одно из неубиваемых достоинств мэйнфреймов
Языки, которые мы потеряли
Серверные системы для SMB – приоритетное направление производителей?
Электронный документооборот для SMB
Рынок информационной безопасности России
Обработка и анализ информационных потоков: системы поддержки принятия решений

В этом разделе
Борьба с утечками информации
Директор подразделения Technical Sales, CA EMEA East: безопасностью нельзя управлять бессистемно
Безопасность и удобство: золотая середина
Константин Гавриленко: как и в медицинской практике, болезнь легче вылечить на начальной стадии
Общая проверка безопасности при проведении внутренних аудитов
Внутренний vs внешний: аудит безопасности
Интервью с экспертом Softline
Сертификация: ИТ-безопасность
Сертификация: администратор БД
Сертификация: программист
Сертификация: системный администратор
Особенности национальной сертификации
Золотая рыбка GlassFish: сервер приложений от Sun с открытым исходным кодом
Сервер приложений и JavaBeans: современная альтернатива клиент-серверной технологии
Будьте бдительны: Java-мидлеты
Новое - хорошо забытое старое: уязвимость Java-приложений
Небезопасная безопасная Java
JavaOne 2007. Репортаж с конференции
Java vs .NET: почему .NET
Java для SMB: Удобство решения определенных задач
Круговорот документов: система автоматизации документооборота Docs Vision
Внедрение ERP на практике: описание примера внедрения системы Microsoft Dynamics AX
Корпоративные ­информационные системы
Борьба с утечкой информации через USB/Ethernet-порты
АнтиDoS: защита от DoS-атаки средствами маршрутизатора


Хакер | GameLand | Мобильные компьютеры | Купи Камеру | Total Football | All Hockey | Onboarg Magazine | Хулиган | Sync
Total DVD | DVDxpert | Maxi Tuning | (game)land company | GamePost | Свой Бизнес


Rambler's Top100