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

Современные технологии динамического создания информационного наполнения являются мощнейшим средством управления потоками информации в Internet. В условиях постоянного роста вычислительной мощности языки сценариев стали одним из ключевых механизмов организации инфраструктуры Web-сайтов. Получили широкое распространение мощные и одновременно простые специализированные языки программирования, рассчитанные на разработчиков сайтов. Языки сценариев изначально были ориентированы на быстрое и эффективное решение иных задач, нежели языки программирования системного уровня и создавались как связующие средства к уже готовым программным компонентам [1]. Преимущества такого подхода перед традиционным статическим наполнением сайтов очевидны: гибкость построения гипертекстовых переходов, возможность динамического формирования отчетов по записям в базах данных, генерация комплексных документов из имеющихся элементарных компонентов [2].

В программировании информационного наполнения Internet-серверов существует два подхода: создание интерпретируемых сценариев и компиляция байт-кода. При использовании первого подхода для разработки гипертекстовой страницы нужен только обычный текстовый редактор, а сам гипертекстовый документ легко читается. Второй подход повышает эффективность исполнения программы, а также защищенность ее кода от доступа и несанкционированных изменений [2]. Интерпретаторы таких языков сценариев, как Perl и Phyton, в целях повышения эффективности перед исполнением сценария проводят предварительную трансляцию в особый переносимый байт-код. В случае популярного языка сценариев Perl у него даже есть собственное название, данное Ларри Уоллом, создателем Perl, — «пи-код» (p-code). Такой код, сформированный в результате трансляции исходного текста сценария, записывается в память или файл и лишь затем обрабатывается интерпретатором. Для языка Python файлы с байт-кодом (они имеют специальное расширение .pyc) в дальнейшем можно переносить с платформы на платформу и исполнять с равным правом, скажем, и на компьютере Sun Microsystems, и на ПК.

В конце 90-х годов CGI-программирование стало наиболее популярным и эффективным способом организации интерактивного взаимодействия с пользователями. Как и в любой другой области программирования, здесь есть свои проблемы. Одним из самых интересных и неоднозначных вопросов был и остается вопрос о защите авторских прав [3]. Он актуален хотя бы потому, что все сценарные языки, такие как Perl, Phyton, JavaScript и всевозможные его производные с постфиксом Script (JavaScript, PerlScript и т.д.) являются интерпретируемыми, и ни о каких двоичных кодах и скрытых исходных текстах не может идти и речи. В этом случае исследованию алгоритма работы сценария и использованию его без разрешения авторов не создано никаких препятствий. Программисты, создающие Web-инструментарий, пытаясь решить названную проблему, прибегают порой к изощренным методикам сокрытия исходных текстов и защиты их от модификации.

Стоит отметить, что защита от модификации важна и в качестве защиты «от дурака». Это немаловажно в тех случаях, когда приобретающий программное обеспечение пользователь получает полный доступ не только к конфигурационным файлам, но и к самим сценариям, и может по неосторожности или незнанию повредить их. Кроме того, как показывает практика обеспечения информационной безопасности, программное обеспечение Web-серверов зачастую столь несовершенно, что при достаточной сноровке злоумышленник вполне способен получить исходный текст сценариев. Классическим примером может служить инцидент с сервером WebTrends, который позволял получить исходный текст сценария, просто добавив пробел к его имени в строке запроса. Запрос по адресу «http://somewhere.in.the.internet.com/cgi-bin/script.pl» запускал script.pl на исполнение, а запрос к «http://somewhere.in.the.internet.com/cgi-bin/script.pl%20» выдавал его исходный текст любому, даже неавторизованному пользователю.

Для языка Perl одним из вариантов сокрытия исходных текстов стала возможность компилирования исходных текстов в исполняемый двоичный код (формат PE-exe для платформ Win32, ELF для Linux/BSD). Соответствующую утилиту компиляции Perl2Exe с недавних пор предоставляет компания IndigoStar Software (http://www.indigo-star.com/p2xfaq.htm).

Исходя из заявлений самих разработчиков, можно было бы предположить, что имеется в виду интеграция интерпретатора языка Perl и уже готового пи-кода: двоичный исполняемый файл не содержит исходного текста сценария. Однако на поверку компиляция оказалась даже не компиляцией в пи-код, а именно простым вложением зашифрованного файла с исходным текстом. В процессе исполнения двоичного файла исходный текст сценария и требуемые модули языка Perl расшифровываются с помощью инженерного пароля, а затем исполняются. Для этого используется технология Perl Embedded in C, разработанная Уоллом, инструментарий для поддержки которой бесплатно распространяется вместе с интерпретаторами Perl.

Недавно в популярной рассылке BugTraq, посвященной информационной безопасности и, в частности, выявлению фактов уязвимости программ, появились сообщения о ненадежности предлагаемого IndigoStar Software метода распространения исходных текстов сценариев в виде двоичных файлов. Несмотря на то что авторы утилиты Perl2Exe не предоставляют ее исходных текстов, оказалось возможным, исследовав ее программный код, выявить инженерный пароль и способ шифрования исходных текстов. Более того, оказалось, что сделать это можно в совершенно автоматическом режиме, без участия человека-оператора. Говорить о криптографической стойкости здесь бессмысленно, поскольку ключ к шифру находится рядом с самим шифром [4]. Таким образом, для того чтобы извлечь исходный текст из двоичного файла, достаточно запустить на исполнение специальную утилиту, совершающую обратное преобразование Exe2Perl.

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

#!/bin/perl
use DecipherModule;
@*x$]`0uN&k^Zx02jZ^X{.?s!(f;9Q/^A^
@~~8H]|,%@^P:q-=

Фильтры исходных текстов в частном случае позволяют зашифровать и/или заархивировать часть основного тела сценария так, что сначала будет загружен специальный модуль, который будет расшифровывать остальную часть сценария построчно. Возможно, преимущества такого подхода на первый взгляд не выглядят очевидными. Для того чтобы оценить их, надо чуть более детально разобраться в достаточно универсальном механизме фильтров исходных текстов. В этом весьма специфичном инструменте нашли отражение последние разработки в смежных областях программирования и защиты программного обеспечения. Действительно, многие технологии защиты программ от несанкционированного копирования и использования можно легко перенести на «почву» фильтров исходных текстов и применить при создании Web-сценариев. Однако здесь применимы и те же самые методы обхода защитных барьеров.

Самым уязвимым является модуль дешифрования основного тела исходного текста. Он может быть написан на самом языке Perl, но тогда достаточно будет его исследовать, что является, в общем-то, тривиальной задачей, поскольку он не может быть закодирован. Кроме того, если алгоритм шифрования достаточно сложен, расшифровка исходного текста может занять долгое время, что отрицательно скажется на эффективности функционирования Web-сайта. Очевидно, в этом случае решение воспользоваться шифрованием может оказаться не очень удачным. Однако в качестве расшифровывающего модуля можно использовать своего рода plug-in — подключаемую библиотеку, написанную на некотором другом, компилируемом языке и оформленную в виде разделяемого модуля. Используя набор функций Perl API, данный модуль расшифрует исходный текст гораздо быстрее, чем если бы он сам был написан на языке Perl. Кроме того, такой подход позволяет на полную мощность использовать средства усложнения анализа программного кода, включая такие известные приемы, как применение самомодифицирующегося кода, шифрование/десшифрование «на лету», во время исполнения процедур модуля. Наконец, встроенные средства Perl API позволяют определить, не запущен ли сценарий под управлением отладчика в целях исследования его кода, а также определить наличие и количество других фильтров исходных текстов.

Подобный механизм был реализован авторами статьи с использованием поточного шифра RC4 с длиной ключа 32 байта. Механизм его работы довольно прост и может быть адаптирован в зависимости от конкретной задачи. После шифрования с помощью RC4 исходного сценария:

#!/bin/perl
print «Hello, world»;
die immediately;

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

#!/bin/perl
use scripher;
f;9Q/^A^@~Ро$#9Ёфsdjаs2fk58f_!@.?s!
(f;9Q/^A^@~

Модуль scripher.pm загружает заранее откомпилированную разделяемую библиотеку scripher.so с помощью стандартного модуля интерпретатора DynaLoader.

Scripher.pm
package scripher;
require DynaLoader;
@ISA = qw(DynaLoader);
$VERSION = «0.0.1»;
bootstrap scripher $VERSION;
1;

Модуль объемом 7 Кбайт с реализованным алгоритмом RC4 и необходимыми средствами обработки исходного текста размещается в том же каталоге, что и зашифрованный файл сценария. Таким образом, для передачи сценария необходимо передать два дополнительных файла scripher.pm и scripher.so (они являются общими для всех зашифрованных сценариев этого типа).

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

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

#!/usr/bin/perl
# randomize source file
# lines are output in random order
# reads from from stdin or arg0, writes
to stdout or arg1
open (STDIN, $ARGV[0]) if (($ARGV[0] ne «»)
&& ($ARGV[0] ne «-»));
open (STDOUT, «>$ARGV[1]») if ($ARGV[1] ne «»);
@list = ;
while (@list) {
$rand = rand (@list);
print $list[$rand];    # for indexing
rand is truncated
plice @list, $rand, 1; # delete array element
}

превратится в нечто подобное:

#!/usr/bin/perl
open (STDIN,$ARGV[0])if (($ARGV[0] ne
 «»)&&($ARGV[0] ne «-»));open
(STDOUT,»>$ARGV[1]»)if ($ARGV[1] ne
 «»);@110202012_as=;<
while(@110202012_as){$qewre7_434=
rand(@l110202012_as);print
$110202012_as[$qewre7_434];splice@
110202012_as,$qewre7_434,1;}

Техника искажения исходных текстов в свое время была весьма популярна: достаточно вспомнить распространяемые исходные тексты на языке Паскаль к пакетам Turbo Power, которые, будучи искажены подобным образом, оставались, тем не менее, пригодными к компиляции и сборке. Возможно, что с развитием сценарного программирования, эта техника обретет вторую молодость.

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

Литература

[1] Остераут Д., «Сценарии: высокоуровневое программирование для XXI века», «Открытые системы», 1998, № 3

[2] Храмцов П., «Управление сценариями просмотра Web-страниц», «Сomputerworld Россия», 1996, № 46

[3] Крюков М., Прозоровский В., «Гражданско-правовой статус производителей программ», «Открытые системы», 1999, № 2

[4] Аграновский А.В., Хади Р.А., Ерусалимский Я.М., «Криптография и открытые системы», «Телекоммуникации», 2000, № 1

Александр Аграновский (asni@rnd.runnet.ru), Роман Хади (rhady@rsu.ru) — сотрудники ГП КБ «Спецвузавтоматика» (Ростов-на-Дону).


Компилятор для Perl

Утилита для преобразования сценариев на языке Perl в исполняемые файлы Perl2Exe позволяет сгенерировать модули для Win32 и многих Unix-подобных операционных систем. Perl2Exe также позволяет создавать неконсольные программы с использованием Perl/Tk.