Тонкости с include

Тема в разделе "PHP Pro", создана пользователем PHPCod3r, 24 май 2011.

Статус темы:
Закрыта.
  1. PHPCod3r

    PHPCod3r

    Регистр.:
    7 июн 2010
    Сообщения:
    261
    Симпатии:
    25
    Все наверно знают что include служит для подключения файлов, в наш
    сценарии, но в пхп есть и аналоги этой конструкции
    к примеру
    PHP:
    eval('?>' trim(file_get_contents($our_file)));
    Понятно что это тоже подключит файл, но директива allow_url_include
    здесь уже работать не будет!
    То есть это более "опасный" вариант чем просто include.
    Но почему то разработчики phpMyAdmin его используют и переходить
    но обычный include не хотят.

    Чем по сути использование этой конструкции отличается от использование обычного include?
     
  2. DrakonHaSh

    DrakonHaSh

    Регистр.:
    29 июн 2010
    Сообщения:
    358
    Симпатии:
    122
    из кода в eval можно выйти(вернуться) через return, а из include такого не сделаешь.

    добавлено
    стыдно, стыдно. был неправ [ виновано :) ]
     
  3. Alternator

    Alternator

    Регистр.:
    23 мар 2009
    Сообщения:
    295
    Симпатии:
    145
    вы бы сначала бы справочник почитали, прежде чем писать такие глупости.
    ну или бы проверили хотя бы
    стыдно товарищ, в PRO такие глупости писать

    по теме же:
    на вскидку вижу такие отличия:
    ошибка парсинга внутри подключаемого файла, через include остановит выполнение скрипта, а в случае eval - продолжит в корневом файле выполнение дальше
     
  4. Miraage

    Miraage Angular/Laravel

    Регистр.:
    3 июн 2008
    Сообщения:
    230
    Симпатии:
    51
    возвращает ли eval данные?

    например:
    foo.php
    PHP:
    <?php
    return array();
    ?>
    test.php
    PHP:
    <?php
    $data 
    = array();
    $data['incl'] = include_once 'foo.php';
    $data['eval'] = eval('?>' trim(file_get_contents('foo.php')));   
    ?>
    что будет в $data['eval'] ? нету хоста под рукой ))
     
  5. PHPCod3r

    PHPCod3r

    Регистр.:
    7 июн 2010
    Сообщения:
    261
    Симпатии:
    25
    Запустил то что вы предложили
    PHP:
    <?php // foo.php
    return array('A');
    ?> 
    PHP:
    $data = array();
    $data['incl'] = include_once 'foo.php';
    $data['eval'] = eval('?>' trim(file_get_contents('foo.php'))); 
    var_dump($data);  
    Скрипт выплюнул такое
    array(2) {
    ["incl"]=>
    array(1) {
    [0]=>
    string(1) "A"
    }
    ["eval"]=>
    array(1) {
    [0]=>
    string(1) "A"
    }
    }
    Про возвращение данных тоже думал, вот тут про это подробней пищут

    http://habrahabr.ru/blogs/personal/78941/

    Вот по поводу ошибок интересная мысль, подравил выше приведенный код так, файл foo.php
    PHP:
    $a 1  // тута у нас точка с запятой забыта.
    return array('A');
    Получаем
    1.
    PHP:
    $data = array();
    $data['eval'] = @eval('?>' trim(file_get_contents('foo.php')));
    var_dump($data);  
    скрипт выдаст
    array(1) {
    ["eval"]=>
    bool(false)
    }
    2.
    PHP:
    $data = array();
    $data['incl'] = include 'foo.php';
    var_dump($data);
    Скрипт выдаст
    <br />
    <b>Parse error</b>: syntax error, unexpected T_RETURN in <b>/path/to/foo.php</b> on line <b>3</b><br />

    Может еще у кого есть мысли на эту тему?
     
  6. Alternator

    Alternator

    Регистр.:
    23 мар 2009
    Сообщения:
    295
    Симпатии:
    145
    Ну, я еще проверил насчет контекста переменных.
    переменные объявляемые/используемые в подключаемом файле, остаются в контексте вызова, независимо от конструкции.
    с функциями такая же байда.

    Идея:
    можно пройтись по PMA и заменить один способ вызова на другой(думаю спокойно можно в автоматическом режиме эту операцию проделать)
    ну и соовтетсвенно посмотреть что при этом изменится.
    самому лень сейчас проверять, но с удовольствием бы послушал о результатах

    Добавлено через 15 минут
    любопытсво не выдержало, и проверил сам.
    итог:

    в PMA подобная конструкция используется всего лишь в одном месте.
    таким образом подключаются конфиги.
    и подключаются они таким способом именно ради того, чтобы корректно обработать ошибку парсинга конфига(которые написан на PHP), в случае если кто-то неосторожно его модифицирует неверным образом
    PHP:
            if (function_exists('file_get_contents')) {
                
    $eval_result =
                    eval(
    '?>' trim(file_get_contents($this->getSource())));
            } else {
                
    $eval_result =
                    eval(
    '?>' trim(implode("\n"file($this->getSource()))));
            }
            
    error_reporting($old_error_reporting);

            if (
    $eval_result === false) {
                
    $this->error_config_file true;
            } else  {
                
    $this->error_config_file false;
                
    $this->source_mtime filemtime($this->getSource());
            }
    при этом выводится вполне красиво оформленное сообщение вида "phpMyAdmin was unable to read your configuration file!", вместо "Parse error"

    короче все ради удобства пользователя.

    PS заодно выянилось, что include возвращает int 1, если в файле нету return, а eval возвращает null
    хотя, это и в справке можно найти, полагаю ж)

    Добавлено через 26 минут
    PHPCod3r.
    вы так опубликовали тему, как будто в PMA используют повсеместно такой метод, чем лично меня(например) ввели в заблуждение.
    в то время, как достаточно было просто проанализировать небольшой кусок кода, и если он непонятен, то хотя бы привести его, чтобы мы мы могли думать уже над ним, а не идти вслепую.

    Ну, чтож, мы разобрались для чего в данном конкретном случае PMA использует такой способ.
    Решение интересное, и полагаю оно будет полезно тем, кто не знал о нем(например мне ;) )

    Более практического применения финту не вижу.
     
  7. Miraage

    Miraage Angular/Laravel

    Регистр.:
    3 июн 2008
    Сообщения:
    230
    Симпатии:
    51
    а мне вообще не нравится код в phpmyadmin. вообще не ok
     
  8. Alternator

    Alternator

    Регистр.:
    23 мар 2009
    Сообщения:
    295
    Симпатии:
    145
    Miraage поделись чем-нибудь конкретным
     
  9. PHPCod3r

    PHPCod3r

    Регистр.:
    7 июн 2010
    Сообщения:
    261
    Симпатии:
    25

    Ну подключение конфига дело такое, используется не повсеместно
    но при этом вещь очень важная.
    Причем вот этот сплоит
    http://snipper.ru/view/12/phpmyadmin-2119-unserialize-arbitrary-php-code-execution-exploit/
    был как я понимаю основан имено на обсуждаемой конструкции
    и как вы сами верно подметили, разработчики пма так и не убрали
    уязвимость.
    Было тупо потерто не нужное ансериалазе и все....

    А был бы инклюд, сплоит бы не имел такой мощи из за того что allow_url_include все бы резало на корню.

    То есть у разрабов пма аккуратный вывод ошибки стоит намного выше чем безопасность их творения ))))
     
  10. KillDead

    KillDead

    Регистр.:
    11 авг 2006
    Сообщения:
    890
    Симпатии:
    562
    Вообще оглядываться на других- не совсем правильная логика. Порой мне ставят в пример- мол вот скрипт, там есть блок кода, который я назвал ересью и атавизмом прошлых лет, но скрипт используют тысячи людей, следовательно этот блок должен считаться шедевром. Вспомнился демотиватор, правда немного более жёсткий для этой ситтуации- "миллионы мух не могут ошибаться!"
    вообще про евал и инклуд - темко на хабре, http://habrahabr.ru/blogs/php/24038/
    в комментах вся соль.
     
Статус темы:
Закрыта.