怖すぎるコードから学ぶ認証でやっちゃいけないことn選
怖すぎるコード
Twitter(旧X)に投稿された怖すぎるコードの何が”怖すぎる”のか言語化してみます。
引用元
コードの文字起こし
該当のコードは以下の通りです。
<!-- todo: put this in a different file!!! -->
<script>
function authenticateUser(username, password) {
    var accounts = apiService.sql(
        "SELECT * FROM users"
    );
    for (var i = 0; i < accounts.length; i++) {
        var account = accounts[i];
        if (account.username === username &&
            account.password === password)
        {
            return true;
        }
    }
    if ("true" === "true") {
        return false;
    }
}
$('#login').click(function() {
    var username = $("#username").val();
    var password = $("#password").val();
    var authenticated = authenticateUser(username, password);
    if (authenticated === true) {
        $.cookie('loggedin', 'yes', { expires: 1 });
    } else if (authenticated === false) {
        $("#error_message").show();
    }
});
</script>
怖すぎポイント
クライアントサイドで認証している
最こわポイントです。クライアントサイドでユーザー認証を完結させると、
- 攻撃者がJavaScriptコードを丸見えで入手・改変可能
- 本来サーバ側で厳重に管理すべき認証情報(ユーザー一覧やパスワード検証処理)をブラウザに晒すことになる
 などの理由から、クライアント側で「認証しているつもり」でも、実質的にまったくセキュリティを担保できません。基本的に漏らしたくない情報はサーバーサイドで扱うようにしましょう。
パスワードをハッシュ化していない
ユーザーのパスワードを平文のまま account.password === password で比較しているため、データベースや通信が漏洩した際に全パスワードが一発で流出します。
安全なアルゴリズム(bcrypt, Argon2など)によるハッシュ処理を行なって、最悪漏れた場合でも攻撃者がパスワードを解読できないようにしましょう。
Cookieに属性をつけていない
発行しているCookieに Secure や HttpOnly フラグが設定されておらず、HTTP経由で盗聴されたり、XSSからクッキーが取得されるリスクがあります。
設定すべきCookieの属性について
- Secure
- Cookieに含まれる認証情報はHTTPS経由でのみ送信されるべきなので"true"にしておく
- "true"にしないと中間者攻撃で盗聴されるリスクがある。
 
- HttpOnly
- JavaScriptから参照できないように"true"にしておく
- "true"にしないとXSSからCookieを盗むことができる。
 
- SameSite
- "Strict"か"Lax"を指定すると、クロスサイトからのCookie送信を制限でき、CSRF抑止にもなります。
 
XSSについて
CSRF対策をしていない
悪意のある第三者サイトを経由したリクエストでもサーバー側で検証できません。CSRFトークンをサーバーサイドで生成して、リクエストに含めて検証することで対策をしましょう。
CSRFとは
総当たり攻撃(ブルートフォース攻撃)対策していない
パスワード試行に回数制限や多要素認証をかけていないため、何度でもパスワードの試し打ちができてしまいます。回数制限か多要素認証を実装して対策しましょう。
総当たり攻撃とは
攻撃者が組み合わせを総当たりで試し、正しい認証情報を見つけ出す攻撃手法です。
特にパスワードが短い・単純な場合に有効で、ボットやスクリプトで何千・何万もの試行を自動化可能です。
SQLインジェクション対策していない
基本的にはサーバーサイドでバインドしながら書きましょう。昨今の著名なORMはだいたいSQLインジェクション対策をしてくれているので、よほどこだわりがない限りは素直にライブラリに頼るのが良いかと思います。
SQLインジェクションとは
Webサイトやアプリケーションの入力欄などに不正なSQL文を送り込み、アプリケーションが想定しないSQLを実行させる攻撃です。
こちらのサイトの説明がわかりやすかったので共有。
https://www.shadan-kun.com/waf_websecurity/sql_injection/#:~:text=SQLインジェクションとは、Web,削除されたりします。
終わりに
他にも色々あるんだと思いますがこのへんで。フレームワークやライブラリがどうにかしてくれていた部分がほとんどなので、意外とこのへんの基礎的な話を忘れていた人もいるんじゃないかって気がします。僕自身も書く過程で確認も含めて改めて調べて、忘れていたり理解ができなかった箇所がところどころあったので、こういう基礎的なことを疎かにせず繰り返し学び直すのは大事だなと思いました。




Discussion