【入門編】APIレートリミットの実装:トークンバケットアルゴリズムと分散環境での制御 – アプリケーションセキュリティ & 安全な開発防御ガイド

こんにちは。セキュリティの世界へようこそ。
普段、私たちは「安全なシステムを作ろう」と意気込みますが、現実はなかなか厳しいものです。今日は、新人エンジニアの皆さんが必ずぶつかる「XSS(クロスサイトスクリプティング)」という泥棒の手口と、それを防ぐための「APIの門番(レートリミット)」について、身近な例えを交えて紐解いていきましょう。

—

1. XSSは「あなたの家の鍵を勝手にコピーされること」

まず、XSSについて。教科書的には「悪意のあるスクリプトを注入して…」なんて書かれていますが、もっとシンプルに考えましょう。

XSSは「あなたの家の合鍵を、訪問者に勝手に作られてしまうこと」です。

あなたが自分の家(ブラウザ)に帰ってきたとき、信頼しているはずの郵便受けから「これ、中に入って確認して」と渡されたメモが、実は「家の中の貴重品を外に持ち出すための指示書」だったらどうでしょう?

  • 反射型(Reflected): 通りすがりの人に「これ見て!」と渡されたメモに悪意が仕込まれているタイプ。
  • 格納型(Stored): 掲示板など、家の中に「置き手紙」として保存され、誰かが開くたびに悪意が発動するタイプ。
  • DOM型: メモそのものではなく、家の中の家具の配置(JavaScript)を直接いじって悪さをするタイプ。

防御の鉄則:入力と出力を疑え

家の玄関に「怪しい荷物は預からない」というルール(入力バリデーション)と、「外に出すときは必ず中身をチェックする」(エスケープ処理)という習慣さえあれば、被害は食い止められます。

// 悪い例:受け取ったものをそのまま表示(危険!)
// document.getElementById(‘output’).innerHTML = userInput;

// 良い例:中身をただの文字として表示する(エスケープ)
const div = document.createElement(‘div’);
div.textContent = userInput; // これなら、もしスクリプトが混じっていてもただの文字列として扱われる
document.body.appendChild(div);

—

2. APIレートリミット:門番を配置して「泥棒の居座り」を防ぐ

さて、次は「APIレートリミット」の話です。APIは家の「ドア」のようなもの。一人が一日に100万回ノックしてきたら、あなたは他の用事(本来のユーザーへのサービス)ができなくなりますよね。これがDoS攻撃やブルートフォース攻撃の正体です。

ここで登場するのが「トークンバケット」という考え方です。

トークンバケット:バケツの中のチケット制

想像してください。あなたのドアには「1秒間に1枚だけ配られるチケット」が入るバケツがあります。

1. 誰かがノック(APIリクエスト)する。
2. バケツにチケットがあれば、それを取って入室できる。
3. バケツが空なら「今は混雑しています」と追い返す。

これなら、短時間に過剰なアクセスをする「迷惑な訪問者」を門前払いできますよね。

—

3. 分散環境での実装:Redisという「共有の番犬」

システムが大きくなると、サーバーが複数台に増えます。AサーバーとBサーバーで別々のバケツを持つと、「合計アクセス数」を管理できませんよね。そこで登場するのがRedisです。

Redisは、全サーバーから見える「共有のバケツ置き場」として最適です。

実装のヒント(擬似コード)

import redis

Redisに接続
r = redis.Redis(host=’localhost’, port=6379, db=0)

def can_access(user_id):
key = f”rate_limit:{user_id}”
# バケツの容量(最大5回まで)
limit = 5
# トークンを補充する間隔(60秒)
window = 60

# 現在のカウンタを取得
current = r.get(key)

if current and int(current) >= limit:
return False # バケツが空なら拒否

# カウンタを増やし、期限を設定
pipe = r.pipeline()
pipe.incr(key)
pipe.expire(key, window)
pipe.execute()

return True # 入室許可

—

最後に:セキュリティは「泥棒とのいたちごっこ」ではなく「習慣」

セキュリティ対策は、一度設定して終わりではありません。家の鍵を頑丈にしても、窓が開いていれば意味がないのと同じです。

  • XSS対策: コンテンツセキュリティポリシー(CSP)というヘッダーを使い、「信頼できる場所からのスクリプトしか動かさない」と宣言する。
  • レートリミット: ユーザー単位だけでなく、IPアドレス単位での制限も組み合わせる。

泥棒は「一番弱いところ」を狙います。だからこそ、こうした基本的な対策を積み重ねることが、結果として「この家(システム)は面倒くさそうだな」と攻撃者に思わせる最大の防御になるのです。

一歩ずつで構いません。まずはコードの中に「疑いの目」を取り入れてみてください。それが、最強のエンジニアへの第一歩ですよ!

コメント

タイトルとURLをコピーしました