よくいろんな記事をググってみると、CSRFやXSSへの対策方法として
フロントエンド側の実装で encodeURIComponent
を使用する方法が推奨されているが、
これって本当に安全と言っていいんだろうか?
encodeURIComponent
は上書きできるからだ。次のコードを見てほしい。
encodeURIComponent("ああ^〜たまらねえぜ")
// -> %E3%81%82%E3%81%82%EF%BC%BE%E3%80%9C%E3%81%9F%E3%81%BE%E3%82%89%E3%81%AD%E3%81%88%E3%81%9C
encodeURIComponent = a => a;
encodeURIComponent("ああ^〜たまらねえぜ")
// -> ああ^〜たまらねえぜ
このように処理内容を完全に上書きしてしまうことで、エスケープを完全に無力化できてしまう。
を満たしてさえいれば、いとも簡単にインジェクション攻撃ができてしまう。
これ、ちょっと危険すぎない?
そこでパッと思いついた対抗策としては、プロパティを変更すること。
以下の例は、Object.defineProperty
を使うことで書き込みと再設定を禁止してる。
Object.defineProperty(window, "encodeURIComponent", {
writable: false,
enumerable: false,
configurable: false
})
これでひとまず、上書きはできなくなる。
encodeURIComponent("ンアッー!(≧Д≦)")
// -> %E3%83%B3%E3%82%A2%E3%83%83%E3%83%BC!(%E2%89%A7%D0%94%E2%89%A6)
encodeURIComponent = a => a;
encodeURIComponent("ンアッー!(≧Д≦)");
// -> %E3%83%B3%E3%82%A2%E3%83%83%E3%83%BC!(%E2%89%A7%D0%94%E2%89%A6)
Object.defineProperty(window, "encodeURIComponent", {
writable: true, // <-
enumerable: false,
configurable: false
})
// -> Uncaught TypeError: Cannot redefine property: encodeURIComponent
とりあえずこのぐらいしか思いつかなかった。
もし、もっとスマートな方法あったら、Twitterで教えてね。
あと、イチャモンは受け付けない。