Это небезопасный способ использовать подготовленные операторы в классе php? - PullRequest
0 голосов
/ 07 февраля 2019

Я создал этот класс с помощью функции query ():

Эта функция упрощает использование подготовленных операторов.Но

  • Это безопасно?
  • Имеет ли смысл использовать его таким образом?

Я уже тестировал его с sqlmap , и он хорошо выглядит.

Функцияобычным образом разбить обычную строку SELECT на несколько меньших строк, чтобы исключить входные значения.Сохраняются входные значения и сама строка.Сама строка будет заменена на?Чем нормальная функция подготовит заменяет?снова с введенными значениями.

    class dbcon
    {   
        public $con;

        public function __construct()
        {
            $this->con = new mysqli( $host, $username, $password, $dbname );
        }


    public function query( $query )
    {   
        //selcet
        if( strpos( $query, "SELECT" ) !== false )
        {   
            $types = ""; $to_replace = []; $values = [];

            $query = explode( "WHERE", $query );
            $query_where = explode( "ORDER BY", $query[ '1' ] );

            $query_where[ '0' ];

            if( isset( $query_where[ '1' ] ) ) 
            { 
                $ORDERBY = explode("LIMIT", $query_where[ '1' ]); 
            }
            if( isset( $ORDERBY[ '1' ] ) )
            {
                $LIMIT = $ORDERBY[ '1' ];
            }

            $SELECT = $query[ '0' ];

            $where = str_replace( array( "(", ")", "[", "]" ), "", $query_where[ '0' ] );
            $where = str_replace( array( "AND", "OR", "and", "or" ), "-|-", $where );
            $where = explode( "-|-", $where );

            for ($i=0; $i < count($where); $i++) {
                $for_where = str_replace( array( "!=", "<=", ">=", "=", "<>", ">", "<", "IS", "NOT LIKE", "LIKE" ), "#|#", $where[ $i ] );
                $for_where = explode( "#|#", $for_where );

                $value = trim( $for_where[ '1' ] );
                if( substr_count($value, "AND") <= 0 AND substr_count($value, "OR") <= 0 )
                {
                    $value = "'?'";
                }

                $to_replace[] = $value;
                $value_num = "values".$i;
                $$value_num = $value;
                $values[] = &$$value_num;

                $types .= "s";
            }
            $WHERE = str_replace( $to_replace , " ? ", $query_where[ '0' ] );

            $prepare = $SELECT . " WHERE " . $WHERE;
            if ( isset( $ORDERBY ) )
            {
                $prepare .= " ORDER BY " . $ORDERBY[ '0' ];
            }
            if ( isset( $LIMIT ) ){
                $prepare .= " LIMIT " . $LIMIT;
            }

            $stmt = $this->con->prepare( $prepare );
            //$stmt->bind_param($types, $values['0'],$values['1']);
            call_user_func_array( array( $stmt, "bind_param" ), array_merge( array( $types ), $values ) );

            $stmt->execute();
                return $stmt->get_result();
            $stmt->close();
        }
    }
}

$db = new dbcon();

Вызовите функцию:

$id = $_GET[ 'id' ];
$my_query = $db->query("SELECT * FROM Users WHERE ID = '$id' ORDER BY created DESC");

while($row = $my_query->fetch_array()){ 
    echo $row['NAME']."<br>";   
}

ОБНОВЛЕНИЕ:

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

public function query( $query, $types, $query_values )
{   
    $values = [];


for ($i=0; $i < count($query_values); $i++) {
    $value_num = "values".$i;
    $$value_num = $query_values[ $i ];
    $values[] = &$$value_num;
}

$stmt = $this->con->prepare( $query );
call_user_func_array( array( $stmt, "bind_param" ), array_merge( array( $types ), $values ) );

$stmt->execute();
    return $stmt->get_result();
    $stmt->close();
}

вызовите функцию

$query  = "SELECT * FROM _Users WHERE ID = ? ORDER BY created ASC";
$my_query = $db->query( $query, "s", array( $id ) );

while($row = $my_query->fetch_array()){
    echo $row['title']."<br>";
}

1 Ответ

0 голосов
/ 07 февраля 2019

Вы не можете по определению "подготовить" / "санировать" / понять запрос после того, как вы уже интерполировали в него значения.

$my_query = $db->query("SELECT * FROM Users WHERE ID = '$id' ORDER BY created DESC");

Так чтопроисходит здесь, если кто-то пытается ввести SQL-код?Например: $id = "foo' OR '1' = '1":

SELECT * FROM Users WHERE ID = 'foo' OR '1' = '1' ORDER BY created DESC

Каким образом любой код , следующий за , может понять разницу между тем, что этот запрос должен сделать, и тем, что он делает на самом деле делает сейчас?Это не может.Смысл уже был изменен путем введения значения.Нет никакого способа исправить это после свершившегося факта.

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