人が書けて、プログラムが書けない — 403の犯人は権限ではなかった

連載「弾かれる」第1回のアイキャッチ

執筆者:

カテゴリ:

記事の下書きを自動で登録する仕組みを使っています。ある日、それが403を返しました。

403は普通、「権限がない」という意味です。ところが同じアカウントで管理画面を開くと、手では問題なく書けます。

この記事で扱うこと

「人が操作すると通るのに、プログラムから叩くと落ちる」状態をどう切り分けたか。権限の問題ではないと判断するまでに確かめた5つと、そこで分かった犯人です。

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

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

最初に疑ったのは、全部はずれだった

思いつく順に確かめました。

疑ったこと 確かめ方 結果
ログインが切れた 自分の情報を取得する問い合わせを投げる 通る。切れていない
権限が足りない 管理画面から同じ操作をする 書ける。足りている
投げ先が違う 一覧の取得を同じ入口に投げる 通る。入口は合っている
記事が壊れている タイトルだけで空の下書きを作る 通る
本文が長すぎる 本文を半分にして投げる 通る

ここで方向が決まりました。同じ人・同じ入口・同じ操作で、本文の中身によって結果が変わっています。

権限の問題なら、中身では変わらない

権限が足りていないなら、空の下書きも落ちるはずです。空なら通って、ある本文だと落ちる。この時点で権限は完全に容疑から外れます。

「403だから権限」と思い込むと、この切り分けに辿り着きません。番号ではなく、何を変えたら結果が変わるかで見るほうが早い。

返ってきたものが、そもそも違った

決定打は、落ちたときの応答の中身でした。

返ってきたもの
通常の権限エラー CMSが作ったJSON。原因を示す符号が入っている
今回 サーバーが作ったHTMLのページ。CMSの符号は一切ない

CMSが断ったなら、CMSの形式で断ります。CMSの言葉で返ってきていないということは、要求がCMSに届く前に止められているということでした。

前段に立っているものがいた

このサイトのCMSは共用サーバーに置いています。そこには、契約時から攻撃を検知して遮断する仕組みが入っていました。

管理画面の設定一覧を見ると、確かに有効になっています。自分で入れた覚えはありません。最初から入っていて、これまで一度も邪魔をしてこなかったので、存在を忘れていました。

自分のサーバーの機能を、自分が知らない

この仕組みは、要求の中身を見て「攻撃の形をしているか」を判定します。判定に引っかかると、CMSに渡さずにその場で断ります。

問題は、断った理由がこちらに見えないことです。何が引っかかったかは教えてくれません。403という数字だけが返ってきます。

引っかかっていたのは、記事の中のサンプルコードだった

落ちていたのは、コードの書き方を説明した記事でした。本文にプログラムの断片が何か所も入っています。

攻撃を検知する仕組みから見ると、プログラムの断片と、送り込まれた攻撃コードの区別がつきません。どちらも同じ形をしています。

つまり、コードの話を書こうとすると落ちるという状態でした。書きたい内容と、守りたい形が正面からぶつかっています。

ここまでで分かったこと

分かったこと
誰が断ったか CMSではなく、その手前にいる遮断の仕組み
何で判定しているか 送った本文の中身
どこが悪いか 不明。教えてくれない

本文は1500文字ほどあります。そのどこか1か所が引っかかっている。読んで探しても、どれも普通のコードにしか見えません。

次回は、この「どこか1か所」を突き止めた方法を書きます。読むのをやめて、機械的に半分ずつ削っていく手順です。

今回の学び

まず、エラーの番号より、何を変えたら結果が変わるかを見るということ。403から権限を疑うのは自然ですが、空の本文で通った時点で権限は関係ありませんでした。変えた条件と結果を並べるほうが、番号を読むより速い。

次に、誰が断ったかは、断り方の形で分かること。CMSが断ればCMSの形式で返ってきます。違う形式で返ってきたということは、そこまで届いていないということでした。中身を見ずに「403だ」で終わらせると、この情報を捨てます。

そして、使っていない機能は、存在ごと忘れること。この遮断の仕組みは契約時から動いていて、これまで一度も邪魔をしませんでした。邪魔をしない期間が長いほど、思い出すきっかけが無くなります。

コメント

コメントを残す

メールアドレスが公開されることはありません。 ※ が付いている欄は必須項目です