タグ: 弾かれる

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

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

    記事の下書きを自動で登録する仕組みを使っています。ある日、それが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だ」で終わらせると、この情報を捨てます。

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