Спасаю ли я себя от инъекций sql? - PullRequest
4 голосов
/ 30 августа 2010

Я правильно делаю?Поможет ли это избежать инъекций sql?

$deleteid = htmlspecialchars(strip_tags(mysql_real_escape_string($_POST['listid'])));

mysql_send("DELETE FROM stage where listid='$deleteid'");

Ответы [ 7 ]

13 голосов
/ 30 августа 2010

Нет.

Вы не должны вызывать ничего, кроме mysql_real_escape_string.

. Функции htmlspecialchars и strip_tags используются для кодирования строк, отображаемых в виде HTML.
Онине должен использоваться с SQL

8 голосов
/ 30 августа 2010

Это может предотвратить атаки с использованием SQL-инъекций, но это плохой способ приблизиться к нему. Вместо этого используйте подготовленные запросы .

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

3 голосов
/ 30 августа 2010

Помимо упомянутых предложений (только mysql_real_escape_string, но еще лучше подготовленные заявления ), я хотел бы добавить, что всегда полезно анализировать именно то значение, которое вы пытаетесь очистить / сделать безопасным.

Если ваш идентификатор должен быть целым числом, я просто использовал бы intval($_POST['listid']), чтобы убедиться, что результатом является целое число, и зарезервировал mysql_real_escape_string для строк (хотя я лично использовал бы подготовленные операторы / PDO).

2 голосов
/ 30 августа 2010

Да, использование mysql_real_escape_string для значений, которые предназначены для использования в объявлениях строк в инструкциях MySQL, защитит вас от SQL-инъекций.Это точное назначение этой функции.

Но вам не нужны другие две функции strip_tags и htmlspecialchars.Потому что эти функции используются для удаления (HTML) тегов и замены специальных символов HTML ссылками на символы соответственно.Они не предназначены для защиты вас от SQL-инъекций.

Фактически, использование strip_tags и / или htmlspecialchars после mysql_real_escape_string может нарушить экранирование в некоторых определенных случаях (например,при использовании наборов символов не на основе US-ASCII см. также addslashes() по сравнению с mysql_real_escape_string()).Поэтому убедитесь, что вы используете эту функцию непосредственно перед вставкой возвращаемого значения в оператор SQL.

Помимо кодирования вывода с использованием mysql_real_escape_string, вы также можете проверить ввод с помощью ctype_digit:

if (ctype_digit($_POST['listid'])) {
    mysql_send("DELETE FROM stage where listid='".$_POST['listid']."'");
} else {
    // invalid value
}

Эта проверка гарантирует, что в запросе используются только (положительные) целочисленные значения, которые не нужно экранировать.

0 голосов
/ 30 августа 2010

в этом случае

mysql_query("DELETE FROM stage WHERE listid=".intval($_POST['listid']));

полная ссылка: объяснен динамический синтаксис SQL

0 голосов
/ 30 августа 2010

Я всегда использую вспомогательный класс базы данных во всех своих проектах ... таким образом, мне не нужно использовать mysql_real_escape_string, сохраняя код чистым и легким для чтения, вы будете защищены от инъекций, если забудете его использовать.

Ниже приведен пример, который я использую ...

<code><?php 
    final class DatabaseException extends Exception {
        function __construct($strErrMessage, $intErrCode) {
            parent::__construct($strErrMessage, $intErrCode);   
        }
    }

    class Database {
        protected $host     = ""; //database server
        protected $user     = ""; //database login name
        protected $pass     = ""; //database login password
        protected $database = ""; //database name
        protected $prefix   = ""; //table prefix        
        protected $connected = false;
        protected $db = null;   
        protected $record = array();
        protected $error = "";
        protected $errno = 0;

                //table name affected by SQL query
        protected $field_table= "";

        //number of rows affected by SQL query
        protected $affected_rows = 0;

        protected $link_id = 0;
        protected $query_id = array(); 

        function __construct($server, $user, $pass, $database, $pre='') {
            $this->connected = false;
            $this->host = $server;
            $this->user = $user;
            $this->pass = $pass;
            $this->database = $database;
            $this->prefix = $pre;
            $this->connect();
        }

        function __destruct() {
            //mysql_close($this->link_id); 
        }

        public function connect() {
            if ($this->link_id > 0 && $this->connected && mysql_ping($this->link_id)) { return; }

            $this->link_id = mysql_pconnect($this->host, $this->user, $this->pass);
            if (!$this->link_id) { //open failed
                throw new DatabaseException("mysql_pconnect failed",0);    
            }

            if(!@mysql_select_db($this->database, $this->link_id)) {//no database
                throw new DatabaseException("mysql_select_db failed",0); 
            }
            $this->server='';
            $this->user='';
            $this->pass='';
            $this->database=''; 
            $this->connected = true;
            $this->query("SET time_zone = '".Settings::get('db.timezone_offset')."';",TRUE);
        }

        public function escape($string) {
            if(get_magic_quotes_gpc()) 
                $string = stripslashes($string);
            return mysql_real_escape_string($string);
        }

        public function insert($table,$data,$tbl_key='id') {
            $v=''; 
            $n='';
            foreach($data as $key=>$val) {
                $n.="`$key`, ";
                if(strtolower($val)=='null') 
                    $v.="NULL, ";
                elseif(strtolower($val)=='now()') 
                    $v.="NOW(), ";
                elseif(strcmp(substr($val,0,7),'**ESC**') == 0) 
                    $v .= str_replace('**ESC**','',$val);
                else 
                    $v.= "'".$this->escape($val)."', ";
            }

            if ($v=='' || $n=='') 
                return false;

            $q  = "INSERT INTO `".$this->prefix.$table."` ";
            $q .= "(". rtrim($n, ', ') .") VALUES (". rtrim($v, ', ') .");";
            if($this->query($q)){
                $id=mysql_insert_id();
                if ($id === 0) {  // The ID generated for an AUTO_INCREMENT column by the previous INSERT query on success, 
                                  // 0 if the previous query does not generate an AUTO_INCREMENT value, or FALSE if no MySQL 
                                  // connection was established.
                    return TRUE;
                } 
                return $id;
            }
            else {
                return false;
            }
        }

        public function replace($table,$data,$tbl_key='id') {
            $v=''; 
            $n='';
            foreach($data as $key=>$val) {
                $n.="`$key`, ";
                if(strtolower($val)=='null') 
                    $v.="NULL, ";
                elseif(strtolower($val)=='now()') 
                    $v.="NOW(), ";
                elseif(strcmp(substr($val,0,7),'**ESC**') == 0) 
                    $v .= str_replace('**ESC**','',$val);
                else 
                    $v.= "'".$this->escape($val)."', ";
            }

            if ($v=='' || $n=='') 
                return false;

            $q  = "REPLACE INTO `".$this->prefix.$table."` ";
            $q .= "(". rtrim($n, ', ') .") VALUES (". rtrim($v, ', ') .");";

            if($this->query($q)){
                $id=mysql_insert_id();
                if ($id === 0) {  // The ID generated for an AUTO_INCREMENT column by the previous INSERT query on success, 
                                  // 0 if the previous query does not generate an AUTO_INCREMENT value, or FALSE if no MySQL 
                                  // connection was established.
                    return TRUE;
                } 
                return $id;
            }
            else {
                return false;
            }
        }

        public function update($table,$data,$where='1') {
            $q = "UPDATE `".$this->prefix.$table."` SET ";
            foreach($data as $key=>$val) {
                if(strtolower($val)=='null') $q .= "`$key` = NULL, ";
                elseif(strtolower($val)=='now()') $q .= "`$key` = NOW(), ";
                elseif(strcmp(substr($val,0,7),'**ESC**') == 0) $q .=  "`$key` = ".str_replace('**ESC**','',$val);
                else $q.= "`$key`='".$this->escape($val)."', ";
            }
            $q = rtrim($q, ', ') . ' WHERE '.$where.';';
            $result = $this->query($q); 

            if ($result) {
            }
            return $result;
        }

        public function search($table, $field, $value, $exact=FALSE)
        {
                    $value = escape($value);
            if (!$exact) {      
                $q = "select * from $table where $field like '%$value%';";
            } else {
                $q = "select * from $table where $field = '$value';";
            }
            return $this->query($q);
        }

        public function delete($table,$where='1') {
            $q  = "DELETE FROM `".$this->prefix.$table."` ";
            $q .= " WHERE ".$where.";";
            $result = $this->query($q);             

            if ($result) {
            }
        }

        public function query($sql,$reset=FALSE) {
            //echo "<pre>$sql
"; $ this-> connect (); $ command = strtok (trim ($ sql)," \ n \ t "); switch (strtoupper (trim ($ command))) {case "SELECT": case "SHOW": case "DESCRIBE": case "EXPLAIN": if (isset ($ this-> query_id [md5 ($ sql)]))&& $ reset == FALSE) {$ row = mysql_fetch_array ($ this-> query_id [md5 ($ sql)], MYSQL_ASSOC); if ($ row == FALSE) {не установлено ($ this-> query_id [md5 ($ sql))]); return FALSE;} else {return $ row;}} else {$ this-> query_id [md5 ($ sql)] = @mysql_query ($ sql, $ this-> link_id); if (! $ this-> query_id [md5 ($ sql)]) {throw new DatabaseException (mysql_error ($ this-> link_id), mysql_errno ($ this-> link_id));}} $ row = mysql_fetch_array ($ this-> query_id [md5 ($sql)], MYSQL_ASSOC); if ($ row == FALSE) {unset ($ this-> query_id [md5 ($ sql)]); return FALSE;} else {return $ row;} break; deошибка: return @mysql_query ($ sql, $ this-> link_id);перерыв;}}}?>

Чтобы создать и использовать класс базы данных:

$db = new Database("db.host","db.user","db.pass","db.database");

Получить данные из $_POST в вашу базу данных очень просто, если все ваши элементы формы названытак же, как поля вашей таблицы .. например:

$data = $_POST;
$ok = $db->update('mytable', $data, 'something = something_else'); //$ok will be false if something went wrong
0 голосов
/ 30 августа 2010

используйте хранимые процедуры и предоставляйте разрешения на выполнение только пользователю db вашего приложения (плюс множество других преимуществ, которые приносят sprocs)

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