ホームページ  >  記事  >  バックエンド開発  >  PHP で SQL インジェクションを防ぐには、addslashes と mysql_real_escape_string をもう使用しないでください。

PHP で SQL インジェクションを防ぐには、addslashes と mysql_real_escape_string をもう使用しないでください。

WBOY
WBOYオリジナル
2016-08-08 09:30:021036ブラウズ

このブロガーはさまざまなインターネット技術に熱心で、頻繁に強迫性障害を患っています。この記事が役立つと思われる場合は、私をフォローしてください。 転載する際は「Dark Blue Scythe」と明記してください


SQL インジェクションを防ぐために、多くの PHP Web サイトが依然として addlashes と str_replace を使用していることを確認しました、そして実際に私はそれを発見しました。 mysql_real_escape_string にも、ハッカーがそれをバイパスできる方法があります あなたのシステムがまだ上記の 3 つの方法を使用している場合、私の このブログ投稿は、このピットをバイパスすることをすべての人に思い出させる意味があります。

将来の世代に穴を掘るのではなく、木を植えるために、将来「問題」が「問題」でなくなるように、PHPとMYSQLのバージョン情報を与える。

str_replace とさまざまな PHP 文字置換関数は、インジェクションを防ぐために使用されることは言うまでもありませんが、この「ブラックリスト」タイプの防御は時の試練に耐えられないことが証明されています。

以下はaddlasherとmysql_real_escape_string(Trick)をバイパスする方法です。


-log の下のトリックは修正されましたが、まだ正確には解決されていませんインジェクションの問題については、多くの企業のシステムがまだ Mysql5.0 を使用しているため、すぐに改善することをお勧めします。プログラマーの能力を迅速に向上させるためのいくつかの方法についても説明します。 」で述べられている非常に重要な点。

注: システムが SQL インジェクション の危険にさらされているかどうかわからない場合は、次のデモをサーバーにデプロイしてください。実行結果が同じであれば、その後、最終的な完璧なソリューションを参照してください。

MYSQL:

mysql> select version();
+---------------------+
| version()           |
+---------------------+
| 5.0.45-community-ny |
+---------------------+
1 row in set (0.00 sec)
mysql> create database test default charset GBK;
Query OK, 1 row affected (0.00 sec)
mysql> use test;
Database changed
mysql> CREATE TABLE users (
    username VARCHAR(32) CHARACTER SET GBK,
    password VARCHAR(32) CHARACTER SET GBK,
    PRIMARY KEY (username)
);
Query OK, 0 rows affected (0.02 sec)
mysql> insert into users SET username='ewrfg', password='wer44';
Query OK, 1 row affected (0.01 sec)
mysql> insert into users SET username='ewrfg2', password='wer443';
Query OK, 1 row affected (0.01 sec)
mysql> insert into users SET username='ewrfg4', password='wer4434';
Query OK, 1 row affected (0.01 sec)=

PHP:

<?php
echo "PHP version: ".PHP_VERSION."\n";

mysql_connect(&#39;servername&#39;,&#39;username&#39;,&#39;password&#39;);
mysql_select_db("test");
mysql_query("SET NAMES GBK");

$_POST[&#39;username&#39;] = chr(0xbf).chr(0x27).&#39; OR username = username /*&#39;;
$_POST[&#39;password&#39;] = &#39;guess&#39;;

$username = addslashes($_POST[&#39;username&#39;]);
$password = addslashes($_POST[&#39;password&#39;]);
$sql = "SELECT * FROM  users WHERE  username = &#39;$username&#39; AND password = &#39;$password&#39;";
$result = mysql_query($sql) or trigger_error(mysql_error().$sql);

var_dump(mysql_num_rows($result));
var_dump(mysql_client_encoding());

$username = mysql_real_escape_string($_POST[&#39;username&#39;]);
$password = mysql_real_escape_string($_POST[&#39;password&#39;]);
$sql = "SELECT * FROM  users WHERE  username = &#39;$username&#39; AND password = &#39;$password&#39;";
$result = mysql_query($sql) or trigger_error(mysql_error().$sql);

var_dump(mysql_num_rows($result));
var_dump(mysql_client_encoding());

mysql_set_charset("GBK");
$username = mysql_real_escape_string($_POST[&#39;username&#39;]);
$password = mysql_real_escape_string($_POST[&#39;password&#39;]);
$sql = "SELECT * FROM  users WHERE  username = &#39;$username&#39; AND password = &#39;$password&#39;";
$result = mysql_query($sql) or trigger_error(mysql_error().$sql);

var_dump(mysql_num_rows($result));
var_dump(mysql_client_encoding());

結果:
PHP version: 5.2.5
int(3)
string(6) "latin1"
int(3)
string(6) "latin1"
int(0)
string(3) "gbk" 
addslashes を使用しても、mysql_real_escape_string を使用しても、コーディングの脆弱性を利用して、任意のパスワードを入力してサーバーにログインできるインジェクション攻撃を実行できることがわかります。 ! ! ! (攻撃の原理については詳しく説明しません。興味のある学生は、文字エンコーディングにおけるシングルバイトとマルチバイトの問題を学ぶことができます) 注: 3 番目の mysql_real_escape_string がインジェクションを防止できる理由mysql_escape_string 自体は現在のエンコーディングを決定できないため、サーバー側のエンコーディングとクライアント側のエンコーディングの両方を指定する必要があります。これにより、エンコーディングの問題の発生を防ぐことができます。 SQL インジェクションはある程度防ぐことができますが、それでも次のような完全な解決策をお勧めします。

完璧な解決策は、PDO とプリペアド ステートメント メカニズムを備えた MYSQLi を使用して mysql_query を置き換えることです (注: mysql_query は PHP 5.5.0 以降非推奨になり、将来削除される予定です):

PDO :

$pdo = new PDO(&#39;mysql:dbname=dbtest;host=127.0.0.1;charset=utf8&#39;, &#39;user&#39;, &#39;pass&#39;);

$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $pdo->prepare('SELECT * FROM employees WHERE name = :name');
$stmt->execute(array('name' => $name));

foreach ($stmt as $row) {
    // do something with $row
}
MYSQLi :

$stmt = $dbConnection->prepare('SELECT * FROM employees WHERE name = ?');
$stmt->bind_param('s', $name);

$stmt->execute();

$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
    // do something with $row
}
上記では、Addslashes と mysql_real_escape_string を使用しないで、PHP で SQL インジェクションを防ぐ方法を紹介しました。PHP チュートリアルに興味のある友人にとって役立つことを願っています。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。