KiSAKU
技術系約4分で読めます

エスケープすれば通る、が通らなかった理由

公開

引っかかる文字の並びが2つ分かりました。次に考えたのは、それを別の書き方で送れば通るのではないかということです。

結論から書くと、通りませんでした。そしてその理由を知ったとき、通らなくてよかったと思いました。

この記事で扱うこと

「表示は同じで、送る文字だけ変える」という手がなぜ効かなかったか。判定する側が照合の前に何をしているか。そして、もし通っていたら何を意味するかです。

連載「弾かれる」(全5回)

第1回:症状の切り分け/第2回:二分探索で原因を絞る/第3回:エスケープが効かなかった理由(この記事)/第4回:意味を変えずに書き直す/第5回:正しく止められたときに何を残すか

思いついた手

HTMLには、文字を番号で書く方法があります。記号そのものを書く代わりに、その文字の番号を決まった形で書くと、表示するときに元の記号に戻ります。

送る文字列 ブラウザでの見え方
そのまま 記号そのもの 記号
番号で書く 記号とは違う数字の列 同じ記号

つまり、読者が見るものは変えずに、サーバーへ送る文字列だけを変えられます。引っかかる並びは送られないので、これで通るはずでした。

変換する処理を書いて、全部の記事に当てて、投げました。

同じところで落ちた

403です。変換していないときと、まったく同じでした。

念のため確かめました。変換後の文字列には、引っかかる並びは1文字も含まれていません。それでも落ちます。

照合の前に、元に戻されている

調べると、この手の判定には前処理があります。照合する前に、番号で書かれた文字を元の記号に戻してから見る、という処理です。

こちらが番号に変えて送っても、判定する側は戻してから照合しています。見ているものは、変換する前と同じでした。

他の逃げ方も同じ理屈で塞がっています。大文字と小文字を混ぜる、余計な空白を挟む、別の方式で符号化する。どれも、照合の前に揃えられます。

こちらの手 判定側の前処理 結果
文字を番号で書く 元の文字に戻す 効かない
大文字小文字を混ぜる どちらかに揃える 効かない
余計な空白を挟む 詰める 効かない
別の方式で符号化する 復号する 効かない

通っていたら、それは穴だった

ここが、この一件でいちばん納得した部分です。

自分がやろうとしたのは、「判定に引っかからない形に変えて、受け取った側で元に戻してもらう」ことでした。

これは、攻撃する側がやりたいことと完全に同じです。

やること 狙い
自分 記号を番号に変えて送る 判定をすり抜けて、記事を登録したい
攻撃する側 記号を番号に変えて送る 判定をすり抜けて、コードを実行したい

手口が同じなので、自分だけ通る理由がありません。もしこの手で通っていたら、それは同じ手で攻撃も通るということでした。

迂回できてしまったら、喜ぶ場面ではない

止められている側にいると、通る方法を見つけたときに前進した気分になります。

ただ、止めている理由が正しいなら、通る方法は穴です。自分が使えたということは、他の人も使えます。今回は前処理があったので塞がっていました。無かったら、この防御はほぼ意味を持っていません。

方針を変えた

ここで、やろうとしていたことの向きを変えました。

考え方 成り立つか
それまで 同じ内容を、判定に見つからない形で送る 成り立たない。成り立ったら穴
ここから 判定に引っかからない内容に書き直す 成り立つ

違いは、隠すか、書き換えるかです。隠す方向は、うまくいってもいかなくても困ります。書き換える方向なら、書いたものがそのまま通ります。

次回は、実際にサンプルコードをどう書き直したかを書きます。意味を変えずに形だけ変える手が3つありました。

今回の学び

まず、見た目を変えて通す手は、たいてい先に塞がれているということ。番号で書く、大文字小文字を混ぜる、空白を挟む。どれも攻撃する側が先に試した手なので、判定する側は照合の前に揃えてから見ています。

次に、迂回できたかどうかで、防御の質が測れること。自分の手が通ってしまったら、同じ手で攻撃も通ります。塞がれていたのは、その防御がきちんと作られていたということでした。

そして、隠す方向と書き換える方向は別物だということ。同じ内容を見つからない形で送るのは、成功しても困ります。内容そのものを別の形にするほうは、通ったものがそのまま残ります。向きを変えるまで、ずっと塞がった側を押していました。

この記事を共有する

Xでポストはてブ
← ブログ一覧へ戻る