Защита своего php скрипта

Защита PHP скрипта путям привязки к доменному имени

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

Некоторым хочется кодировать не весь код, а лишь его часть, и для этого многие используют такой «массив» для защиты:

$_SERVER['HTTP_HOST']='разрешенный домен'; 
  • Скрипт будет закодирован путем обфускатора, который посылает API запрос к сайту, где API ищет доменное имя и ключ в базе данных; если он есть, то скрипт будет работать, если нет, то он будет переадресовывать основному сайту (пример будет таким: domain.com/api.php?domain=mysite1.ru&key=4024B-C0876-4FF0C-9A298-80EFA);
  • Также у нас будет скрипт api.php, который будет отвечать за работу проверки лицензии и т.д.;
  • Также хочу выделить лицензионный ключ, который мы будем получать. Лицензионный ключ — это md5 хэш домена, который будет проверятся через api, а в базе данных будет записан лишь сам домен и его статус.

Решение

1. Выдача лицензий и проверка действительности скрипта через api:

 'localhost', 'user' => 'root', 'pass' => '', 'base' => 'lic' ); $db = new mysqli($config['host'], $config['user'], $config['pass'], $config['base']); if($db->connect_errno) < exit('Ошибка: Не удалось подключиться к базе данных!'); >$db->set_charset("utf8"); class Main < public function keygen($domain)< $key[0] = strtoupper(md5($domain)); $key[1] = substr($key[0], 0, 5); $key[2] = substr($key[0], 5, 5); $key[3] = substr($key[0], 10, 5); $key[4] = substr($key[0], 15, 5); $key[5] = substr($key[0], 20, 5); return $key[1].'-'.$key[2].'-'.$key[3].'-'.$key[4].'-'.$key[5]; >public function getLicInfo($domain)< global $db, $config; $sql = "SELECT * FROM `licenses` WHERE `domain` = '' LIMIT 1"; $result = $db->query($sql); if($result->num_rows == 1)< return $result->fetch_assoc(); > return false; > > $main = new Main; $domain = "".$_GET['domain'].""; $key = strtoupper($_GET['key']); if($lic = $main->getLicInfo($domain))< if($lic['license_status'])< $twokey = $main->keygen($lic['license_domain']); if($twokey == $key) < $a = 'OK_'.$lic['license_domain']; >else < $a = 'ERROR_wrongkey'; >> else < $a = 'ERROR_nolicense'; >> else < $a = 'ERROR_nolicense'; >echo $a; exit(); ?> 

Вот сам код api.php. Тут я хотел бы обратить ваше внимание на следующий код:

Данный класс создает ключ домена путем использования md5 хэш.

2.Проверка доменного имена на наличие в базе данных
В 1 пункте мы с вами обозревали код api.php, который отвечает за работу скрипта. Хочу выделить код, который я уже выделял:

 public function getLicInfo($domain)< global $db, $config; $sql = "SELECT * FROM `licenses` WHERE `domain` = '' LIMIT 1"; $result = $db->query($sql); if($result->num_rows == 1)< return $result->fetch_assoc(); > return false; > > 

Данный класс проверяет доменное имя на наличие в базе данных, и если все удачно, то скрипт работает; если нет, то он переадресует на основной сайт.

Читайте также:  Proxy javascript node js

Вот мы с вами закончили обозревать код api.php, который отвечает за основную работу проверки лицензии, но теперь стоит вопрос: «А как его реализовать в самом скрипте?»

Делается оно благодаря следующему коду:

 public function __destruct() < $request = file_get_contents("http://domain.com/api.php?domain=". $_SERVER['HTTP_HOST'] ."&key _", $request); if($status[0] != "OK" && "".$_SERVER['HTTP_HOST']."" != $status[1])< header("Location: http://domain.com/"); >> 

Этот код отправляет запрос в API и если имеется в базе данных, и если доменное имя есть в базе данных, то скрипт работает, если нет, то не работает. Такая же ситуация, если код неправильный, для этого в api.php существует следующий «отрезок» кода:

if($lic = $main->getLicInfo($domain))< if($lic['license_status'])< $twokey = $main->keygen($lic['license_domain']); if($twokey == $key) < $a = 'OK_'.$lic['license_domain']; >else < $a = 'ERROR_wrongkey'; >> else < $a = 'ERROR_nolicense'; >> else < $a = 'ERROR_nolicense'; >echo $a; exit(); 

Думаю, тут понятно: если все правильно, то «выходит» сообщение ok_myssite.com и это удовлетворяет, то скрипт продолжает работу, а если введен неверный ключ или доменное имя, то «выходит» следующие сообщения (смотря где есть ошибка):

Думаю, все. Также жду конструктивных комментариев, и благодарю pixxxel за его статью «Защита PHP скриптов от копирования — это возможно?»

Источник

Лучшие практики и рекомендации по защите php-приложений от XSS-атак

Создание функционирующего веб-приложения – это только полдела. Современные онлайн-сервисы и веб-приложения, помимо собственного контента, хранят данные пользователей. Защита этих данных зависит от правильно написанного кода с точки зрения надёжности и безопасности.

Большинство уязвимостей связано с неправильной обработкой данных, получаемых извне, или недостаточно строгой их проверкой. Одной из таких уязвимостей является межсайтовое выполнение сценариев (Сross Site Sсriрting, XSS), которая может привести к дефейсу сайта, перенаправлению пользователя на зараженный ресурс, вставке в веб-ресурс вредоносного кода, краже COOKIE-файлов, сессии и прочей информации. Противостоять XSS своими сила поможет применение лучших практик и рекомендаций по безопасному программированию, о которых и пойдет речь ниже.

Лучшие практики и рекомендации:

1. Используйте экранирование входных\выходных данных. Применяйте встроенные функции для очистки кода от вредоносных скриптов. К ним относятся такие функции как htmlspecialchar(), htmlentities() и strip_tags().
Примеры использования:

$name = strip_tags($_POST['name']); $name = htmlentities($_POST['name'], ENT_QUOTES, "UTF-8"); $name = htmlspecialchars($_POST['name'], ENT_QUOTES);

Встроенные функции PHP, в отличие от самописных, работают гораздо быстрее, а также имеют меньше ошибок безопасности и уязвимостей, т.к. постоянно совершенствуются. Также рекомендуется использовать специальные библиотеки, построенные на основе встроенных функций и фильтров. В качестве примера можно привести OWASP Enterprise Security API (ESAPI), HTML Purifier, Reform, ModSecurity.
Для того чтобы библиотека работала правильно, её нужно предварительно настроить!

Читайте также:  Button making in html

2. Используйте подход «белые списки». Подход работает по принципу «что не разрешено, то запрещено». Это стандартный механизм валидации полей для проверки всех входных данных, включая заголовки, куки, строки запросов, скрытые поля, а также длина полей форм, их тип, синтаксис, допустимые символы и другие правила, прежде чем принять данные, которые будут сохраненные и отображены на сайте. Например, если в поле нужно указать фамилию, необходимо разрешить только буквы, дефис и пробелы. Если отклонить все остальное, то фамилия д’Арк будет отклонена — лучше отклонить достоверную информацию, чем принять вредоносные данные.
К сожалению, со своей задачей встроенные фильтры валидации данных PHP не справляются, поэтому рекомендуется писать собственные фильтры и «допиливать» их по мере необходимости. Таким образом, со временем ваши входные методы фильтрации будут усовершенствованы. Стоит также не забывать, что существует слишком много типов активного содержимого и способов кодирования для обхода подобных фильтров. По этой же причине не используйте проверку по «черному списку».

3. Указывайте кодировку на каждой веб-странице. Для каждой веб-страницы необходимо указывать кодировку (например, ISO-8859-1 или UTF-8) до каких-либо пользовательских полей.
Пример использования:

или в файле .htaccess веб-сервера Apache дописать строчку:

Если в http-заголовке или в метатегах кодировка не указана, браузер пытается сам определить кодировку страницы. Стандарт HTML 5 не рекомендует использовать такие кодировки, которые включают JIS_C6226-1983, JIS_X0212-1990, HZ-GB-2312, JOHAB (Windows code page 1361), а также кодировки, основанные на ISO-2022 и EBCDIC. Кроме того, веб-разработчики не должны использовать CESU-8, UTF-7, BOCU-1 и кодировки SCSU. Эти кодировки никогда не предназначались для веб-контента[1]. В случае если тег расположен до тега и заполняется пользовательскими данными, злоумышленник может вставить вредоносный html-код в кодировке UTF-7, обойдя, таким образом, фильтрацию таких символов, как ‘

Читайте также:  Wordpress как добавить css

4. Установить флаг HttpOnly. Этот Флаг делает клиентские куки недоступными через языки сценариев, такие как JavaScript.
Данная настройка активируется
— в php.ini [2]:

— в скрипте через функцию session_set_cookie_params() [3]:

void session_set_cookie_params ( int $lifetime [, string $path [, string $domain [, bool $secure = false [, bool $httponly = true ]]]] )

— в веб-приложении через функцию setcookie() [4]:

bool setcookie ( string $name [, string $value [, int $expire = 0 [, string $path [, string $domain [, bool $secure = false [, bool $httponly = true ]]]]]] )

Эта функция поддерживается последними версиями распространенных браузеров. Однако старые версии некоторых браузеров через XMLHttpRequest и другие мощные браузерные технологии обеспечивают доступ для чтения HTTP-заголовков, в том числе и заголовка Set-Cookie, в котором установлен флаг HttpOnly[5].

5. Использовать Content Security Policy (CSP). Это заголовок, который позволяет в явном виде объявить «белый список» источников, с которых можно подгружать различные данные, например, JS, CSS, изображения и пр. Даже если злоумышленнику удастся внедрить скрипт в веб-страницу, он не выполниться, если не будет соответствовать разрешенному списку источников.
Для того чтобы воспользоваться CSP, веб-приложение должно через HTTP-заголовок «Content-Security-Policy» посылать политику браузеру.
Пример использования:

Content-Security-Policy: default-src 'self'; script-src trustedscripts.example.com style-src 'self' ajax.googleapis.com; connect-src 'self' https://api.myapp.com realtime.myapp.com:8080; media-src 'self' youtube.com; object-src media1.example.com media2.example.com *.cdn.example.com; frame-src 'self' youtube.com embed.ly

‘Content-Security-Policy’ — это официальный http-заголовок, утвержденный W3C, который поддерживается браузерами Chrome 26+, Firefox 24+ и Safari 7+. HTTP-заголовок «X-Content-Security-Policy» используется для Firefox 4-23 и для IE 10-11, заголовок «X-Webkit-CSP» – для Chrome 14-25, Safari 5.1-7[6].

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

6. Регулярно проводите анализ безопасности кода и тестирование на проникновение. Используйте как ручной, так и автоматизированный подходы. Такие инструменты как Nessus, Nikto и OWASP Zed Attack Proxy помогут обнаружить уязвимости XSS в вашем веб-приложении.

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

Автор статьи: Внештатный сотрудник PentestIT, Сергей Сторчак

Источник

Оцените статью