【入門編】 Serverless環境におけるコールドスタートと実行時間異常の相関分析 – インシデントレスポンス & フォレンジック(DFIR)防御ガイド

こんにちは!SOC(セキュリティ・オペレーション・センター)で日々サイバー攻撃の痕跡を追いかけているアナリストです。

クラウドサービス、特にAWS Lambdaなどに代表される「サーバーレス環境」を活用している開発者の方って、最近本当に増えていますよね。「サーバーの管理をしなくていいから楽チン!」「使った分しかお金がかからないから経済的!」と、まるで自分の家事の手間をすべて自動化してくれる全自動ロボットのような便利さがあります。

でも、ちょっと待ってください。その便利さの裏側で、攻撃者たちは新しいタイプの「泥棒の手口」を虎視眈々と狙っているんです。

今回は、サーバーレス環境で密かに進む「リソース枯渇攻撃」や「不正マイニング(勝手に暗号資産を掘られる被害)」をどう見抜くのか、身近な防犯の仕組みに例えながら、一歩ずつ優しく紐解いていきましょう!

—

1. 家の鍵とサーバーレス:コールドスタートってなに?

まずは、サーバーレスの仕組みを私たちの「家」に例えて考えてみましょう。

通常のサーバー(昔ながらのマンションの1室)は、あなたが家にいようが外出していようが、24時間電気をつけっぱなしにして誰かが帰ってくるのを待ち構えていますよね。これは安心ですが、家賃(サーバー代)がずっとかかります。

一方、サーバーレス(AWS Lambdaなど)は、「普段は電気が消えていて、誰かがインターホンをピンポン!と押した瞬間だけ、パッと部屋の電気がついて対応する」という仕組みになっています。

この「誰もいない状態から、インターホンを鳴らされて急いで部屋の電気をつけて準備する動き」のことを、ITの世界では「コールドスタート」と呼びます。

攻撃者はこの「隙」を突いてくる!

泥棒の立場になって考えてみましょう。誰もいない真っ暗な家に向かって、大量の石を投げつけたり、何百人ものサクラを雇って一斉にインターホンを連打させたらどうなるでしょうか?

家の中の人は「わっ、大変だ!」と、次々に起きてドアを開け閉めしなければならなくなりますよね。サーバーレスの世界でもまったく同じことが起きるんです。

—

2. 実行時間とメモリの異常:泥棒の足音を聞き分ける

攻撃者は、あなたのサーバーレス環境に対して、わざと重くて複雑な計算をさせるプログラム(不正な暗号資産マイニングツールなど)を送り込んだり、膨大なリクエストを送りつけてリソースを枯渇させようとします。

ここで、SOCアナリストである私たちが注目するのが、「実行時間」と「メモリ使用量」の相関関係です。

普段のあなたのプログラムの動きを「ベースライン(平時の状態)」と呼ぶのですが、これは普段の生活リズムに似ています。

  • 朝起きて、朝食を作って、会社に行く(通常の処理:実行時間0.5秒、メモリ使用量120MB)
  • 夜帰ってきて、テレビを見て寝る(通常の処理:実行時間0.3秒、メモリ使用量100MB)

ところが、家に泥棒が入って暴れ回ったり、知らない人が勝手に家の中で重い筋トレを始めたらどうでしょう?

  • 実行時間の急増: いつもなら一瞬で終わるはずの処理に、何十秒も時間がかかっている。
  • メモリ使用量の跳ね上がり: 使える限界ギリギリまでメモリを食い潰している。

ログ分析の現場では、この「いつもと違う時間の長さ(実行時間)」と「使っているパワーの大きさ(メモリ)」が同時に跳ね上がった瞬間を見逃しません。これが、サーバーレス環境における「異常のサイン」なのです。

—

3. ログから異常を検知する!実践的なCloudWatch Logs Insightsクエリ

では、実際にAWSのログ環境(Amazon CloudWatch)を使って、この異常を検知するコード(クエリ)を見てみましょう。

「なんだか難しそうな英語が出てきたぞ…」と思った方も大丈夫です!一緒に一つずつ意味を確認していきましょう。以下のコードは、AWSのログから「実行時間がやたらと長いもの」や「メモリをたくさん使っているもの」を見つけ出すための設定です。

-- AWS CloudWatch Logs Insightsで実行する検知クエリの例
-- 普段とは違う「長時間の実行」や「メモリの大量消費」を探し出します

FIELDS @timestamp, @duration, @maxMemoryUsed, @requestId, @logStream
| FILTER @type = "REPORT"
| STATS 
    count(*) AS 実行回数,
    avg(@duration) AS 平均実行時間_ms,
    max(@duration) AS 最大実行時間_ms,
    avg(@maxMemoryUsed) AS 平均メモリ使用量_MB,
    max(@maxMemoryUsed) AS 最大メモリ使用量_MB
  BY @logStream
-- 実行時間が極端に長い(例: 5000ミリ秒以上)またはメモリを大量消費しているものを抽出
| FILTER 最大実行時間_ms > 5000 OR 最大メモリ使用量_MB > 900
| SORT 最大実行時間_ms DESC
| LIMIT 20

このクエリの優しい解説

1. FIELDS @timestamp, @duration... : ログの中から「時間」「かかった時間(@duration)」「使ったメモリ(@maxMemoryUsed)」などの大切な証拠品を集めています。
2. FILTER @type = "REPORT" : Lambdaが「今回の仕事終わりました!」と報告してくるレポート部分だけに絞り込んでいます。
3. MAX(@duration) > 5000 : 「あれ、今回の仕事、いつもより5秒(5000ミリ秒)以上もかかってるぞ?」という怪しい動きを見つけ出します。
4. MAX(@maxMemoryUsed) > 900 : 「使えるメモリの限界(例えば1024MBの契約)に近い900MB以上もメモリを使ってるぞ?」というリソース枯渇の兆候をあぶり出します。

このように、ログの数字を定点観測することで、人間が気づかない深夜の不正アクセスもバッチリ見つけることができるんです。

—

4. 現場で役立つ!今日からできるインシデント対策

怪しい実行時間の異常を見つけたら、私たちはどう動けばいいのでしょうか?現場の対応手順を優しくステップアップ形式でまとめてみました。

ステップ1:入力値のチェック(バリデーション)を厳しくする

家の玄関の鍵が空けっ放しになっていないか確認するのと同じです。API GatewayやLambdaの入口で、「変なデータ(長すぎる文字列や、不正なコード)」が送られてきていないか、しっかりと門番を置きましょう。

ステップ2:タイムアウト時間を短く設定する

Lambdaの設定で、実行時間の最大値(タイムアウト)を無駄に長くしていませんか?「どう長くても10秒で終わるはずの処理」なら、タイムアウトを10秒に設定しておきましょう。万が一、攻撃者が重いプログラムを送り込んでも、10秒で強制終了(自動的に追い出し)させることができます。

ステップ3:アラート通知を設定する

「もし実行時間が平均の3倍を超えたら、Slackやメールに通知する」という防犯ブザーを仕掛けておきましょう。インシデントレスポンスの基本は「いかに早く気づくか」です。

—

まとめ

今回は、サーバーレス環境におけるコールドスタートと、実行時間・メモリ使用量の相関分析についてお話しました。

便利なクラウドの世界でも、私たちの身の回りにある防犯の考え方はまったく同じです。「いつもと違う音がする」「いつもより時間がかかっている」という違和感(アノマリー)にいち早く気づくことが、サイバー攻撃からシステムを守る最大の秘訣になります。

「難しそう…」と身構えてしまうセキュリティの世界も、一歩ずつ仕組みを紐解いていけば、必ず楽しく理解できるようになりますよ。これからも一緒に安全な開発ライフを守っていきましょう!

コメント

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