Закры́тый исхо́дный код — программа, лицензия которой не подходит под определение открытого ПО. Как правило, это означает, что распространяются только бинарные (скомпилированные) версии программы и лицензия подразумевает отсутствие доступа к исходному коду программы, что затрудняет создание модификаций программы. Доступ к исходному коду третьим лицам обычно предоставляется при подписании соглашения о неразглашении.
ПО с закрытым исходным кодом является проприетарным (собственническим) ПО.
Двусмысленность [ править | править код ]
Фраза «Закрытый исходный код» двусмысленна, так как она может подразумевать лицензии, в которых исходный код программ недоступен. Однако если считать её антонимом открытого кода, то она относится к программному обеспечению, не подходящему под определение лицензии открытого ПО, что имеет несколько другой смысл.
Лицензия Microsoft Shared source — пример лицензии, при которой доступен исходный код, но не под открытой лицензией. Если закрытый исходный код понимать как ПО, не подходящее под определение открытого ПО, то Shared source — пример лицензии закрытого исходного кода.
Вот беда. не помню как называется и сейчас нагуглить не могу. Может кто знает? Подскажите, как называется?
_______________________________________________________________ Смысл был на подобие создание виртуальной машины, которую нельзя дешифровать, но запросы делать можно.
_______________________________________________________________ это не обсфуркация
Доброго времени, мои уважаемые читатели! Сегодня я немного расскажу о разнице открытого и закрытого кода программного обеспечения(ПО) и как это может отражаться на работе предпринимателей, которые покупают ПО для организации своих бизнес процессов. Несмотря на то, что предприниматель редко задается таким вопросом, этот момент не стоит упускать из виду, т.к. он может оказаться ключевым при возникновении потребности внести изменения в работу программного обеспечения.
В качестве вступления приведу небольшой пример истории из жизни. Предприниматель Екатерина Сергеевна, приобрела программное обеспечения для создания на его безе интернет магазина, на момент покупки Екатерину Сергеевну устраивало практически все, что касалось функционала приобретаемого ПО. В течении нескольких дней был запущен сайт, затем на протяжении месяца сайт наполнялся полезными статьями, писался раздел справки и помощи, активно добавлялись товары. Параллельно с этим была развернута рекламная компания, по привлечению клиентов в интернет магазин. Спустя 6 месяцев, сайт начал приносить доход, и перед предпринимателем встал вопрос о его улучшении, внесении ряда правок, чтобы сделать работу сайта лучше и эффективнее. Екатерина Сергеевна, обратилась к разработчику ПО, собственно у кого оно и было куплено. Но, как оказалось разработчик в данный момент занят, и не может заняться её проектом. Тогда, Екатерина обратилась к стороннему программисту, найти которого не составило большого труда. Подготовила подробный список того, что хочет изменить в своем сайте, и договорилась с ним, о начале работ. Но каково было удивление Екатерины, услышать от программиста ответ: «Я не могу реализовать ваши пожелания, т.к. исходный код ПО закрыт, я не имею к нему доступа». Работа встала.
Я очень часто наблюдаю такие ситуации, когда программа требует внесения доработок, а сделать этого нельзя, из-за того, что исходный код закрыт. Само понятие «закрытый исходный код» носит двусмысленный характер, оно может означать что:
1) код закрыт(скомпилирован, зашифрован, обфусцирован) и его нельзя посмотреть, а следовательно нельзя внести правки, изменения, дополнения;
2) код закрыт согласно лицензионному соглашению, такой код нельзя модифицировать(запрещено правообладателем) даже в том случае, если технически это возможно.
На фоне вышесказанного, возникает вопрос: кто может вносить изменения в работу такого программного обеспечения? Ответ — только разработчик, и то если пожелает, или вы сможете с ним договориться.
В свою очередь, открытый исходный код, лишен всех этих недостатков. Он может быть просмотрен, изменен, доработан и так далее, как правило лицензия по которой распространяется такое программное обеспечении разрешает пользователю модифицировать его любым образом, и если носит какие-то ограничения, то они как правило связаны с распространением его(программного обеспечения) копий.
Возвращаясь к истории предпринимателя Екатерины Сергеевны, в её случае решить возникшую задачу так и не получилось. Спустя год работы её сайта, накопилось очень большое количество изменений, которые требовалось внести в скрипты. Во первых её бизнес вырос, количество клиентов перевалило за несколько тысяч, и встал вопрос о добавлении на сайт различных сервисов: «расчет стоимости доставки», «личный кабинет», «отложенные товары» и т.д. Разработчик так и не смог выделить время на то, что-бы поработать с Екатериной (впрочем его винить за это не стоит, он изначально не оказывал услуг по доработкам, плюс ко всему таких запросов ему поступает ежедневно по несколько штук и он физически не способен их все удовлетворить), а сторонние программисты просто бессильны в данной ситуации. В итоге Екатерина приняла решение, полностью переделать весь сайт и в качестве платформы использовать уже ПО с открытым исходным кодом, это был её основной критерий к покупаемому продукту. Какие издержки она при этом понесла: покупка нового ПО, расходы по переносу базы клиентов, товаров, прочих материалов, работа по сохранению адресов страниц(что-бы не выпасть из индекса ПС) для сохранения позиций в поисковых системах, плюс её сайт простаивал некое время, и она также упустила часть выгод от возможных продаж. Все это обошлось её в крупную денежную сумму, потраченное время и нервы.
Данная история, это случай из жизни, из моей практики. Екатерина обратилась ко мне и мы славно поработали, впрочем еще многое предстоит сделать, ведь в голову постоянно приходят новые идеи, которые способствуют росту её бизнеса.
Что лучше открытое или закрытое ПО? Однозначного ответа на этот вопрос нет, в ряде случаев закрытое ПО не чем не хуже открытого. Оно выполняет поставленные задачи, обеспечивая пользователя хорошим функционалом, таких примеров много iOS, Windows, MS Office и т.д. Но если речь идет о бизнесе, который зависит от ПО, и который со временем будет расти требуя внедрения новых идей, выбор однозначно падает на программное обеспечение с открытым исходным кодом!
Закрытый исходный код — программа, лицензия которой не подходит под определение открытого ПО. Как правило, это означает, что распространяются только бинарные (откомпилированные) версии программы и лицензия подразумевает отсутствие доступа к исходному коду программы, что затрудняет создание модификаций программы. Доступ к исходному коду третьим лицам обычно предоставляется при подписании соглашения о неразглашении.
ПО с закрытым исходным кодом является проприетарным (собственническим) ПО.
Двусмысленность
Фраза «Закрытый исходный код» двусмысленна, так как она может подразумевать лицензии, в которых исходный код программ недоступен. Однако если считать её антонимом открытого кода, то она относится к программному обеспечению, не подходящему под определение лицензии открытого ПО, что имеет несколько другой смысл.
Лицензия Microsoft Shared source — пример лицензии, при которой доступен исходный код, но не под открытой лицензией. Если закрытый исходный код понимать как ПО, не подходящее под определение открытого ПО, то Shared source — пример лицензии закрытого исходного кода. Но если подразумевать под ним только те программы, исходный код которых недоступен, то это не так.
См. также
Смотреть что такое «Закрытый исходный код» в других словарях:
Закрытый код — Проприетарное, частное или собственническое программное обеспечение (англ. proprietary software) программное обеспечение, являющееся частной собственностью авторов или правообладателей и не удовлетворяющее критериям свободы ПО (речь именно о… … Википедия
Warp4 — OS/2 Warp Разработчик Microsoft Семейство ОС OS/2 Исходный код Закрытый исходный код Последняя версия 4.52 декабрь 2001 Тип ядра модульное Интерфейс графический Л … Википедия
Warp 3 — OS/2 Warp Разработчик Microsoft Семейство ОС OS/2 Исходный код Закрытый исходный код Последняя версия 4.52 декабрь 2001 Тип ядра модульное Интерфейс графический Л … Википедия
Warp3 — OS/2 Warp Разработчик Microsoft Семейство ОС OS/2 Исходный код Закрытый исходный код Последняя версия 4.52 декабрь 2001 Тип ядра модульное Интерфейс графический Л … Википедия
Warp5 — OS/2 Warp Разработчик Microsoft Семейство ОС OS/2 Исходный код Закрытый исходный код Последняя версия 4.52 декабрь 2001 Тип ядра модульное Интерфейс графический Л … Википедия
Warp 4 — OS/2 Warp Разработчик Microsoft Семейство ОС OS/2 Исходный код Закрытый исходный код Последняя версия 4.52 декабрь 2001 Тип ядра модульное Интерфейс графический Л … Википедия
Миранда (IM) — Miranda IM Тип Программа мгновенного обмена сообщениями Разработчик Miranda IM Project Написана на C/C++ ОС Microsoft Windows … Википедия
Миранда IM — Miranda IM Тип Программа мгновенного обмена сообщениями Разработчик Miranda IM Project Написана на C/C++ ОС Microsoft Windows … Википедия
Миранда АйЭм — Miranda IM Тип Программа мгновенного обмена сообщениями Разработчик Miranda IM Project Написана на C/C++ ОС Microsoft Windows … Википедия
ОС/2 — OS/2 Warp Разработчик Microsoft Семейство ОС OS/2 Исходный код Закрытый исходный код Последняя версия 4.52 декабрь 2001 Тип ядра модульное Интерфейс графический Л … Википедия
Как защитить исходный код от кражи его разработчиками
Можно ли доверять исходный код разработчикам, которые присоединились к команде, и как себя защитить от того, что они могут украсть его и начать свое дело на основе него?
Отвечают юристы Владимир Беляев («Центр Управления Законом») и Павел Мищенко (Runetlex).
У нас для вас плохие новости: единственный честный ответ на ваш вопрос одновременно является и самым бесполезным — у вас нет возможности защитить себя. Если новые разработчики захотят украсть у вас код, вы можете усложнить им жизнь, но не помешать. Ни одна бумажка не решит вашу проблему окончательно. Чего уж там, Уголовный кодекс действует чёрт знает сколько времени, но он так и не решил проблему убийств.
Нам знакома точка зрения «безопасности много не бывает», которую исповедуют банки и soviet-style компании, преимущественно с госучастием. Наймите вы такого специалиста, он сразу же покажет вам, что вы не зря платите ему деньги. Вы и оглянуться не успеете, как доступ в кабинеты будет по карточкам, к компьютерам — по отпечаткам пальцев, а чтобы отредактировать файл, понадобится служебная записка, завизированная генеральным директором, начальником отдела разработки и руководителем службы безопасности.
Нам жаль, но этот путь ведёт в тупик. Сколько бы денег вы не влили в информационную защиту, если ваш разработчик захочет украсть код — он всё равно это сделает. Единственный способ гарантировать неразглашение тайны запрещён всё тем же Уголовным кодексом.
Поэтому мы советуем вам не страдать паранойей, ограничившись минимальным разумным комплектом мер и документов: режим коммерческой тайны решит треть проблем, аккуратное обращение с правами на новый код — вторую треть, а внимательное отношение и грамотный подбор кадров — всё остальное.
Режим коммерческой тайны — это не просто подписание NDA. Одноимённый федеральный закон в статье 10 описывает целый ряд действий, которые необходимо сделать в компании:
Лайфхак: никто не запрещает поставить гриф «коммерческая тайна» в футере системы управления проектами или в теме чатика, ну и есть хардкорный вариант — наклейка на компьютере. Не лайфхак: коммерческая тайна сработает только в том случае, если вы юрлицо или индивидуальный предприниматель.
Аккуратная работа с правами подразумевает следующее:
На сдачу от сэкономленных на защите информации денег купите разработчикам печенек — их профилактическую роль сложно переоценить, а толку всё равно больше.
Можно ли защитить веб-страницы от анализа исходного кода?
Архив номеров / 2003 / Выпуск №3 (4) / Можно ли защитить веб-страницы от анализа исходного кода?
Рубрика: Программирование / Аудит
ДАНИИЛ АЛИЕВСКИЙ
Можно ли защитить веб-страницы
от анализа исходного кода?
Можно ли как-то помешать программисту-профессионалу, располагающему сколь угодно богатым арсеналом специализированных программ – отладчиком, собственной версией браузера с исходными текстами, виртуальной машиной и любыми другими средствами – проанализировать исходный HTML-код веб-страницы или, по крайней мере, клиентский JavaScript? Если это и возможно, то так же трудно, как реализация схемы защиты, описанной в этой статье.
Формат HTML – самый популярный формат для представления веб-страниц – изначально разрабатывался как открытый. Это значит, что любой посетитель, который видел веб-страницу в своем браузере, при желании всегда мог увидеть исходный HTML-текст этой страницы. Подобная возможность была встроена почти во все браузеры. Например, в Internet Explorer это команда меню View/Source.
Такое положение дел всех устраивало, пока веб-страницы были сравнительно несложные. Язык HTML тогда использовался в основном для выделения гиперссылок, вставки графики и стилевого оформления текста. В этой ситуации исходный HTML-текст отличался от того, что посетитель видел на экране, только сравнительно небольшим количеством простых тегов, управляющих заголовками, курсивом, жирностью, таблицами и т. п. Прятать от пользователя такой HTML-текст не было особого смысла. Любой HTML-верстальщик cмог бы без особого труда воспроизвести его (или написать эквивалентный), просто глядя на экран готовой веб-страницы.
Но постепенно приемы верстки усложнялись, появились стили и, самое главное, стал широко применяться язык JavaScript. Ускорение связи сделало возможным встраивание в HTML-страницы нетривиальных JavaScript-программ, которые при желании могут насчитывать десятки тысяч строк кода.
Сегодня достаточно сложная веб-страница уже не отличается от программы, написанной на традиционном языке типа Delphi или C++ и реализующей некоторый пользовательский интерфейс.
В такой ситуации открытость формата HTML иногда оказывается нежелательной. Стандарты HTML и JavaScript как бы «навязывают» соглашение, по которому все исходные тексты программ автоматически доступны конечному пользователю. Но в мире обычных программ только сторонники движения «Open Source» придерживаются такого подхода. Остальные разработчики склонны рассматривать свой исходный код как коммерческую тайну или «ноу-хау». Более того, в некоторых случаях разработчики стараются помешать даже изучению скомпилированного машинного кода (или виртуального байт-кода, как в случае Java). Для этого применяют различные приемы защиты от дизассемблирования и отладки.
Кроме соображений «коммерческой тайны» возможны случаи, когда открытость исходного кода веб-страниц недопустима по самому замыслу. Возьмем, например, веб-страницу, содержащую некоторый тест. По его результатам, которые посетитель должен куда-то отправить, принимаются какие-то решения. Такой тест в принципе нельзя реализовывать в рамках открытого HTML и JavaScript – иначе любой грамотный программист легко подделает результаты тестирования, просто подсмотрев в JavaScript-коде правильные ответы. Обычно приходится использовать серверное решение – ответы посетителя обрабатываются серверным скриптом. Но у такого решения есть свои минусы: например, необходимость в течение всего прохождения теста поддерживать связь с Интернетом или высокая нагрузка на сервер при достаточной его популярности.
Возникает естественный вопрос: можно ли как-то помешать посетителю веб-страницы получить и проанализировать ее исходный HTML-код или хотя бы используемый клиентский JavaScript? Иначе говоря, можно ли защитить веб-страницу от взлома?
Я попытаюсь подробно ответить на этот вопрос.
Вначале мы рассмотрим типичные способы «защиты», к которым прибегают неопытные веб-программисты, и расскажем, как можно легко их преодолеть. Затем мы попробуем выстроить защитную технологию, которая смогла бы реально противодействовать взломщикам.
Сразу оговорюсь: я не располагаю готовым программным пакетом, позволяющим автоматизировать защиту страниц. Я также никогда не реализовывал описываемую далее систему защиты для своих веб-страниц. Описываемая схема рассматривается чисто теоретически.
Я также не думаю, что защита от взлома именно языков HTML и JavaScript – действительно актуальная задача, по крайней мере, сегодня. Пока что, по моему личному мнению, эти языки еще «не тянут» на роль профессиональной технологии разработки нетривиального программного обеспечения. Если действительно требуется разработать клиентское приложение, серьезно защищенное от анализа исходных текстов, то, наверное, рациональнее написать его на других языках программирования.
Но с теоретической точки зрения задача защиты исходных текстов HTML и JavaScript, как мне кажется, представляет интерес именно потому, что эти языки крайне уязвимы для взлома. Технологии, которые позволили бы защитить от анализа исходных текстов HTML/JavaScript-программу, скорее всего, окажутся применимыми практически к любому другому языку.
Еще одна необходимая оговорка. Я не берусь утверждать, что предлагаемые здесь идеи действительно позволяют создать надежную защиту. Может быть, можно придумать программу, автоматически «взламывающую» любую защиту, наподобие описанных далее. Если вы найдете принципиальные упущения в приведенных далее построениях или, наоборот, придумаете альтернативную систему защиты – буду рад обсудить это на форуме xpoint.ru, а лучше пишите на daniel@siams.com.
Во всяком случае, я надеюсь, приведенные ниже рассуждения помогут новичкам вовремя остановиться в процессе разработки новой уникальной системы защиты, которая взламывается профессионалом за 3 минуты. А если кому-то действительно всерьез понадобится защитить свои страницы, возможно, эта статья сможет помочь.
Предметом нашего обсуждения будет одна HTML-страница либо несколько взаимосвязанных HTML-страниц и JavaScript-файлов, подключаемых тегом:
Вместе этот блок файлов мы будем называть веб-приложением.
Наша цель – защитить HTML- и JavaScript-код веб-приложения настолько хорошо, чтобы стоимость его взлома была существенно выше стоимости разработки эквивалентного веб-приложения. Под взломом подразумевается получение всех исходных текстов с пониманием логики их работы, с тем чтобы создать аналогичный либо совершенно другой продукт, пользуясь украденными фрагментами HTML- и JavaScript-кода.
Мы исходим из того, что в распоряжении потенциального взломщика имеются любые программные средства, которые уже существуют или могут быть в принципе разработаны. Например, взломщиком может быть программист компании Microsoft, располагающий полным исходным текстом самого популярного браузера Internet Explorer. Такой программист вполне может чуть-чуть «подправить» браузер с тем, чтобы любой HTML- или JavaScript-код, который браузеру приходится интерпретировать, автоматически сохранялся в протоколе на диске. (Недооценка подобных возможностей взломщика-профессионала – одна из самых типичных ошибок новичков, пытающихся защитить свои страницы.)
Мы также предполагаем, что взломщик и «законный» посетитель находятся в равных условиях. В частности, если для начала работы «законный» посетитель вводит какие-то пароли, то предполагается, что взломщик знает все эти пароли.
Веб-приложение должно исполняться (визуализироваться и реагировать на действия пользователя) с помощью HTML- или JavaScript-кода, расположенного на компьютере клиента. В идеале пользователь должен иметь возможность отключиться от Интернета и работать с веб-приложением в режиме off-line, пользуясь копиями файлов приложения, которые браузер поместил в свой внутренний кэш. Данное требование можно немного ослабить: допустить небольшой обмен данными с сервером (скажем, для целей защиты). Но мы не рассматриваем ситуацию, когда весь нетривиальный код «прячется» банальным образом: интерпретируется полностью на сервере.
Дополнительное требование: веб-приложение должно корректно работать хотя бы в некоторых стандартных браузерах, скажем, Internet Explorer или Netscape.
Самый наивный прием – борьба с мышкой
Очень многие авторы «систем защиты» в первую очередь начинают рассуждать следующим образом.
Чтобы увидеть исходный текст страницы, посетитель должен выбрать в браузере команду «View Source». Самый типичный способ это сделать – «всплывающее» меню, доступное по правой кнопке мышки. Пишем на JavaScript обработчик нажатия правой кнопки мышки, который вместо визуализации локального меню высвечивает какое-нибудь ругательство. Есть еще команда «View/Source» в основном меню браузера. Кладем главную страницу внутрь фрейма: тогда Internet Explorer покажет по этой команде тривиальный FRAMESET. А если умный пользователь увидит внутри FRAMESET адрес страницы с фреймом и откроет ее непосредственно? И с этим можно справиться – достаточно проверить в JavaScript, что мы находимся внутри нужного фрейма, и если это не так, то сразу уйти на страницу с «ругательствами».
Одна из самых очевидных ошибок таких авторов – они забывают про кэш браузера. Обычно проще всего получить все исходные тексты, «спрятанные» таким образом, очистив кэш в Internet Explorer и затем зайдя на «защищенную» веб-страницу. После этого достаточно заглянуть в папку «Temporary Internet Files» и обнаружить там все «спрятанные» HTML- и JavaScript-файлы.
С кэшированием, правда, можно бороться.
Борьба с кэшированием
Более «подкованные» разработчики защитных механизмов могут вспомнить про кэширование страниц и попытаться его отключить. В принципе это не так уж сложно. Для запрета кэширования существуют специальные элементы в заголовке HTTP-ответа:
(имеет смысл указать оба элемента). Заголовок HTTP-ответа достаточно легко настраивается в любом сервере. Для тех, кто не имеет доступа к нужным настройкам своего сервера, существуют эквивалентные META-теги в самом HTML:
Очевидный метод «взлома» таких способов «защиты» – использование нестандартного браузера, игнорирующего указание «не кэшировать страницы».
Нужно иметь в виду, что если единственная задача взломщика – получить на диске точную копию HTML-страницы или подключаемого JavaScript-файла, то «браузер», решающий такую задачу, пишется за 10 минут на любом языке типа Perl или Java. Все, что нужно – отправить на сервер стандартный запрос по HTTP-протоколу (например, такой же, какой выдает Internet Explorer), получить соответствующий ответ и сохранить его на диске. В большинстве современных языков программирования такая задача решается тривиально.
Существует и общее решение, позволяющее справиться с любым видом «блокировки кэширования». Это proxy-сервер, устанавливаемый на клиентский компьютер и «пропускающий через себя» без модификаций все HTTP-запросы. Такой proxy может быть совершенно «невидимым» и для клиента, и для сервера. «По пути» proxy-сервер может сохранять на диске все проходящие через него HTML- и JavaScript-файлы. Скажу больше: proxy-сервер с такими возможностями, скорее всего, уже давно существует, например, среди бесплатных утилит ускорения доступа в Интернет.
Нестандартная обработка запросов к файлам
PHP-скрипт полностью анализировал заголовок HTTP-запроса, посылаемый браузером серверу. Каждый такой заголовок среди прочего содержит поле «Referer»: URL документа, инициировавшего данный запрос (если таковой имеется). Для Java-скриптов, подключаемых тегом:
Поле «Referer» в заголовке запроса всегда содержит адрес HTML-страницы, внутри которой находится указанный тег. Если же попытаться прочитать тот же Java-скрипт, просто набрав его URL в адресной строке браузера, то поле «Referer» будет отсутствовать.
Конечно, кэширование этого JavaScript-файла было отключено.
Подобную защиту в принципе преодолеть так же просто, как и обычную блокировку кэширования, например, с помощью клиентского proxy-сервера, описанного в предыдущем пункте. Однако ленивый хакер, взламывающий «подручными средствами», вполне может оказаться сбитым с толку.
Cамогенерация методом document.writeln()
Из сказанного выше должно быть ясно, что защищаемые веб-страницы лучше всего разрабатывать таким образом, чтобы знание их исходных текстов и исходных текстов всех подключаемых JavaScript-файлов было недостаточным.
Основным приемом в данном случае является самогенерация страницы JavaScript-методом document. writeln(). HTML-страница (включающая, возможно, некоторый JavaScript) в этом случае «зашифровывается» в виде некоторой бессмысленной на вид строки символов – строковой константы языка JavaScript. Затем вызывается некоторая JavaScript-функция, расшифровывающая эту строку, и ее результат передается методу document.writeln().
В Интернете можно найти специальные утилиты, выполняющие подобное преобразование с готовой HTML-страницей. Некоторые из них при этом выполняют сжатие данных, так что «бессмысленная» строка оказывается короче исходного HTML- и JavaScript-кода.
При банальной реализации подобную защиту тоже легко взломать. Ведь страница уже «вынужденно» содержит процедуру расшифровки! Ничто не мешает слегка подправить исходный текст страницы и вставить перед вызовом document.writeln() распечатку аргумента этого метода в любое место, откуда его легко прочитать.
Тем не менее идея шифрования – одна из самых продуктивных. Мы это увидим в следующих разделах, когда будем пытаться создать «серьезную» систему защиты. Пока что заметим: ниоткуда не следует, что первый же вызов процедуры расшифровки сразу «поднесет на блюдечке» взломщику полностью расшифрованный исходный текст страницы. Может быть, будет расшифрована только небольшая часть, содержащая, в свою очередь, вызов процедуры расшифровки для следующего фрагмента. Может быть, веб-приложение состоит из сотен небольших страниц и взаимосвязанных скриптов, в которых не так-то легко найти и «подправить» вызовы расшифровывающих процедур.
Есть одна общая проблема, которую следует иметь в виду при использовании метода document. writeln(). Если содержимое страницы в Internet Explorer целиком выделить, скопировать в ClipBoard и затем попытаться вставить в какой-нибудь HTML-редактор, например в FrontPage Editor, то содержимое страницы будет вставлено уже «в готовом виде». Если часть страницы (включая какие-то JavaScript-фрагменты) была сгенерирована вызовом document.writeln(), то в HTML-редактор попадет и скрипт, содержащий вызов и тот HTML-код, который им был создан.
Мы переходим к рассмотрению более сложных технологий защиты исходного кода веб-страниц. Не буду утверждать, что они обеспечивают стопроцентную защиту. Может быть, можно разработать программное обеспечение, гарантирующее достаточно эффективный автоматизированный взлом описываемых далее защитных механизмов. Но во всяком случае, задача взлома этих механизмов неочевидна.
О защите видимого HTML-кода
Сразу оговоримся. Описанные далее методы не позволяют защитить конечный HTML (без JavaScript), который пользователь в конце концов видит на защищенных страницах. Видимый HTML всегда можно скопировать из Internet Explorer через ClipBoard в HTML-редактор, как уже было сказано в предыдущем разделе. Мне трудно представить ситуацию, когда HTML, уже видимый пользователю, настолько сложен, что его крайне трудно воспроизвести по содержимому экрана и, соответственно, имеет смысл защищать от анализа.
Серьезная защита уже визуализированного HTML невозможна в принципе. Это очевидно: всегда можно «слегка исправить» стандартный браузер, например Internet Explorer, так, чтобы в момент анализа HTML-кода и воспроизведения его на экране весь этот HTML сохранялся в протоколе на диске. Но на «несерьезном» уровне кое-какая защита все же возможна.
Вот пример такой защиты для Internet Explorer, признаюсь, не слишком «изящной». Можно просто запретить пользователю выделять какие-либо фрагменты страницы, тогда он не сможет ничего скопировать в ClipBoard. Один из способов это сделать в Internet Explorer – 10 раз в секунду исполнять примерно такую конструкцию:
var rng= document.body.createTextRange();
Самый очевидный путь построения защиты основан на шифровании. Мы сосредоточимся только на защите JavaScript-кода: любой HTML-код можно сгенерировать динамически средствами JavaScript.
Будем считать, что JavaScript-код, в соответствии с хорошим тоном программирования, состоит из большого количества не слишком больших функций. Мы начнем со следующей идеи.
Давайте зашифруем основное тело каждой функции и добавим в ее начало код, расшифровывающий и исполняющий ее тело. В языке JavaScript это означает, что текст функции
заменяется на эквивалентный текст:
// зашифрованный текст тех же самых операторов
var source=decoding_function (encrypted);
Для выполнения такой замены, конечно, следует написать некую автоматическую (или автоматизированную) утилиту.
При таком подходе функции постоянно существуют в зашифрованном виде вплоть до момента их вызова, и рассматривать их исходный текст сравнительно бесполезно.
Используемый алгоритм шифрования, в частности его криптостойкость, не имеет значения. Все равно все ключи для расшифровки, если такие имеются, распространяются вместе с зашифрованными данными. Единственная цель шифрования – сделать текст JavaScript визуально нечитаемым. Собственно, разумнее всего вместо шифрования использовать какой-нибудь простой алгоритм сжатия типа Лемпеля-Зива.
Мы не будем останавливаться на реализации такого алгоритма – это классическая задача, многократно описанная в литературе. Тут есть лишь один специфический подводный камень.
Как правило, алгоритмы расшифровки (или распаковки сжатых данных) должны получать на вход массив бинарных данных – некоторую цепочку битов. А строчная JavaScript-константа, присваиваемая переменной encrypted оператором:
по определению может содержать только текст. Следовательно, нужно как-то кодировать произвольные бинарные данные символами, допустимыми в строчной JavaScript-константе.
Я бы рекомендовал использовать 64 заведомо «безопасных» символа, скажем, все латинские буквы, цифры и пару знаков препинания. Тогда с помощью каждого символа можно кодировать 6 битов информации. Эти биты можно передать расшифровывающему алгоритму для восстановления полного Unicode-текста исходного JavaScript-кода.
К сожалению, приведенное выше решение только на первый взгляд кажется действенным.
Прежде всего, если расшифровывающая функция – это действительно одна-единственная вызываемая отовсюду функция JavaScript, то ничего не стоит, располагая полным набором HTML- и JavaScript-файлов, ее найти и подменить, с тем чтобы все расшифрованные тексты, скажем, сохранялись на диске.
А что, если не делать специальную расшифровывающую функцию, а просто разместить соответствующий код в каждой точке, где он нужен? Это не поможет – такой код все равно можно автоматически повсюду отыскать и заменить своим кодом, который будет дополнительно записывать на диск расшифрованный текст. Даже если делать расшифровывающий код каждый раз немного другим, чтобы его нельзя было искать автоматически, все равно остается «узкое место» – вызов «eval». Все вызовы eval или эквивалентные средства JavaScript типа
можно без особых усилий отыскать соответствующей автоматической утилитой и заменить подходящим JavaScript-кодом, который запротоколирует на диске весь расшифрованный текст.
А может быть, можно помешать злоумышленнику менять исходный текст наших функций? Вообще-то можно. Достаточно где-нибудь в расшифровывающем коде получить полный JavaScript-текст рассматриваемой функции – в JavaScript для этого следует выполнить оператор
(somefunction – имя нашей функции). После чего можно использовать полученный текст для расшифровки, например, наложить его в режиме XOR на зашифрованные данные. Предполагается, что алгоритм зашифровки учитывает эту операцию. Тогда искажение исходного текста функции сделает расшифровку невозможной.
Только все это – борьба с непрофессионалами. Опытный взломщик может попросту использовать собственный интерпретатор JavaScript, в котором сам оператор eval будет записывать свой аргумент на диск. Такому взломщику не нужно менять исходные тексты.
Я предлагаю пойти другим путем. Пусть алгоритм расшифровки (это может быть и одна вызываемая отовсюду функция) выдает не один полный JavaScript-текст, а серию небольших JavaScript-кусочков. Исходный текст полной функции somefunction мы превратим в «спагетти»: смесь из коротких (одна-две строки) незашифрованных фрагментов и вызовов eval для столь же коротких расшифрованных кусочков, выданных алгоритмом расшифровки. Более того, некоторые расшифрованные кусочки на самом деле будут представлять собой опять же зашифрованный код аналогичного вида:
var source= decoding_function(encrypted);
Код source, расшифровываемый здесь, может, в свою очередь, быть зашифрован. Количество «уровней» зашифровки может быть для каждого расшифровываемого кусочка функции своим и случайным.
Процесс превращения произвольной функции в подобное «спагетти» вполне можно сделать автоматическим. Написание соответствующего софта – не слишком простая, но и не самая сложная задача. Потребуется лишь корректный синтаксический анализатор JavaScript-кода, да и то не обязательно полный: скажем, можно не анализировать «внутренности» формул, ограничившись разбиением JavaScript-кода на операторы.
Не упускаем ли мы что-то очевидное? Увы, пока да.
Если расшифровывающий код будет выглядеть столь банально:
var source= decoding_function(encrypted);
то нет проблем написать утилиту, которая отыщет все подобные фрагменты, выполнит расшифровку и заменит вызов eval на расшифрованный код. Если даже source будет, в свою очередь, зашифрован – такую утилиту можно вызвать многократно.
Чтобы создание общей расшифровывающей утилиты было невозможно, надо сделать переменную encrypted вычисляемой – зависящей от хода выполнения программы. Например, если выполняется некий цикл, то он может «по пути» собирать encrypted сложением элементов массива строк. Для правильной сборки encrypted может, например, использоваться информация о времени выполнения участков программы.
Такой подход к шифрованию, наверное, невозможно полностью автоматизировать. Программисту придется самому заботиться о нетривиальной генерации переменных encrypted. Но зато теперь написание автоматической программы, полностью расшифровывающей весь JavaScript, может потребовать полного понимания логики работы программы, т.е. того самого, что мы скрываем.
Как мне кажется, мы более или менее защитили веб-приложение от «вскрытия» какими бы то ни было автоматическими сканерами, которые анализируют текст программы, не выполняя его. В терминах защиты обычных программ, компилируемых в машинные коды, мы защитились от дизассемблирования.
На банальном уровне мы также защитились от специальных средств исполнения программы вроде собственного интерпретатора JavaScript – теперь взломщику недостаточно «перехватить» пару операторов типа eval, чтобы получить «на блюдечке» первоначальные исходные тексты JavaScript-функций.
Тем не менее, работая с собственным средством исполнения JavaScript, в частности почти с любым качественным отладчиком, взломщик все же может, выполняя программу шаг за шагом, без особого труда реконструировать исходные тексты зашифрованных функций.
Для борьбы с подобным «on-line» взломом существуют специальные технологии, которые мы рассмотрим в следующем разделе.
Борьба с отладчиками
Предположим, что взломщик располагает произвольным отладчиком, в худшем для нас случае написанным самим взломщиком. Иначе говоря, наш JavaScript исполняется в некоторой виртуальной среде, полностью подконтрольной взломщику.
Если при этом наше веб-приложение будет работать нормальным образом, то всякая защита окажется бесполезной. Взломщик в любом случае сможет проследить оператор за оператором, как исполняются все наши алгоритмы. Может быть, это будет не столь комфортно, как чтение прокомментированных исходных текстов, но в принципе задача взлома – изучение исходного кода для понимания его логики – будет решена.
Мы должны предусмотреть систему противодействия отладчику. Коротко говоря, мы должны добиться, чтобы под отладчиком веб-приложение не работало нормальным образом.
Основной способ борьбы с отладчиками – анализ времени выполнения программы. Очевидно, когда взломщик занимается «вскрытием» защиты и анализирует исполняемый код, программа выполняется несравненно медленнее, чем в нормальных условиях. Для языка JavaScript это, пожалуй, единственное, чем хороший отладчик «выдает себя» – в остальном все операторы JavaScript работают обычным образом.
Как этим воспользоваться?
Банальное решение – в случае чересчур долгого исполнения некоторого кода выдавать сообщение об ошибке – не годится. Взломщик просто «обойдет» соответствующую проверку, подправив «на лету» исполняемый JavaScript или изменив значение подходящей переменной. Надо быть хитрее.
Самое разумное – использовать результаты измерения времени выполнения очень часто, в частности, в циклах. По мере исполнения программы, в том числе в процессе расшифровки функций, должны постоянно выполняться замеры времени выполнения. Заведомо слишком большие времена должны приводить к тому, что начинает выполняться код, достаточно сложный и внешне похожий на нормальный, но на самом деле бесполезный и не имеющий отношения к решаемой задаче.
Чтобы «взломать» такую программу, последовательно «подделывая» все замеры времени, взломщику придется выполнить очень большую (возможно, астрономически большую) ручную работу. Причем малейшая ошибка взломщика будет приводить к тому, что он будет незаметно для себя переходить к анализу пустого и ненужного кода, который может заканчиваться неприятными тупиками типа зацикливания или открытия на экране тысяч окон-«пустышек».
Веб-сервер и электронная подпись
Вообще говоря, для борьбы с описанным методом защиты существует сравнительно несложный общий прием. Взломщик может «подделать» таймер, JavaScript-объект Date, традиционно используемый для измерения времени. Располагая собственным отладчиком, можно «подделать» любой источник информации о времени – скажем, метод System.current TimeMillis() из Java-апплетов (и даже низкоуровневую команду процессора Intel RDTSC, в случае если бы мы защищали ассемблерную программу). «Подделанный» таймер может выдавать виртуальное время, в котором не учитываются интервалы пассивного ожидания нажатия взломщика на клавиши.
Существует ли какой-либо источник данных, который взломщик не может подделать? Вообще говоря, да. Это данные от веб-сервера, защищенные электронной подписью.
Мы не можем здесь подробно рассматривать технологию электронной подписи и наиболее популярный в этой области алгоритм RSA. Все это очень легко найти в литературе, в частности в Интернете.
В двух словах, идея здесь следующая. Есть два ключа (длинные цепочки битов): закрытый и открытый. Располагая одним ключом, невозможно восстановить другой. Закрытый ключ – секретный, открытый – общедоступный (например, распространяется вместе с данными). Данные шифруются с помощью закрытого ключа, а расшифровываются с помощью открытого.
Если данные удалось расшифровать открытым ключом, значит, есть гарантия, что они были зашифрованы соответствующим закрытым ключом. Иначе говоря, данные, зашифрованные таким способом, – это нечто вроде подписи источника данных, владеющего закрытым ключом. Такую «подпись» подделать невозможно, или, по крайней мере, сегодня неизвестны алгоритмы, позволяющие это сделать менее чем за астрономическое время.
Если допустить небольшой обмен данными с веб-сервером, к которому взломщик не имеет доступа, то, кажется, ничто не мешает использовать идею электронной подписи для получения неподделываемой информации, в частности, текущего времени. Для обращения к серверу за зашифрованным временем и расшифровки этого времени, вероятно, лучше использовать Java-апплет – JavaScript для такой задачи чересчур неуклюж. Расшифрованное текущее время можно использовать для замера быстродействия и обнаружения отладчика. По крайней мере, так можно поступать иногда, скажем, раз в несколько минут. В большинстве ситуаций, чтобы не перегружать Интернет, лучше полагаться на обычный тайминг и только иногда «сверять» часы JavaScript с показаниями часов сервера. Можно даже допустить работу в off-line-режиме (без обращений к серверу) на те периоды времени, пока не исполняется наиболее важный код, требующий особо тщательного «скрытия».
Конечно, использовать эту технику надо так же хитро, как и любые другие защитные приемы, рассматривавшиеся выше. Скажем, просто сделать Java-апплет, возвращающий столь сложным образом полученное время, совершенно бессмысленно. Взломщик просто подменит весь этот апплет. Язык Java нужно использовать только для сервисных функций – чтения зашифрованных данных с сервера и исполнения «критичных ко времени» фрагментов алгоритма расшифровки. Сам же алгоритм расшифровки по открытому ключу должен быть реализован многократно в рамках саморасшифровывающегося JavaScript, в свою очередь, по возможности, защищенного таймингом.
Идею электронной подписи можно использовать и более широко. Скажем, JavaScript-программа может правильно работать только при условии, что она имеет связь с «родным» сервером, причем гарантированно с ним, а не с его виртуальным аналогом. А это значит, что владельцы сервера могут в принципе организовать наблюдение за исполнением своих программ. Если сервер обнаружит, что JavaScript-программа на некотором клиентском компьютере (IP-адресе) исполняется «подозрительным» образом, он может вообще заблокировать дальнейшую работу JavaScript на этом компьютере, скажем, неправильной дальнейшей реакцией на запросы зашифрованных данных с этого IP-адреса. «Подозрительным» может считаться обращение за некоторыми двумя порциями данных (например, за текущим временем), разделенные слишком большим временным интервалом, что может свидетельствовать об исполнении соответствующего кода под отладчиком.
Маскировка – «безумный» код
Еще один универсальный способ борьбы со взломщиками, располагающими собственным отладчиком, – маскировка.
Цель взломщика – проанализировать логику работы некоторых алгоритмов, реализованных на JavaScript. Но для этого нужно увидеть каждый такой алгоритм в относительно «обозримом» виде, скажем, в течение часа проследить работу сотни JavaScript-операторов. А что, если эти сто операторов разбавлены «мусором» из тысячи ненужных операторов, не мешающих работе программы, но крайне запутывающих потенциального читателя?
Думаю, вполне можно разработать программный пакет, который бы целенаправленно «замусоривал» исходный код на языке JavaScript (или на любом другом языке) бесполезными операторами, которые делают что-то «на вид» вполне ценное, но в конце концов не оказывают влияния на нормальное исполнение программы. Более того, некоторые куски программы, например, начальный этап, на котором расшифровываются первые функции, могут почти полностью состоять из подобного «безумного» кода. Взломщику могут потребоваться сотни часов, чтобы «пробраться» через десятки тысяч ненужных операторов и дойти до той точки, где, наконец, появляется очередной расшифрованный фрагмент JavaScript. А если к этому добавить тайминг и связь с сервером, то подобное «путешествие» сквозь «безумный» код почти наверняка закончится уходом в совершенно бессмысленные области или даже обнаружением взломщика и блокировкой его IP-адреса.
Хотелось бы отметить еще один несложный универсальный защитный прием, который может быть довольно эффективным для защиты JavaScript-программ. Во всяком случае, его почти всегда имеет смысл использовать в дополнение к описанным выше механизмам защиты.
Это, конечно, не настоящая защита – любая программа, скомпилированная классическими компиляторами C++ или Delphi, уже «защищена» таким образом. Но по крайней мере, это делает «взлом» JavaScript-кода почти такой же непростой задачей, что и анализ машинного кода обычных программ.
Вероятно, в Интернете уже есть утилиты, выполняющие подобное преобразование. Во всяком случае, такую программу нетрудно написать, располагая синтаксическим анализатором JavaScript.
Приведенные здесь идеи по защите JavaScript-программ от взлома, т.е. несанкционированного изучения исходных текстов, вполне применимы и к другим языкам. Язык JavaScript интересен своей предельной незащищенностью от такого рода атак. Он позволяет использовать лишь сравнительно «серьезные» схемы защиты, построенные на достаточно фундаментальных идеях. Разного рода частные «трюки», основанные на особых свойствах процессора или операционной системы, здесь не проходят.
Многие из описанных выше идей были почерпнуты автором из книги:
Защита информации в персональных ЭВМ. Спесивцев, Вегнер, Крутяков, Серегин, Сидоров. М., Радио и связь, ВЕСТА, 1993. (Библиотека системного программиста).
Эту книгу написали авторы Cerberus – одной из лучших систем защиты машинного кода, популярных во времена DOS-программ. В частности, идеи саморасшифровки, тайминга и «безумного» кода – оттуда.