Webアプリ開発者も他人事じゃない バッファオーバーフロー攻撃の概要と対策
バッファオーバーフローとは、攻撃者によってメモリ上に確保したバッファを超えて書き込みが行われる問題(脆弱性)であり、この問題を利用した攻撃手法を指します。
別名としてバッファオーバーランとも呼ばれます。
バッファオーバーフローの脆弱性を軽減するには、攻撃者がどのようにして悪用するのか、またどのような危険性があるのか、理解することが重要です。
本記事では、バッファオーバーフロー攻撃についての概要と対策方法について、Web アプリケーション開発に携わっている視点から解説していきます。
バッファオーバーフロー攻撃はどのようにして発生するのか
バッファとは、データが 1 つの場所から別の場所に転送する際に、データを一時的に保持するメモリストレージ領域のことをいいます。
プログラムがデータをバッファに書き込もうとした際に、データの量がメモリバッファのストレージ容量を超えてしまうと、隣接するメモリ位置を上書きしてしまいます。
この結果発生する事象をバッファオーバーフロー(バッファオーバーラン)と呼びます。
攻撃者は、アプリケーションのメモリを上書きすることにより、バッファオーバーフローの問題を悪用します。
これにより、プログラムの実行パスが変更され、ファイルを損傷したり、誤って個人情報にアクセスできるレスポンスが返ってくることがあります。
攻撃者は追加のコードを導入し、新しいコマンドをアプリケーションに送信することで、IT システムにアクセスする可能性もあります。
攻撃者がプログラムのメモリレイアウトを知っている場合、バッファに収まりきらない入力データを意図的に用意し、実行可能なコードが格納されているメモリ領域を上書きして、独自のコードに置き換えることができます。
たとえば、攻撃者はポインター(メモリ内の別の領域を指すオブジェクト)を上書きすることで、プログラムの動作をコントロールできてしまうのです。
バッファーオーバーフローが発生する仕組み
バッファオーバーフロー攻撃の種類
バッファオーバーフローを利用した攻撃としては、著名なもので以下の 2 種類が挙げられます。
スタックバッファオーバーフロー(Stack-based)
スタックを標的とした攻撃と呼ばれるもので、最も一般的な攻撃手法になります。
関数の実行時にのみ存在するスタックメモリを活用します。
ヒープベースのバッファオーバーフロー(Heap-based)
現在のランタイム操作に使用されているメモリを超えて、プログラムに割り当てられたメモリ空間をオーバーフローさせる攻撃手法です。
「ヒープを標的とした攻撃」とも呼ばれます。
その他には、静的領域を標的とした攻撃があります。
攻撃を成功させるためには、上記の攻撃手法と、プログラムの動作とメモリ内部のレイアウトがどのようになっているか、把握しておく必要があります。
どのようなプログラミング言語で発生しやすいのか
C 言語および C++ は、メモリ内のデータの上書きやアクセスに対する保護機能が備わっていないため、バッファオーバーフロー攻撃の影響を非常に受けやすい言語です。
メモリ管理を適切に行わないと、バッファオーバーフローの問題につながります。
昨今の Web アプリケーション開発で用いられる Java や PHP、Ruby、Python といった言語では、バッファオーバーフローの可能性を最小限に抑える安全策が言語の内部に備わっています。
開発者が実装を行う際にメモリアクセスを意識する必要がなく、バッファオーバーフローについての知識を特段持たなくとも開発ができます。
ただしプログラミング言語によっては、言語の内部で C 言語や C++ が使われていることもあり、言語の内部にバッファオーバーフローの脆弱性が潜んでいるケースが存在します。
たとえば PHP というプログラミング言語は、内部では C 言語を使って開発が行われています。
ChangeLog ページ を見てみると、バッファオーバーフローの脆弱性が発見されて、修正対応を行った記録が見受けられます。
直近では CVE-2020-7060 はバッファオーバーフローに関連した脆弱性です。
PHP のバージョンが 7.2.27 より前の 7.2.x 系, 7.3.14 より前の 7.3.x 系, 7.4.2 より前の 7.4.x 系をお使いの方は、対応が必要です。
また、JavaScript の実行環境である Node.js も内部では C 言語が利用されているため、バッファオーバーフローの脆弱性が報告されることがあります。
September 2020 Security Releases で公開されている CVE-2020-8252 はバッファオーバーフローの脆弱性で、こちらのコミットで修正され、バージョン 10.22.1, 12.18.4, 14.9.0 で修正されています。
一例として PHP と Node.js を挙げましたが、Ruby や Python についても、本体や周辺モジュールが C 言語で記述されている部分があり、本体にバッファーオーバーフロー脆弱性が含まれているバージョンが存在しています。
ライブラリに潜むバッファオーバーフロー
PHP や Node.js といったプログラミング言語本体や実行環境以外に PyPI や npm が提供するライブラリでも同様に内部で C 言語が利用され、バッファオーバーフローの脆弱性が報告されているものがあります。
Python の画像処理ライブラリの Pillow でも CVE-2020-10379 としてバッファオーバーフローの脆弱性が報告され、バージョン 7.1.0 で修正されています。
修正コミットを見てみると、src/libImaging/TiffDecode.c というファイルが修正されていることから、内部で C 言語が使われていることが確認できます。
Node.js で利用できる画像処理ライブラリの node-canvas も内部では C++、C 言語が多く利用されており、CVE-2020-8215としてバッファオーバーフローの脆弱性が報告されています。
「Python や JavaScript のライブラリならバッファオーバーフローのリスクはない」と思われがちではありますが、一部の画像処理、機械学習ライブラリなどでは内部で C++ や C 言語が使われているケースもあるため、影響を受けることがあります。
どのような対策を行えば良いのか
バッファオーバーフローの脆弱性が、言語の本体やライブラリの内部にも潜んでいるケースがあることをご紹介しました。
脆弱性というリスクがある以上、解決するための対策を行うことが不可欠です。
Web アプリケーション開発者がとりえる有効な対策として、ミドルウェアや OS レイヤーで使われているソフトウェアを最新の状態に保ち続けること、いわゆる「パッチ管理」を行っていくことが挙げられます。
先述した PHP や Ruby、Python については、脆弱性情報を日々チェックして最新バージョンにアップデートしていくことが必要不可欠です。
利用しているライブラリに関しても内部では C や C++ が使われていることもあるため、同様にパッチ管理することが重要となります。
言語本体、ライブラリのアップデートはもちろんのこと、ミドルウェア・OS パッケージについても定期的に最新バージョンへアップデートが行える仕組みを構築していきましょう。
さいごに
昨今の Web アプリケーション開発においては、C や C++ で直接開発する機会はほとんどないため、バッファオーバーフローの脆弱性は Web アプリケーション開発の観点でいえば無縁なものと思われたかもしれません。
Web アプリケーション開発者としてはなかなか意識が向かない部分かもしれませんが、無縁とは決していえないことがお分かりいただけたかと思います。
言語の内部(インタープリター)や一部のライブラリに脆弱性が発見される可能性があるのは事実です。
利用しているサーバにインストールされたソフトウェアや OS の種類、バージョンを把握し、日頃からセキュリティに関わる情報収集に努め、問題が発表された際は速やかにアップデートを行えるように、運用体制を確立しておくことが重要です。
最後に、yamory ではアプリケーションライブラリの脆弱性検出から対応までを一元的に管理できるサービスとして提供しております。
無料トライアルもできますので、一度お試しいただけると幸いです。