私が取り組んでいるターゲット システムでは PDO はサポートされていませんが、PostGres-DB 8.2+でPHP 5.1.xを使用して SQL インジェクションを防止するソリューションを探しています。現時点では、PDO に切り替える可能性はありません。
現時点での私の解決策は、pg_prepare-prepared ステートメントです。
// Trying to prevent SQL-Injection
$query = 'SELECT * FROM user WHERE login=$1 and password=md5($2)';
$result = pg_prepare($dbconn, "", $query);
$result = pg_execute($dbconn, "", array($_POST["user"], $_POST["password"]));
if (pg_num_rows($result) < 1) {
die ("failure");
}
しかし、pg_prepare-documentation には重要な情報が欠けています:
「後で使用する」について説明します
pg_prepare() は、後で pg_execute() または pg_send_execute() で実行するための準備済みステートメントを作成します。[...]
「名前付き/匿名のステートメント」について説明します
この関数は、クエリ文字列から stmtname という名前の準備済みステートメントを作成します。このステートメントには、単一の SQL コマンドが含まれている必要があります。名前のないステートメントを作成するために stmtname を "" にすることができます。この場合、既存の名前のないステートメントは自動的に置き換えられます。[...]
「型キャスト」について説明します
pg_prepare() で使用するプリペアド ステートメントは、SQL PREPARE ステートメントを実行することによっても作成できます。(ただし、pg_prepare() は、パラメータの型を事前に指定する必要がないため、より柔軟です。) また、準備済みステートメントを削除するための PHP 関数はありませんが、SQL DEALLOCATE ステートメントをその目的に使用できます。
ただし、準備済みステートメントのこの実装が SQL インジェクションから安全であるかどうかはわかりません
*このセキュリティの質問によるほぼすべてのコメントは PDO ソリューションに関するものであり、ドキュメントではドライバーが SQL インジェクションを防止することが示されています。しかし、簡単な解決策が pg_prepare である可能性がある場合は、現時点では pg_prepare を使用します.*
おそらくベストプラクティスソリューションのこの重要な情報をありがとう。
編集(解決策としてマークされた後): 非常に啓発的な回答をありがとう!
- SQL インジェクションの重要なポイントを説明しているため、Frank Heikens のソリューションを最良の回答としてマークしました。プログラマーは準備されたステートメントを使用する場合がありますが、SQL インジェクションの欠如が誤って存在する可能性があります。
- Frank Heikens の回答とは別に、hoppa は pg_prepare/pg_query_params を使用して SQL インジェクションが防止されることを示しています。でもありがとう。
- 最適化されたコードを使用するようになりました
pg_query_params
(Milen A. Radev に感謝) - そして
pg_escape_string()
、それに関しては代替として(Halferに感謝)
すべての答えは役に立ちます:)
// Trying to prevent SQL-Injection (**updated**)
$sql_query = 'SELECT * FROM user WHERE login=$1 and password=md5($2);';
$result = pg_query_params($dbconn_login, $sql_query, array($_POST["user"], $_POST["password"]));
if (pg_num_rows($result) < 1) {
die('failure');
}