magic_quotes_gpc をエミュレートしたい

pho5.4以降で大きく変更された箇所の一つとしてマジッククォートの廃止があります。 magic_quotes_gpc = on を前提に書いていたコードは軒並み変更する必要があります。

これを回避するために、magic_quotes_gpc 相当の機能をエミュレートできないか考えてみました。

注意: 検証は十分に行えていないので、参考程度にご覧ください

マジッククオートとは

オンの場合、全ての' (シングルクオート), " (ダブルクオート), \ (バックスラッシュ)およびNULL 文字がバックスラッシュで自動的にエスケープされます。 これは、addslashes() の機能と同じです。

https://www.php.net/manual/ja/security.magicquotes.what.php

magic_quotes_gpc とは

GPC(Get/Post/Cookie) 処理に関する magic_quotes の設定を行います。 magic_quotes が on の場合、'(シングルクオート)、" (ダブルクオート)、(バックスラッシュ) 、NULL には全て自動的に バックスラッシュでエスケープ処理が行われます。magic_quotes_sybase も on の場合、シングルクオートは、バックスラッシュではなく シングルクオートでエスケープされます。

https://www.php.net/manual/ja/info.configuration.php#ini.magic-quotes-gpc

試してみる

<?php

var_dump($_GET['hoge']);
var_dump($_POST['huga']);
var_dump($_COOKIE['piyo']);
var_dump($_REQUEST);

リクエス

curl 'http://localhost/?hoge=ho"ge' -X POST -d "huga=hu'ga"  -b 'piyo=pi\yo'

レスポンス

magic_quotes_gpc = On の場合

string(6) "ho\"ge"
string(6) "hu\'ga"
string(6) "pi\\yo"
array(2) {
  ["hoge"]=>
  string(6) "ho\"ge"
  ["huga"]=>
  string(6) "hu\'ga"
}

magic_quotes_gpc = Off の場合

string(5) "ho"ge"
string(5) "hu'ga"
string(5) "pi\yo"
array(2) {
  ["hoge"]=>
  string(5) "ho"ge"
  ["huga"]=>
  string(5) "hu'ga"
}

これをエミュレートするにはどうすればよいか

やっていること

  • $_GET $_POST $_COOKIE $_REQUEST の値を再帰的に addslashes() している
  • phpのコードが実行される前に処理されている

参考になりそうなコードやドキュメントを色々みていく

  • php-magic-quotes-gpc

マジッククオートは内部で addslashes() を使ってほしいのですが、mysql_real_escape_string() を使っていたりと magic_quotes_gpc の実装とは乖離がありました。

https://github.com/yidas/php-magic-quotes-gpc

  • merciful-polluter

今回の要件では magic_quotes_gpc だけ、エミュレートして欲しいのですが、register_globals のエミュレートまでされてしまいました。

https://github.com/gongo/merciful-polluter

$_REQUEST の値がエスケープされていなかったのでこの箇所については修正が必要かもです。)

string(6) "ho\"ge"
string(6) "hu\'ga"
string(6) "pi\\yo"
array(2) {
  ["hoge"]=>
  string(5) "ho"ge"
  ["huga"]=>
  string(5) "hu'ga"
}

現在もどうかはわかりませんが、wordpressでは、magic_quotes_gpc の設定に関わらず、magic_quotes_gpc 相当の処理が有効になっているとのことでした。 https://www.ilovex.co.jp/blog/system/php/wordpress%20php%20magicquotes.html

該当のコードを見てみると、$_SERVER を加えてエスケープしているものの、magic_quotes 相当の処理をしています。 https://developer.wordpress.org/reference/functions/wp_magic_quotes/ https://developer.wordpress.org/reference/functions/add_magic_quotes/

除去フィルタの項目に FILTER_SANITIZE_MAGIC_QUOTES というのを発見。 https://php.net/manual/ja/filter.filters.sanitize.php

addslashes() を適用します。 ということでやりたいことも実現できている。

filter_var_array にこの定数を指定してあげれば、よさそう。 https://www.php.net/manual/ja/function.filter-var-array.php

こんなイメージ

$_GET = filter_var_array($_GET, FILTER_SANITIZE_MAGIC_QUOTES);
$_POST = filter_var_array($_POST, FILTER_SANITIZE_MAGIC_QUOTES);
$_COOKIE = filter_var_array($_COOKIE, FILTER_SANITIZE_MAGIC_QUOTES);
$_REQUEST = filter_var_array($_REQUEST, FILTER_SANITIZE_MAGIC_QUOTES);

phpの実行前に読み込ませるようにする

上記で、magic_quotes_gpc 処理自体はできましたが、どこで読み込ませるかが課題になってきます。 できれば、phpのメイン処理が実行する前に読み込んでおきたいです。

実は、php.iniauto_prepend_file というディレクティブがあり、ここにphpのメイン処理の実行前に実行したいphpファイルを指定することができます。

ここに、上記で作成した処理を実行させるようにします。

例:

auto_prepend_file = /var/www/app/init.php

最後に

これで magic_quotes_gpc 相当の処理をエミュレートすることができました。

ここに、今回実装したサンプルを置いておきます。

github.com

余談ですが、もし、SQLインジェクション対策として、magic_quotes_gpc や addslashes() を使っている場合は、Shift_JISを使っているケースなどで、十分に対策されないことがあるので注意が必要です。 (そうでなくても、SQLインジェクション対策は、Prepared Statement を使うのが望ましいです。) https://t-komura.hatenadiary.org/entry/20060122/1137944280 https://codeday.me/jp/qa/20181226/77247.html