Предотвращение Внедрений SQL с PHP и Платформой Зенда - как?

Я пытаюсь защитить форму входа в систему на своей странице от Внедрений SQL. На серверной стороне я использую Платформу Зенда (Zend_Db,Zend_Db_Table_Abstract), но его сборка - в инжекционных функциях предотвращения: quote, quoteInto, quoteIdentifier не делайте их работу хорошо (насколько я знаю, как использовать их). Другие пути как mysql_real_escape_string, addslashes кажется, не работаю вообще...

Это - то, что я пытаюсь реализовать для защиты:

function prevent_from_sql_injection($str) {
    if(preg_match('/[\'"]/', $str))
     {die('attack1'); exit;  }// no quotes
elseif(preg_match('/[\/\\\\]/', $str))
     {die('attack2'); exit;  }// no slashes
elseif(preg_match('/(and|or|null|not)/i', $str))
     {die('attack3'); exit;  }// no sqli boolean keywords
elseif(preg_match('/(union|select|from|where)/i', $str))
     {die('attack4'); exit;  }// no sqli select keywords
elseif(preg_match('/(group|order|having|limit)/i', $str))
     {die('attack5'); exit;  }//  no sqli select keywords
elseif(preg_match('/(into|file|case|LOAD_FILE|DUMPFILE|char|schema|AES_DECRYPT|AES_ENCRYPT)/i', $str))
     {die('attack6'); exit;  }// no sqli operators
elseif(preg_match('/(--|#|\/\*)/', $str))
     {die('attack7'); exit; }// no sqli comments
elseif(preg_match('/(=|&|\|)/', $str))
     {die('attack8'); exit;  }// no boolean operators
elseif(preg_match('/(UNI\*\*ON|1 OR 1=1|1 AND 1=1|1 EXEC XP_)/', $str))
     {die('attack9'); exit; }
elseif(preg_match('/(1|'| |O|R|=|1' OR '1'='1|%31%27%20%4F%52%20%27%31%27%3D%27%31)/', $str))
     { die('attack10'); exit; }
elseif(preg_match('/(SELECT\s[\w\*\)\(\,\s]+\sFROM\s[\w]+)| (UPDATE\s[\w]+\sSET\s[\w\,\'\=]+)| (INSERT\sINTO\s[\d\w]+[\s\w\d\)\(\,]*\sVALUES\s\([\d\w\'\,\)]+)| (DELETE\sFROM\s[\d\w\'\=]+)/', $str))
     { die('attack11'); exit; } 
elseif(preg_match('/(script)|(<)|(>)|(%3c)|(%3e)|(SELECT) |(UPDATE) |(INSERT) |(DELETE)|(GRANT) |(REVOKE)|(UNION)|(&lt;)|(&gt;)/', $str))
     { die('attack12'); exit; } 
elseif(!preg_match('/^["a-zA-Z0-9\040]+$/', $str))
     { die('attack13'); exit; } 
else return $str;

}

Для тестирования моих результатов я использую расширение Firefox, SQL Вводит Меня, и это показывает еще 14 ошибок (иногда 21 или 17, и я не знаю, почему результаты отличаются):

Server Status Code: 302 Found
Tested value: 1' OR '1'='1
Server Status Code: 302 Found
Tested value: 1 UNI/**/ON SELECT ALL FROM WHERE
Server Status Code: 302 Found
Tested value: 1' OR '1'='1
Server Status Code: 302 Found
Tested value: 1 OR 1=1
Server Status Code: 302 Found
Tested value: 1' OR '1'='1
Server Status Code: 302 Found
Tested value: 1 EXEC XP_
Server Status Code: 302 Found
Tested value: 1 UNION ALL SELECT 1,2,3,4,5,6,name FROM sysObjects WHERE xtype = 'U' --
Server Status Code: 302 Found
Tested value: %31%27%20%4F%52%20%27%31%27%3D%27%31
Server Status Code: 302 Found
Tested value: 1 AND 1=1
Server Status Code: 302 Found
Tested value: 1' OR '1'='1
Server Status Code: 302 Found
Tested value: 1 AND ASCII(LOWER(SUBSTRING((SELECT TOP 1 name FROM sysobjects WHERE xtype='U'), 1, 1))) > 116

Таким образом, что лучший способ состоит в том, чтобы предотвратить все это атаки с использованием кода на SQL? Используя заполнителей хорошо, но это не делает хорошо в некоторых случаях. Возможно, это расширение является неправильным, и у меня есть паранойя?

6
задан user406136 1 August 2010 в 20:11
поделиться

3 ответа

Я настоятельно рекомендую использовать Zend_DB. В ней используются подготовленные утверждения.
Параметры подготовленных операторов не нужно заключать в кавычки; драйвер обрабатывает это автоматически.

Если приложение использует только подготовленные операторы, разработчик может быть уверенным, что SQL-инъекции не не произойдет (однако, если другие части запрос строится с использованием неэскэпированного ввода, SQL-инъекция все еще возможна

$db = Zend_Db::factory('Pdo_Mysql', array(
    'host'     => '127.0.0.1',
    'username' => 'webuser',
    'password' => 'xxxxxxxx',
    'dbname'   => 'test'
));

$stmt = $db->query('SELECT * FROM bugs WHERE reported_by = ? AND bug_status = ?',
    array('goofy', 'FIXED')
);

$rows = $stmt->fetchAll();

echo $rows[0]['bug_description'];
8
ответ дан 8 December 2019 в 17:17
поделиться

Использовать подготовленный Операторы SQL вместо экранирования значений.

 $st = $pdo->prepare("SELECT * FROM tbl WHERE x = ?");
 $st->execute($x);

Внесение в черный список пары операторов SQL не является разумным подходом. Это расширение Firefox вводит в заблуждение и создает неверное впечатление.

Очевидно, вам не следует начинать принимать случайные команды SQL в качестве входных данных. В лучшем случае вы используете некоторые переменные запроса в качестве данных запроса. И подготовленных заявлений достаточно, чтобы обеспечить безопасность в этом случае. Объединение команд и переменных SQL - устаревшая практика (что, кажется, предлагает это сомнительное расширение Firefox).

7
ответ дан 8 December 2019 в 17:17
поделиться

Поместите этот код в заголовок страницы.

function clean_header($string)
{
$string = trim($string);

// From RFC 822: “The field-body may be composed of any ASCII
// characters, except CR or LF.”
if (strpos($string, “\n“) !== false) {
$string = substr($string, 0, strpos($string, “\n“));
}
if (strpos($string, “\r“) !== false) {
$string = substr($string, 0, strpos($string, “\r“));
}

return $string;
}
-1
ответ дан 8 December 2019 в 17:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: