こんにちは!サーバーレス開発の世界へようこそ。
「サーバーの管理がいらない」「使った分だけお支払い」という夢のような技術、AWS Lambdaなどのサーバーレス関数。初心者の方や開発者の方にとって、これほど心強い味方はありませんよね。
でも、ちょっと待ってください。実はこの「便利さ」の裏側に、泥棒(攻撃者)がこっそり狙っている「開けっぱなしの窓」があることをご存知でしょうか?
今日は、世界中のシステムに潜り込むレッドチーム(攻撃側)の視点から、サーバーレス特有の弱点である「タイムアウト」と「同時実行数」について、お家の防犯に例えて優しく紐解いていきましょう。
—
1. サーバーレスは「時給制の家政婦さん」?
まず、サーバーレス関数(Lambdaなど)をイメージしてみましょう。
例えるなら、「必要な時だけやってきて、働いた秒数分だけお給料を払う家政婦さん」です。
通常、家政婦さんは「お掃除して」と頼めば、数分で終わらせて帰っていきます。
しかし、もし悪い人が「家政婦さんをずっと拘束して、お給料を無駄に払わせよう」と考えたらどうなるでしょうか?
攻撃者の狙い:お財布を空にする「EDoS」攻撃
従来のサーバー攻撃は「サイトを動かなくさせる(DoS)」が主流でした。しかし、サーバーレスの世界では「EDoS(Economic Denial of Service)」、つまり「お財布を空っぽにさせる攻撃」が猛威を振るいます。
攻撃者は、わざと処理に時間がかかるようなゴミデータを送ったり、返事をわざと遅らせたりして、あなたの家政婦さん(Lambda)を限界(タイムアウト)まで引き留めます。すると、何もしていないのに高額な請求だけがあなたに届くことになるのです。
—
2. 「タイムアウト設定」は、家政婦さんへの「門限」
では、どうすれば守れるのでしょうか?
一番大切なのは、「タイムアウト(門限)」を適切に設定することです。
多くの人が、念のため……とタイムアウトを長め(例:5分や15分)に設定してしまいがちですが、これは「泥棒さん、15分間好きなだけ居座っていいですよ」と言っているようなものです。
対策のポイント:必要最小限の時間を攻める
もし、その処理が普段1秒で終わるものなら、タイムアウトは「3秒」や「5秒」で十分ですよね。
# AWS CloudFormation (SAM) での記述例
MySafeFunction:
Type: AWS::Serverless::Function
Properties:
Handler: index.handler
Runtime: nodejs18.x
# 【ここが重要!】タイムアウトを必要最小限に設定します。
# 15分(900秒)ではなく、例えば「10秒」に絞ることで、
# 万が一攻撃されても被害を最小限(10秒分の料金)に抑えられます。
Timeout: 10
MemorySize: 128
このように「門限」をピシッと決めておくことで、家政婦さんが変な男(攻撃者)に捕まっても、10秒経てばサッと帰ってこられるようになります。
—
3. 「同時実行数」は、お家の「同時入居人数」
タイムアウトを絞っても、まだ安心はできません。
泥棒は次に、「1,000人の偽の依頼主」を一気に送り込んできます。
あなたの家政婦サービスに1,000人の依頼が一気に来たら、会社はパニックになり、本当に助けが必要なあなたの声が届かなくなってしまいます。これがリソースの枯渇です。
対策のポイント:同時実行制限(予約された同時実行)
これを防ぐのが「同時実行数の制限」です。
「うちの家政婦さんは、最大でも同時に5人までしか働かせません!」とルールを決めておくのです。
# AWS CloudFormation (SAM) での記述例
MySafeFunction:
Type: AWS::Serverless::Function
Properties:
Handler: index.handler
# 【ここが重要!】同時実行数を制限します。
# これにより、攻撃者が1万回同時に呼び出しても、
# 5回分以上のリソース(とお金)は消費されません。
ReservedConcurrentExecutions: 5
これを設定しておけば、もし泥棒が嫌がらせをしても、被害は「5人分」で止まります。他のお家(他の機能)に迷惑がかかることもありません。
—
4. 現場の知恵:防御力を高める「一言」
レッドチームとして多くの現場を見てきた私から、皆さんにぜひ覚えておいてほしい「防犯のコツ」がもう一つあります。
それは、「中身をしっかり確認してから、作業を始める」というプログラムの書き方です。
悪い例(泥棒を家に入れてから考える)
exports.handler = async (event) => {
// どんなに重いデータが来ても、とりあえず受け取って処理を始めてしまう
// → これだと、タイムアウトまで時間を稼がれてしまいます。
await longRunningTask(event.body);
};
良い例(玄関先で追い返す)
exports.handler = async (event) => {
// 1. 玄関先で「変な荷物(異常なデータ量)」を持っていないかチェック!
if (!event.body || event.body.length > 1000) {
console.log("怪しい荷物を持った客を拒否しました。");
return { statusCode: 400, body: "Invalid Request" };
}
// 2. 問題なければ、短い制限時間(タイムアウト)の中で素早く作業
return await quickTask(event.body);
};
このように、「入り口でチェックする」だけで、あなたのサーバーレス関数は驚くほど強固になります。
—
まとめ:一歩ずつ、安全なクラウド生活を!
セキュリティと聞くと「難しそう……」と感じるかもしれませんが、その本質は「お家の戸締まり」と同じです。
1. タイムアウト(門限)を短くする
2. 同時実行数(最大人数)を制限する
3. 変な荷物(不正なデータ)は玄関で断る
この3つを意識するだけで、あなたはもう立派な「防犯意識の高いエンジニア」の仲間入りです!
クラウドの世界は広くて便利ですが、油断していると見えないところでお金やリソースが逃げていってしまいます。「自分の身は自分で守る」という少しの工夫で、安心・安全な開発を楽しんでいきましょう。
もし分からないことがあっても大丈夫。一歩ずつ、一緒に学んでいきましょうね!
コメント