こんにちは。セキュリティの世界へようこそ。
普段、私たちは「安全なシステムを作ろう」と意気込みますが、現実はなかなか厳しいものです。今日は、新人エンジニアの皆さんが必ずぶつかる「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アドレス単位での制限も組み合わせる。
泥棒は「一番弱いところ」を狙います。だからこそ、こうした基本的な対策を積み重ねることが、結果として「この家(システム)は面倒くさそうだな」と攻撃者に思わせる最大の防御になるのです。
一歩ずつで構いません。まずはコードの中に「疑いの目」を取り入れてみてください。それが、最強のエンジニアへの第一歩ですよ!
コメント