PHP eval () это использовать в моем коде? (динамические аргументы) - PullRequest
0 голосов
/ 25 декабря 2011

РЕДАКТИРОВАТЬ: после прочтения всего ввода от других пользователей, я решил использовать то, что @chris предложил call_user_func_array () еще одна причина не использовать eval () медленнее, чем call_user_func_array () , но до сих пор никто не смог использовать его по-моему, если вы найдете способ, пожалуйста, опубликуйте его как ответ или комментарий :).Так что каждый может извлечь из этого уроки.Веселого Рождества всем!

--- EDIT END ---

Хорошо, мне нужно было создать динамический код:

Я получаю пользовательский вводкак $ _ POST ['a'], $ _POST ['b']; // Зависит от каждого запроса, сколько пользовательского ввода.

$sql = "SELECT 1, 2, 3 FROM x WHERE b = ? AND a = ? LIMIT 10"; // SQL STATEMENT
$input = array($_POST['a'], $_POST['b']);
$output = 3; // Number of variables need for 1, 2, 3
$data = readDB2($sql, $input, $output);
var_dump($data);

этот ввод передается в mysqli-> подготовленные операторы

, поскольку число переменных является динамическим ($ input и $ output);

я использовал функцию php eval ();Теперь мой вопрос может быть использован в моем коде?

Просто посмотрите в моей функции readDB2, чтобы увидеть, как я использовал функцию eval () (использовал ее 3 раза).

public function readDB2($sql, $input, $output1) {

    $stmt = $this->mysqli->prepare($sql);
    if(!empty($input) && is_array($input)) {
        $sp = "";
        $data = "";
        $inputn = count($input) - 1;
        for($i = 0; $i <= $inputn; $i++) {
            if($i !== $inputn) {
                $data .= '$input[' . $i . "],";
            } else {
                $data .= '$input[' . $i . "]";
            }
            $sp .= "s";
        }
        $bind = '$stmt->bind_param(\''. $sp . '\',' . $data . ');';
        eval("return $bind");
    }
    if (!$stmt) {throw new Exception($this->mysqli->error);}
    $stmt->execute();
    if (!$stmt) {throw new Exception($this->mysqli->error);}
    $stmt->store_result();
    $checker = $stmt->num_rows;
    if($checker !== 0) {
        if(!empty($output1)) {
            $out = "";
            for($i = 1; $i <= $output1; $i++) {
                if($i !== $output1) {
                    $out .= '$out' . $i . ",";
                } else {
                    $out .= '$out' . $i;
                }
            }
            $res = '$stmt->bind_result(' . $out . ');';
            eval("return $res");

            $vars = "array(" . $out . ");";

            while ($stmt->fetch()) {
                $results[] = eval("return $vars");
            }

        }
    } else {
        $results = "NO RESULTS";
    }
    $stmt->fetch();
    $stmt->close();

    $this->results = array('num_rows' => $checker, $results);

    return $this->results;
}

РЕДАКТИРОВАТЬ ДЛЯ Meagar

$bind = '$stmt->bind_param(\''. $sp . '\',' . $data . ');'; 
==
$bind = '$stmt->bind_param('ss', $input[0], $input[1]);); 
OR and so on
$bind = '$stmt->bind_param('sss', $input[0], $input[1], $input[2]););

РЕДАКТИРОВАТЬ ДЛЯ Incognito:

$input = array($_POST['pwnd']);

$data = readDB2($sql, $input, $output) {

public function readDB2($sql, $input, $output) {
    ...
    $inputn = count($input) - 1;
    for($i = 0; $i <= $inputn; $i++) {
            if($i !== $inputn) {
                $data .= '$input[' . $i . "],";
            } else {
                $data .= '$input[' . $i . "]";
            }
            $sp .= "s";
        }
        $bind = '$stmt->bind_param(\''. $sp . '\',' . $data . ');';
        eval("return $bind");

    ...
}

в моем результате

$bind = '$stmt->bind_param(\''. $sp . '\',' . $data . ');';

получает

eval("return $bind");

получает

$stmt->bind_param('s', $input[0]);

не то, что вы сказали.

Ответы [ 2 ]

4 голосов
/ 25 декабря 2011

Вы оцениваете данные, предоставленные пользователем, фактически позволяя злоумышленникам выполнять произвольный код. Это самая серьезная дыра в безопасности, которую может иметь ваше приложение, без исключения. Я имею в виду, что. У ваших программ буквально худшая уязвимость, которую может иметь программа.

Вы передаете $_POST['a'] как параметр $input. Параметр $input обрабатывается как массив, а его отдельные элементы добавляются в строку, которая оценивается. Если кто-то отправит исполняемый код в ваше приложение, вы можете случайно запустить его.

Я не буду заходить так далеко, чтобы фактически опубликовать работающий эксплойт, но предположим, что $_POST['a'] содержал единственный элемент со строкой '); rmdir("/etc"); //.

Эта строка:

    $bind = '$stmt->bind_param(\''. $sp . '\',' . $data . ');';

превращается во что-то вроде этого:

    $stmt->bind_param(''); rmdir("/etc"); //);';

То есть цель вашего исходного утверждения аннулируется, и вместо этого пользователь заставил вас удалить каталог /etc. Опять же, это, вероятно, не рабочий пример, но это та атака, которой вы открываете себя, доверяя предоставленным пользователем данным, чтобы передать их eval.

2 голосов
/ 25 декабря 2011

fyi, call_user_func_array () - это способ вызова функций с неизвестным числом аргументов.

array_unshift($input, str_repeat('s', count($input)));
$callable = array($stmt, 'bind_param');
call_user_func_array($callable, $input);

array_unshift () выдвигает строковый элемент 'sss'в начало массива (нам нужен фронт, потому что он должен быть первым аргументом, передаваемым в bind_param)

$ callable - это также callback тип psuedo

,в будущем, если вы обнаружите, что используете eval, ознакомьтесь с функцией php var_export (), которая может помочь вам в создании безопасных строк.Постарайтесь не использовать eval.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...