まだ、テスト環境ができていないので本件のテストはまだなのですが、元トピの通り、問題がテンプレート変数のみでpagetitleやintroxextに及ばないのがなぜか、という点が気になって少しコードを眺めたのですが、気になる点に行き当たりました。
pagetitleやintroxextは save_content.processor.php のだいぶ上の方でPOSTから変数に保存されるのですが、一応、$modx->db->escapeの処理はされています。
しかし、この段階ではまだ mysqlへのconnectが確立していないため、 $modx->db->escape内の分岐では一番最後を通ることになります。
(ここはconnectの件含め、確認済みです)
コード: 全て選択
function escape($s) {
// if (function_exists('mysql_set_charset') && $this->conn)
if (function_exists('mysql_real_escape_string') && $this->conn)
{
$s = mysql_real_escape_string($s, $this->conn);
}
elseif ($this->config['charset']=='utf8' && $this->conn)
{
$s = mb_convert_encoding($s, 'eucjp-win', 'utf-8');
$s = mysql_real_escape_string($s, $this->conn);
$s = mb_convert_encoding($s, 'utf-8', 'eucjp-win');
}
else
{
$s = mysql_escape_string($s);
}
return $s;
}
つまり mysql_escape_string を使用します。この関数が一応エスケープ処理してくれますし、エスケープ対象はrealと同じようなので脆弱性を抱える可能性は低いと思いますが、関数自体は DEPRECATED となっているようです(なくなるときが来る?)。
この関数が非推奨である理由がrealと違って「カレントの文字セットを考慮したエスケープ」が無いからという点だけかどうかはわかりませんが、それだけだとすればUTF-8前提ならば代替コードの代わりにこの関数を使ってしまうのもひとつの手段かな・・・と一瞬考えました。
yama さんが書きました:
たぶん代替のescape処理に差し替えるだけであっさり解決するんじゃないかという気がしています。接続側の文字セットを確定できるからmysql_real_escape_stringを使う意味があるのですが、それだったらCMSのシステム側で分かりますし(・・ということですよね、たぶん)。今やってる処理も、いったんシステム側でeuc-jpに落としているわけですが、utf-8であることがはっきりしていて、そのutf-8に対して問題なくエスケープを行なえる処理を実装すれば、それで解決としていいんじゃないかと思います。
まぁ、こちらのコメントに沿っているといえば沿っているのかも・・・。
でも、やはり DEPRECATED となっていますし、関数内部に問題があったとしても今後修正されることはないとすれば、よくありませんよね。
となると逆にここの処理は念のため、例の代替コードで置き換えるべきだと思います。ただ、この部分は後述の理由により本来通過すべきではないと思います。
まず、realの方はlibmysqlclientの処理を呼び出して使用してくれるのだと理解していますが、これによって今後発生しうるmysql側の何らかの変更(脆弱性や仕様変更など)によってエスケープすべき対象や処理が変更になった時にphp側と切り離した形で対処できるので(逆に今はそのせいで文字コードを制御できないケースがあるわけですが)これを利用すべきということですよね。。。
そうなると、本来はまずconnectの確立を最初に行い、pagetitleなどもrealの方できっちりエスケープした上でDB投入されるべきと思われます(これがどうでもいいならば、逆に全部でrealを使う必要もないよね、、、realがついてるの片っ端からとっちゃえばUTF8なら一応今回の問題はなくなるね、というわけです)。
記事編集は管理画面で管理者のみが入力すると思いきや、サイトの作りやスニペット次第でウェブユーザに開放できる以上、しっかり行わないといけない部分だと思います。
よって、connectの確率が最初にされていれば、例のエスケープルーチンで現在 mysql_escape_string を通過する所は通過することがなくなり、基本的にはreal付きのエスケープを使用し、DB環境に問題がある場合のみ代替コードを通過する感じになる・・・はずなのですが、例のキャッシュ処理でのエスケープや他のルーチンでも同じ事をしていると、connect無しにこのエスケープルーチンに入ってくる可能性もありそうなので、connect無し時の mysql_espace_string は代替コードに置き換えて置いておくか、 connectあり&DB問題なしならばrealエスケープ、それ以外は代替コードとなるのかな。。。
キャッシュ処理時のconnect状況がどうなっているかは確認していませんが、今回の発端の改修の原因だとすれば、connectありでrealを通過ですね。。。
全然別のところで、似たような必要ないエスケープをしている部分が潜んでそうですが。。。
少々元トピの件から脱線気味ですが、本件も同時に解決できればいいかなぁと思います。save_content.processor.php の件は既知の問題でしょうか?この管轄もyamaさんだったら話が早そうですが、、、。