Шифрование отдельной части PHP-скрипта
Многие из тех, кто программируют на PHP, сталкивались с необходимостью шифрования своих скриптов в байткод для передачи на сторону. Слава богу, в наши дни существует огромный ассортимент PHP Encoder’ов, — как говорится, на любой вкус и цвет!
Мы же в своей работе столкнулись с нетривиальной задачей. Требовалось скрыть лишь некоторую часть кода, — функцию, содержимое которой не должен увидеть никто, кроме нас.
При этом нельзя зашифровать весь файл, так как все, кроме этой функции, должно быть на виду, чтобы технические специалисты принимающей стороны убедились в отсутствии «криминала» в скрипте. Вынести функцию в отдельный файл тоже нельзя, ибо мы должны быть убеждены, что md5 всего кода остался неизменным, а это значит, что необходима уверенность в неизменности первоначального вида как зашифрованной, так и видимой части скрипта.
Что делать? Первое, что пришло на ум — так называемые обфускаторы, то есть «запутывальщики» кода. При этом такой код может быть загружен без необходимости дополнительных модулей loader’ов для PHP, что является плюсом. Минусом же является то, что даже самый лютый обфускатор, который удалось найти, шаг за шагом ломался в течение 15-20 минут без излишней спешки.
На полке тем временем пылился старый добрый Zend Encoder 3.6. Понятно, что encoder’ом часть скрипта не зашифруешь, но задача требовала решения. Если посмотреть в получившийся зашифрованный файл, то можно обнаружить некоторую часть PHP-кода в начале каждого файла, а именно:
- 3272 ;
- /* This is not a text file ! */
- print «\n» ;
- print «\n» ;
- print «&# 38 ; lt ; h1 > Zend Optimizer not installed < /h1 >«;
- print «This file was encoded by the Zend Encoder / Zend SafeGuard Suite\n»;
- print «In order to run it, please install the freely available Zend Optimizer, version 2.1.0 or later.\n»;
- print » < h2 >What is the Zend Optimizer? < /h2 >
- «;
- print < < < EOM
- The Zend Optimizer is one of the most popular PHP plugins for performance-improvement , and has been freely available since the early days of PHP 4 . It improves performance by taking PHP ‘ s intermediate code through multiple Optimization Passes , which replace inefficient code patterns with efficient code blocks . The replacement code blocks perform exactly the same operations as the original code , only faster .
- In addition to performance-improvement , the Zend Optimizer also enables PHP to transparently load files encoded by the Zend Encoder or Zend SafeGuard Suite .
- The Zend Optimizer is a freely-available product from Zend Technologies . Zend Technologies is the company that develops the scripting engine of PHP , also known as the Zend Engine .
- EOM ;
- print «\n» ;
- exit ();
- ? >
Этот кусок создается на случай, если на сервере не установлен Zend Optimizer, и при загрузке любого шифрованного файла заявляет на весь мир, что пора бы задуматься о смене системного администратора :). Но нас больше привлекло другое. Что же это за загадочное «@Zend; \n 3272;» в первых строчках скрипта? Опытным путем установлено, что 3272 — это количество байт, заключенное между строчками «/* This is not a text file! */» и «exit();», умноженное на два. При этом конструкции типа «\n» и «
Далее задача свелась к размещению основного («видимого») кода на место этой Zend Encoder’овской занавески и написанию лоадера, который бы исполнил «видимый» скрипт после основного зашифрованного.
Итогом стал вполне простой файл:
- function Secret()
- // наша секретная функция
- >
- // загрузчик «видимого» скрипта:
- $script = «» ;
- $file = file($_SERVER[ «script_FILENAME» ]);
- foreach ($file as $k => $v)
- if ($k >= 3)
- $script .= $v;
- if (substr($v, 0, 7) == «exit();» ) break ;
- >
- >
- eval($script);
- exit;
Далее мы шифруем этот файл и вместо Encoder’овской заглушки ставим нужный нам скрипт.
Осталось лишь подсчитать количество байт в нашем «видимом» скрипте, дабы правильно установить значение для Zend Optimizer’а во второй строчке файла (после «@Zend»). Было лень высчитывать его вручную, поэтому написали еще один скрипт с двумя циклами: в первом цикле создавалось некоторое количество копий файла с разными «около-правдивыми» значениями байт, а во втором все эти скрипты дергались wget’ом. Скрипт с правильным значением вернет 200-й заголовок вместо 500-го.
Все готово. Итоговый файл содержит «видимую» часть скрипта и байткод. Если сервер сконфигурирован с модулем Zend Optimizer’а, то при вызове скрипта сначала исполнится его зашифрованная часть, а после — та, которую мы не скрываем. В некоторых коммерческих задачах это действительно очень необходимо.
PHP СКРЫТЬ ЧАСТЬ КОДА
1) Использование комментариев. Код, заключенный в комментарии, не исполняется, но сохраняется в файле, поэтому может быть полезен для отладки:
// Начало скрытого кодакод, который нужно скрыть// Конец скрытого кода
2) Использование функции eval. Эта функция позволяет выполнять код, переданный ей в виде строки:
$hidden_code = «код, который нужно скрыть»;eval($hidden_code);
3) Использование конструкции if(false)<. >. Код, заключенный в фигурные скобки этой конструкции, не будет выполнен, если условие, стоящее внутри if, не будет выполнено:
4) Использование функции ob_start и ob_end_clean. Функция ob_start запускает буферизацию вывода, а функция ob_end_clean удаляет все, что было записано в буфер:
ob_start();// Код, который нужно скрыть$hidden_code = ob_get_contents();ob_end_clean();
5) Использование конструкции __halt_compiler. Эта конструкция останавливает компиляцию программы на текущей строке, а код, после нее, становится недоступным для выполнения:
код, который нужно выполнить до __halt_compiler();__halt_compiler();код, который нужно скрыть
6 советов по безопасности PHP для защиты вашего сайта
Не используйте Вложенные условия. Лучше перепишите код вот так.
Как спрятать скрипт в файл
Правила написания простого.и понятного кода на PHP — Clean Code
76 вещей и предметов со скрытыми функциями
Как легко взломать сайт на PHP — SQL injection
Как скрыть расширение .html или .php в адресной строке сайта? Удалить хвосты файлов из URL (ссылок)
Как защитить исходный код PHP, JS, HTML, CSS — обфускация, минимизация, сжатие и шифрование
Приемы скрытого исполнения php кода, применяемые во вредоносных скриптах
Познакомся с несколькими «трюками», которыми пользуются разработчики вредоносного кода и вирусов, чтобы затруднить обнаружение и анализ исходного кода бэкдора или хакерского шелла.
В процессе лечения сайтов мы обнаруживаем множество разновидностей хакерских шеллов и бэкдоров. Скрипты отличаются функционалом и способом обфускации исходного кода, но у всех есть общая черта — это неявное объявление переменных и функций, а также косвенный вызов функций.
Данный подход с одной стороны значительно усложняет анализ исходного кода, а с другой — позволяет хранить код в текстовых данных. Например, часть вредоносного кода может загружаться со стороннего сайта, из базы данных и мета-данных jpeg/png/gif или передаваться в запросе к скрипту. Кроме того, часть кода, представленная в виде обычной текстовой строки, может быть очень надежно зашифрована.
Эти же приемы используются веб-разработчиками и в мирных целях в скриптах проверки лицензионных ключей и регистрации веб-приложений, чтобы затруднить взлом программных продуктов.
Практика
Несмотря на все многообразие вредоносного кода, существует не так много вариантов объявления и косвенного вызова функций. Ниже представлены примеры различных техник скрытого вызова кода. Для простоты и наглядности пусть «вредоносный код» представлен обычной функцией
которая выводит слово «Test» на странице. Естественно, имена переменных и функций, а также исполняемый код не хранятся в открытом виде и в большинстве случаев обфусцированы.
Косвенный вызов функции
Выполнение кода через eval или assert()
Выполнение кода через функции, принимающие callable-аргумент, например, array_map()
Выполнение кода через preg_replace(‘/.*/e’)
Выполнение кода через preg_replace_callback
Скрытое объявление функций и передача параметров через extract
При запуске http://site.ru/script.php?a=system&b=ls выполнит системную функцию system(«ls»)
Через регистрацию функции завершения (можно сделать exit() или die() для немедленного выполнения)
register_shutdown_function(create_function(», «echo ‘Test’;»));
Такой же подход можно использовать со всеми вызовами, принимающими в качестве аргумента callable функцию: call_user_func_array(), call_user_func(), forward_static_call_array, forward_static_call(), register_tick_function(). Хотя в реальных шеллах и бэкдорах вызовы через данные функции мы не встречали, обычно используются варианты выше.
Выполнение кода через include (когда eval, например, запретили)
В данных примерах рассматривались только примеры из функционального программирования. Но в объектно-ориентированном PHP также есть несколько варианты неявного вызова методов.
В реальных бэкдорах перечисленные варианты используют в комплексе, причем сами объявления переменных и функций часто выносят за пределы скрипта (например, загружают из базы данных, с удаленного сервера или из мета-данных изображений).
Кстати, кроме самого php хакеры иногда используют директиву auto_prepend_file для неявного подключения вредоносного кода. Например, в .htaccess могут добавить
php_value auto_prepend_file /tmp/jhdfvi2wqodvDDAD
и код из файла /tmp/jhdfvi2wqodvDDAD будет выполняться при каждом обращении к php скриптам.
Большинство перечисленных вызовов успешно детектируются сканером вредоносного кода AI-BOLIT. Это отличает его от обычных сканеров, выполняющих поиск вредоносного кода по конкретным сигнатурам или хэшу.