Skip to main content

REST APIを安全に保護するには?

著者
blog feature snyk container custom base recommendations

2024年6月27日

0 分で読めます
How to Secure a REST API

開発者は、サードパーティーのシステムと連携したり、業務でフロントエンドとバックエンドのシステムを接続したりする際に、REST APIを扱うことがよくあります。API、特にREST APIは、HTTP経由でデータの作成、読み取り、更新、削除を可能にする、現代のWebアプリケーションに欠かせない存在です。しかし、どのようなテクノロジーにもセキュリティ上の課題があります。ここでは、こうした課題を整理し、REST APIアプリケーションを安全に保護する方法を見ていきましょう。

REST APIとは?

REST(Representational State Transfer)APIは、ネットワークアプリケーションを設計するための一連の規約です。HTTPプロトコルを使ってデータを送受信し、HTTPリクエストを送信できるプログラミング言語であれば、どれでも利用できます。この汎用性の高さから、Web開発で幅広く使われています。

ただし、その汎用性の高さゆえに、サイバー脅威の標的にもなります。OWASPトップ10のプロアクティブコントロールを実装するなど、安全なソフトウェア開発を常に優先しましょう。適切なセキュリティ対策がなければ、REST APIから機密データが漏えいしたり、攻撃者がシステムに侵入する足掛かりになったりするおそれがあります。

REST APIに対する一般的なセキュリティ脅威

開発者が把握しておくべき、REST APIに対する一般的なセキュリティ脅威をいくつか紹介します。

  1. インジェクション攻撃:攻撃者がコマンドやクエリの一部として悪意のあるデータを送り込み、インタープリターをだまして意図しないコマンドを実行させたり、許可されていないデータにアクセスさせたりする攻撃です。たとえばSQLインジェクション攻撃では、APIのデータベースクエリが操作され、データ漏えいや不正なデータ改ざんにつながる可能性があります。

  2. 認証の不備:APIの認証メカニズムが正しく実装されていないと、攻撃者が他のユーザーになりすましたり、管理者権限を取得したりするおそれがあります。2018年のRedditのデータ侵害では、ハッカーがSMSベースの2要素認証を回避しました。

  3. 機密データの漏えい:APIはユーザーの認証情報や個人情報など、機密データを扱うことがよくあります。こうしたデータが適切に保護されていないと、傍受や漏えいが起こり、深刻なプライバシー侵害につながる可能性があります。

  4. レート制限の欠如:レート制限がないAPIは、総当たり攻撃に対して脆弱です。攻撃者がユーザー認証情報を推測したり、システムに過剰な負荷をかけたりするために、リクエストを繰り返し送信する可能性があります。2016年のDynへの攻撃では、これがTwitterやNetflixなどの大手Webサイトをダウンさせた主な要因となりました。レート制限はミドルウェアの一部として実装されることが多く、APIゲートウェイセキュリティのベストプラクティスとされています。

  5. 安全でない依存関係:APIが既知の脆弱性を含むサードパーティーのライブラリやフレームワークに依存している場合、攻撃者に悪用される可能性があります。オープンソースソフトウェアでよく見られる問題です。2017年のEquifaxのデータ侵害では、Apache Strutsの脆弱性が悪用されました。

こうした脅威は、安全なコーディング手法の採用、堅牢な認証・認可メカニズムの実装、機密データの暗号化、そしてSnyk CodeやSnyk Open Sourceなどのツールを使ったコードや依存関係の脆弱性の検出・修正といった、REST APIセキュリティのベストプラクティスに従うことで軽減できます。

以降の章では、こうしたベストプラクティスと、REST APIアプリケーションを安全に保護するための実践方法を詳しく見ていきます。

1. 堅牢な認証・認可メカニズムを実装する

REST APIを保護するうえで、堅牢な認証・認可メカニズムの実装は最初の防御線となります。これにより、認証・認可されたユーザーだけがAPIエンドポイントにアクセスできるようになります。

安全な認証とは、ユーザーが本人であることを確認するプロセスです。REST APIを安全に保護するには、不正アクセスを防ぐため、認証プロセスの安全性を確保することが重要です。たとえば2019年、Facebookで発生したデータ侵害により、約5,000万人のユーザーの個人情報が流出しました。この侵害は認証メカニズムの問題が原因であり、安全な認証の重要性を示しています。

Snyk Codeを使えば、ハードコードされた認証情報やレート制限の欠如など、総当たり攻撃につながりかねないコードベース内の認証関連の脆弱性を検出できます。

OAuth 2.0とJSON Web Token(JWT)の利用

OAuth 2.0は、ユーザーが認証情報を共有することなく、サードパーティーのWebサイトやアプリケーションに自身の情報へのアクセスを許可できるプロトコルです。拡張性とシンプルさから、幅広く利用されています。

認証でよく使われるJSON Web Token(JWT)は、当事者間で情報をJSONオブジェクトとして安全にやり取りするための仕組みです。JWT内の情報はデジタル署名されているため、検証でき、信頼性を確認できます。

Node.jsのREST APIでJWTを認証に使う方法を、以下の例で紹介します。

const jwt = require("jsonwebtoken");

// User login
app.post("/login", (req, res) => {
  // Authenticate user
  // ...

  // Generate JWT
  const token = jwt.sign({ userID: user.id }, "your-secret-key");

  // Return token
  res.json({ token });
});

// Secure endpoint
app.get("/secure", (req, res) => {
  // Get token from headers
  const token = req.headers["x-access-token"];

  // Verify token
  jwt.verify(token, "your-secret-key", (err, decoded) => {
    if (err) {
      return res.sendStatus(403);
    }

    // Access granted
    // ...
  });
});

アクセストークン管理のベストプラクティス

アクセストークンはAPIへの鍵となるため、安全に管理する必要があります。次のベストプラクティスを参考にしてください。

  • トークンの有効期限:アクセストークンの有効期間は短く設定しましょう。トークンが侵害された場合の影響を抑えられます。

  • トークンの保存:アクセストークンをローカルストレージに保存するのは避けましょう。アプリケーションにクロスサイトスクリプティング(XSS)の脆弱性があると、攻撃者が簡単にアクセスできてしまいます。代わりに、セキュリティ属性(SameSite、Secure、HttpOnly)を有効にしたHTTP専用Cookieなど、安全な保存方法を利用しましょう。

  • トークンの送信:トークンは必ず安全なチャネルで送信しましょう。中間者攻撃を防ぐため、HTTPではなくHTTPSを使用してください。

Snyk Open Sourceを使えば、トークン管理に使用するオープンソース依存関係の脆弱性を検出し、既知のセキュリティ脆弱性がないライブラリでアクセストークンを管理できます。アプリケーションセキュリティについてさらに理解を深め、脅威に先手を打つには、Snykの無料アカウントを作成してください。

2. 通信中および保存中のデータを保護する

通信中と保存中の両方のデータを保護することは、REST APIセキュリティの重要な要素です。このセクションでは、データを安全に保つためのベストプラクティスを紹介します。

HTTPS(Hypertext Transfer Protocol Secure)は、あらゆるAPIに欠かせないセキュリティ対策です。クライアントとサーバー間で転送されるデータを暗号化し、攻撃者による傍受を防ぎます。

多くのクラウドベンダーやホスティングインフラサービスでは、REST APIでHTTPSを有効にするためのSSL証明書が無料で提供されています。ただし、内部マイクロサービス間の通信などの理由で、アプリケーションコード内でSSLターミネーションを行う必要がある場合は、PythonパッケージのFlask-SSLify拡張機能を使ってFlaskアプリケーションにHTTPSを強制する方法を、以下の例で確認してください。

from flask import Flask, request
from flask_sslify import SSLify

app = Flask(__name__)
sslify = SSLify(app)

@app.route('/')
def index():
    return "Hello, World!"

if __name__ == '__main__':
    app.run()

上記のPythonコードでは、Flask-SSLify拡張機能を使ってFlaskアプリケーションにHTTPSを強制しています。これは、HTTPSを使ってREST APIを保護する方法の一つです。

データ暗号化の方法

データ暗号化も、REST APIを保護するうえで重要です。攻撃者がデータにアクセスできたとしても、復号キーがなければ内容を読み取れないようにします。

広く使われているデータ暗号化方式の一つがAES(Advanced Encryption Standard)です。AESは、セキュリティと効率性に優れた共通鍵暗号アルゴリズムです。

from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes

key = get_random_bytes(16)
cipher = AES.new(key, AES.MODE_GCM)
plaintext = b'This is a test.'
ciphertext = cipher.encrypt(plaintext)

print('Ciphertext:', ciphertext)

上記のPythonコードでは、PyCryptoDomeライブラリを使い、128ビット鍵とGCM(Galois/Counter Mode)を用いてデータを暗号化しています。

セキュリティにHTTPヘッダーを活用する

HTTPヘッダーを使うことで、REST APIのセキュリティを強化できます。Content Security Policy(CSP)やX-Content-Type-Optionsなどのヘッダーは、一般的なWebの脆弱性の防止に役立ちます。

CSPは、Webページが読み込めるリソースを制御し、クロスサイトスクリプティング(XSS)攻撃を防ぐセキュリティヘッダーです。

X-Content-Type-Optionsもセキュリティヘッダーの一つです。攻撃者がブラウザーをだまして悪意のあるスクリプトを実行させるために利用する、MIMEタイプのスニッフィングを防ぎます。

@app.after_request
def apply_caching(response):
    response.headers["X-Content-Type-Options"] = "nosniff"
    response.headers["Content-Security-Policy"] = "default-src 'self'"
    return response

上記のPythonコードでは、FlaskアプリケーションにX-Content-Type-OptionsヘッダーとCSPヘッダーを設定しています。

Content Security PolicyでXSSなどの脆弱性を防ぐ方法について、ぜひ詳しく読んでみてください。

3. 入力データを検証・サニタイズする

REST APIを安全に保護するための重要な手順の一つが、入力データの検証とサニタイズです。SQLインジェクションなどの攻撃を防ぐうえで欠かせません。

SQLインジェクションは、アプリケーションのデータ入力フィールドの脆弱性を悪用する、一般的なセキュリティ脅威です。攻撃者が入力フィールドを通じて悪意のあるSQLコードを送り込み、SQLクエリを操作すると、データへの不正アクセスや改ざんにつながります。同様に、NoSQLデータベースのクエリに入力フィールドから悪意のあるコードを送り込み、操作するNoSQLインジェクション攻撃も発生します。

Snyk Security Researchチームは以前、人気の高いSquelize ORMライブラリにSQLインジェクション攻撃に対する脆弱性があることを明らかにするセキュリティアドバイザリーを公開しました。これは、入力データを検証・サニタイズし、オープンソースライブラリの脆弱性を監視することの重要性を示しています(Snyk Open Sourceは無料でご利用いただけます)。

入力検証の手法を実装する

こうしたリスクを軽減するには、入力検証の手法を実装することが重要です。入力検証によって、適切な形式のデータだけがシステムに入力されるようにできます。たとえば、ユーザーの年齢に数値を期待する場合、数値以外の入力はシステムで拒否する必要があります。

JavaScriptで入力を検証する簡単な例を紹介します。

function validateAge(age) {
  if (isNaN(age)) {
    throw new Error("Invalid input: age must be a number");
  }
}

さらに、ZodやJoiなどのライブラリを使うと、より堅牢で保守しやすい方法で入力を検証できます。これらのライブラリでは入力データに期待するスキーマを定義し、そのスキーマに照らしてデータを検証します。独自の検証ロジックを記述するよりも高速で信頼性があります。TypeScriptを使う方には、TypeScriptを前提に構築されたZodがおすすめです。

入力検証に加えて、悪意のある入力による有害な影響をなくすために、データをサニタイズする必要もあります。データサニタイズでは、データが有害な形で使われないよう、データを削除または変更します。

JavaScriptでデータをサニタイズする簡単な例を紹介します。

function sanitizeString(str) {
  return str.replace(/<[^>]*>?/gm, "");
}

ただし、正規表現によるサニタイズに頼りすぎないでください。万能ではなく、攻撃者に回避される可能性があります。代わりに、npmエコシステムのvalidator.jsなどのユーティリティライブラリを使いましょう。さまざまな種類のデータに対応した幅広い検証メソッドが用意されています。正規表現を自分で書くと、エッジケースを見落とし、正規表現によるサービス拒否(ReDoS)と呼ばれる脆弱性を招くおそれがあります。Snykは以前、人気の高いUAParser.jsのReDoS脆弱性について詳しく解説しました。

データを一つひとつ手作業で検証・サニタイズするのは骨の折れる作業です。幸い、こうした作業を自動化できるツールがあります。その一つがSnyk Codeです。Snyk Codeは静的アプリケーションセキュリティテスト(SAST)ソリューションであり、入力検証やサニタイズに関するものを含め、コード内の脆弱性の特定と修正を支援します。

4. 安全な依存関係を使用する

REST APIを安全に保護するうえで、アプリケーションが依存するライブラリやパッケージに注意を払うことは重要です。これまでのセクションで、セキュリティ上の脅威に対する脆弱性が見つかった、人気のライブラリやフレームワークをいくつか紹介しました。

このセクションでは、脆弱なライブラリを使うことの危険性、Snyk Open Sourceでこうした脆弱性を検出する方法、そして依存関係を最新の状態に保つための対策について、さらに詳しく説明します。

脆弱なライブラリを使う危険性

依存関係は、アプリケーションを構成する building block のようなものです。しかし、弱いレンガが建物の強度を損なうように、脆弱性のあるライブラリはREST APIに深刻なセキュリティリスクをもたらす可能性があります。

たとえば、2017年に発生した悪名高いEquifaxのデータ侵害は、Java Webアプリケーションを作成するためのオープンソースフレームワークであるApache Strutsの脆弱性が原因でした。この侵害では1億4,700万人分の個人データが流出し、安全な依存関係を使用することの重要性が浮き彫りになりました。

// Example of a vulnerable Apache Struts configuration
<struts>
  <constant name="struts.devMode" value="true" />
</struts>

上記の例では、struts.devModeがtrueに設定されています。これにより機密情報が公開される可能性があるため、本番環境では避ける必要があります。

Apache Strutsの開発モード(devMode)は、開発やデバッグを目的とした機能です。devModeを有効にすると、フレームワークでより詳細なログ記録やエラー報告、設定の再読み込みが可能になります。これらの機能は開発時には役立ちますが、本番環境で有効にすると機密情報が公開されたり、セキュリティ上の脆弱性につながったりする可能性があります。

たとえば、devModeを有効にすると、次のようなリスクがあります。

  • 詳細なエラーメッセージがユーザーに表示され、アプリケーションの構造や基盤となるテクノロジー、さらには悪用される可能性のある具体的なコード行やパスまで明らかになるおそれがあります。

  • 設定が自動的に再読み込みされるため、アプリケーションを再起動せずに動作を変更する目的で悪用される可能性があります。

  • ログ記録や処理の増加によってリソース使用量が増え、パフォーマンスや安定性に影響する可能性があります。

そのため、本番環境ではdevModeをfalseに設定し、こうしたリスクを軽減することがセキュリティのベストプラクティスとされています。

Snyk Open Sourceで脆弱性のある依存関係を検出する

脆弱性のあるライブラリの使用リスクを軽減するには、脆弱性を検出して管理するための堅牢な仕組みが欠かせません。そこで役立つのがSnyk Open Sourceです。

Snyk Open Sourceは、オープンソースの依存関係にある脆弱性を特定し、修正するためのツールです。既知の脆弱性を網羅したデータベースを備え、依存関係を継続的に監視して新たなリスクを通知します。

# Example of using Snyk Open Source to scan your project for vulnerabilities
snyk test

上記の例では、snyk testコマンドでプロジェクトをスキャンして脆弱性を検出し、修正に向けた具体的なアドバイスを得られます。スキャン結果はターミナル(またはSnykのWebインターフェースを使用している場合はSnykダッシュボード)に表示され、脆弱性の詳細や深刻度、推奨される修正方法が示されます。以下は、脆弱性のあるバージョンのApache Strutsを使用しているSpring Javaアプリケーションの出力例です。

Testing /path/to/your/project...

✗ High severity vulnerability found in org.apache.struts:struts2-core@2.3.20
  Description: Remote Code Execution
  Info: https://snyk.io/vuln/SNYK-JAVA-ORGAPACHESTRUTS-31560
  Introduced through: org.apache.struts:struts2-core@2.3.20
  From: org.apache.struts:struts2-core@2.3.20 > org.apache.struts:struts2-core@2.3.20
  Remediation:
    Upgrade direct dependency org.apache.struts:struts2-core@2.3.20 to org.apache.struts:struts2-core@2.3.24

Tested 123 dependencies for known vulnerabilities, found 1 vulnerabilities, 1 vulnerable paths.

依存関係を最新の状態に保つための戦略

依存関係を最新の状態に保つことは、REST APIのセキュリティを確保するうえで重要です。依存関係を効果的に管理するための戦略をいくつかご紹介します。

  1. 定期的に更新を確認する:依存関係の更新を定期的に確認する習慣をつけましょう。手動で確認するほか、Snykのように確認を自動化するツールも利用できます。

  2. バージョン管理の方針を決める:最新機能の必要性とアプリケーションの安定性のバランスが取れた方針を採用しましょう。セマンティックバージョニングは、変更の種類や規模をバージョン番号で伝える、広く使われている方法です。

  3. 可能な場合は更新を自動化する:依存関係の更新を自動化すると、時間を大幅に節約でき、人的ミスのリスクも軽減できます。Snykでは、安全なアップグレードやパッチのプルリクエストを自動で作成するよう設定できます。

# Example of using Snyk to automate dependency updates
snyk monitor

上記の例では、snyk monitorコマンドでプロジェクトを継続的に監視し、安全なアップグレードやパッチのプルリクエストを自動で作成します。こうしたベストプラクティスを実践すれば、依存関係がREST APIのセキュリティにおける弱点になるのを防げます。「REST APIをどうすれば安全にできるか」を考えるときは、細部まで気を配ることが重要です。安全な依存関係は、そのために欠かせない要素です。

REST APIのセキュリティ確保は、入力データの検証やサニタイズだけではありません。定期的な監視と更新が必要な、継続的なプロセスです。こうしたベストプラクティスを実践し、Snykのようなツールを活用することで、REST APIのセキュリティを大幅に強化できます。

REST APIのセキュリティ対策を始めませんか?今すぐSnykに登録しましょう。

続きを読む

Blog

フロンティアモデルは脆弱性を発見した。攻撃者だけがエクスプロイトチェーンを見つけた。

静的解析で欠陥は見つかりましたが、ライブ攻撃テストで侵害につながる連鎖を実証できたのは唯一でした。Evo COS、Claude Security、Claude Code Securityを比較します。

feature insights context
Blog

自律型攻撃はすでに始まっている。防御もそのスピードに追いつかなければならない。

自律型攻撃者によって、防御に使える時間は短くなっています。継続的な検出、修復、検証、予防で、セキュリティチームが攻撃に歩調を合わせる方法をご紹介します。

Blog

AIコーディングエージェントが不適切なアクセス制御を繰り返し実装する理由

AIコーディングエージェントは、コンパイルが通りレビューも通過する一方で、あるテナントのデータを別のテナントに公開してしまう認可ロジックを生成することがあります。不適切なアクセス制御が検出しにくい理由と、その防止策をご紹介します。