「自社のLinuxサーバーはバッファオーバーフロー攻撃に耐えられるか?」と問われて即答できるエンジニアは多くありません。OSをインストールしただけでは十分でなく、カーネルに組み込まれたエクスプロイト緩和策が正しく有効になっているかを確認することが、現場のセキュリティ管理の基本です。
この記事では、Linuxの主要なカーネルエクスプロイト緩和策(ASLR・NXビット・スタックカナリア・PIE・RELRO)の仕組みを攻撃者の視点から解説し、現場ですぐ確認・設定できるコマンド手順を紹介します。

カーネルエクスプロイト緩和策とは?
カーネルエクスプロイト緩和策(Exploit Mitigation)とは、攻撃者がプログラムの脆弱性を悪用しようとしたときに、その成功率を大きく下げるためにOSやコンパイラが実装した防御機構の総称です。
昔のLinuxには緩和策がほとんど存在せず、バッファオーバーフロー(バッファ(メモリ上の領域)に想定外のデータを書き込んで処理を乗っ取る攻撃)が成功しやすい状況でした。現在は複数の緩和策が多層的に組み合わさっており、攻撃者は1つの技術だけでは目的を達成しにくくなっています。
緩和策は攻撃を「不可能」にするものではなく「著しく困難」にするものです。これが現場で「100%安全ではないが、それでも有効」と言われる理由です。
緩和策が防ぐ攻撃の仕組み(敵を知る)
緩和策の意義を理解するために、攻撃者がエクスプロイトを実行する典型的な流れを把握しておきましょう。
バッファオーバーフロー攻撃を例に挙げると、次のような手順で攻撃が進みます。
(1)プログラムのバッファにデータを大量に書き込み、隣接するメモリ領域(リターンアドレスなど)を上書きする。
(2)書き換えたアドレスに攻撃者が用意したコード(シェルコード)の場所を指定する。
(3)関数が戻るタイミングで実行フローが攻撃者のコードに移り、任意コードが実行される。
この流れでは「バッファに書き込める」こと、「シェルコードが決まったアドレスにある」こと、「スタックが実行可能」であることが前提になります。カーネルエクスプロイト緩和策はこれらの前提を1つずつ崩す仕組みです。
主要な緩和策の仕組みと確認方法
1. ASLR(アドレス空間配置のランダム化)
ASLR(Address Space Layout Randomization)は、プロセスが起動するたびにスタック・ヒープ・共有ライブラリのメモリ上の配置アドレスをランダムに変える仕組みです。攻撃者が「シェルコードはアドレス0x7fff○○○○にある」と決め打ちしてもランダム化されているため、外れる確率が高くなります。
Linuxカーネルは /proc/sys/kernel/randomize_va_space で制御します。
# 現在のASLR設定を確認する cat /proc/sys/kernel/randomize_va_space # 0 = 無効 # 1 = スタック・VDSO・ライブラリのみランダム化 # 2 = スタック・ヒープ・ライブラリをすべてランダム化(推奨)
推奨値は「2」です。RHEL/CentOS/Ubuntu等の主要ディストリビューションでは、デフォルトで2に設定されています。値が0または1になっている場合は、以下のコマンドで変更します。
# 即時変更(再起動で戻るため永続化が必要) sysctl -w kernel.randomize_va_space=2 # 永続化(/etc/sysctl.d/に追加する) echo 'kernel.randomize_va_space = 2' > /etc/sysctl.d/99-aslr.conf sysctl -p /etc/sysctl.d/99-aslr.conf
2. NXビット(実行不可ビット)
NXビット(No-eXecute bit)は、特定のメモリページを「実行不可」に設定するCPUレベルの機能です。スタック領域(データを格納する場所)に攻撃者がシェルコードを書き込んでも、そのページが実行不可になっていれば、コードとして実行されずにセグメンテーション違反(Segfault)で終了します。
IntelはこれをXD(Execute Disable)ビット、AMDはNXビットと呼びます。LinuxではDEP(Data Execution Prevention)とも呼ばれます。
NXビットが有効かどうかは、BIOS/UEFI設定とカーネル起動オプションで確認できます。
# CPUがNXビットをサポートしているか確認 grep -w nx /proc/cpuinfo | head -1 # "nx" が表示されれば対応済み # カーネルがNXを有効化しているか確認 dmesg 2>/dev/null | grep -i "nx\|no-execute" | head -5 # "NX protection: active" 等が出れば有効
クラウド・仮想マシン環境では基本的に有効になっています。オンプレの古いサーバーでBIOSの「Execute Disable Bit」が無効になっている場合は、BIOS設定で有効化してください。
3. スタックカナリア
スタックカナリア(Stack Canary)は、コンパイラが関数のリターンアドレスの手前にランダムな値(カナリア値)を埋め込み、関数が戻る前にその値が改ざんされていないか検証する仕組みです。バッファオーバーフローでリターンアドレスを書き換えようとすると、カナリア値が壊れて異常終了します。
GCCでは -fstack-protector-strong オプションで有効になります。
# バイナリにスタックカナリアが含まれているか確認する例(sshdで確認) readelf -s /usr/sbin/sshd 2>/dev/null | grep -i canary # "__stack_chk_fail" が出ればスタックカナリアあり
システム標準のパッケージ(openssl・openssh等)は通常、ディストリビューションのビルドオプションでスタックカナリアが有効になっています。自社でソースビルドするカスタムアプリがある場合は、コンパイルオプションを明示的に確認してください。
4. PIE(位置独立実行形式)
PIE(Position Independent Executable)は、実行ファイル自体の配置アドレスもASLRでランダム化できるようにするコンパイルオプションです。PIEが有効でないと、実行ファイル本体は固定アドレスに配置されてしまい、ASLRが部分的にしか効かなくなります。
# バイナリのタイプを確認する(PIEの有無) file /usr/sbin/sshd # "ELF 64-bit LSB shared object" と出ればPIE有効 # "ELF 64-bit LSB executable" と出ればPIE無効 # あるいはreadelfで readelf -h /usr/sbin/sshd | grep Type # Type: DYN (Shared object file) → PIE有効 # Type: EXEC (Executable file) → PIE無効
5. RELRO(リロケーション読み取り専用)
RELRO(Relocation Read-Only)は、プログラム起動時にリンカが書き込む再配置情報(GOT: Global Offset Table)を、起動後に読み取り専用にする仕組みです。攻撃者がGOTを書き換えて実行フローを乗っ取る「GOT Overwrite攻撃」を防ぎます。
Partial RELROとFull RELROがあり、Full RELROのほうがより強固です。
# RELROの確認 readelf -l /usr/sbin/sshd 2>/dev/null | grep GNU_RELRO # "GNU_RELRO" セグメントが表示されればRELRO有効
checksecで緩和策を一括確認する方法
個別のコマンドで確認するのは手間がかかります。現場では checksec ツールを使うと、ASLR・NX・スタックカナリア・PIE・RELROをすべて一覧で確認できます。
# Debian/Ubuntu系でのインストール apt install checksec # 使い方(個別バイナリの確認) checksec --file=/usr/sbin/sshd # 使い方(起動中プロセス全体の確認) checksec --proc-all 2>/dev/null | head -30
出力の見方(想定例):
RELRO STACK CANARY NX PIE Full RELRO Canary found NX enabled PIE enabled
4項目すべてに「enabled」や「found」と表示されれば、基本的な緩和策が機能しています。「disabled」や「No canary found」が表示されている場合は対処が必要です。
中小企業でも今日からできること
カーネルエクスプロイト緩和策は「設定すれば終わり」ではなく、継続的な確認が重要です。情シス1人体制でも取り組める具体的な手順を挙げます。
・ASLRの値を月次チェックリストに組み込む: cat /proc/sys/kernel/randomize_va_space の値が2であることを、月次の定期点検作業に追加する。
・自社開発アプリのビルドオプションを見直す: Cで書かれた自社アプリがあれば、コンパイルオプションに -fstack-protector-strong -fpie -pie -Wl,-z,relro,-z,now が含まれているかを開発チームに確認する。
・新規サーバー構築時にchecksecを実行する: サーバー構築後の受け入れ確認として、主要バイナリ(nginx、sshd、業務アプリ)にchecksecを実行し、結果を記録する。
・カーネルを最新に保つ: 緩和策はカーネルバージョンが上がるにつれて改善されています。パッチ適用を遅らせないことが根本的な対策です。
よくある誤解と注意点
【誤解1】「デフォルト設定だから問題ない」
主要ディストリビューションではデフォルトでASLR等が有効ですが、古いバージョンのOSや、組み込み向けLinux、独自ビルドの環境では無効になっている場合があります。「インストールしたから大丈夫」は確認を省いた思い込みです。
【誤解2】「緩和策があれば攻撃は防げる」
これらの緩和策は攻撃を「難しくする」ものであり、「完全に防ぐ」ものではありません。情報漏洩バグ(メモリリーク)でアドレスが特定されると、ASLRを迂回されるケースがあります。緩和策はあくまでも多層防御の1層として位置づけてください。
【注意1】コンパイル済みバイナリは後から変更できない
スタックカナリア・PIE・RELROはコンパイル時に決まります。パッケージ管理システムで配布されている公式バイナリには通常有効になっていますが、古いバイナリをそのまま使い続けているシステムでは確認が必要です。緩和策を追加したければ、対象バイナリをオプション付きで再コンパイルするか、対応パッケージに更新するしかありません。
【注意2】ASLRは32bitシステムでは効果が薄い
32bitシステムはアドレス空間が狭く(最大4GB)、ランダム化の範囲が限られるため、ブルートフォースで突破されやすくなります。64bit環境への移行が根本的な対策です。
権限昇格につながる攻撃チェーンについては、「権限昇格(Privilege Escalation)とは?仕組み・攻撃手口・防御策をわかりやすく解説」もあわせてご参照ください。
Linuxのファイル権限管理の基礎については、姉妹サイトLinuxMaster.JPで詳しく解説しています。

本記事のまとめ
| 緩和策 | 防ぐ攻撃 | 確認コマンド |
|---|---|---|
| ASLR | アドレス決め打ち攻撃 | cat /proc/sys/kernel/randomize_va_space(推奨値: 2) |
| NXビット | スタック上のコード実行 | grep -w nx /proc/cpuinfo |
| スタックカナリア | バッファオーバーフローによるリターンアドレス改ざん | readelf -s バイナリ | grep canary |
| PIE | 実行ファイル本体への固定アドレス攻撃 | file バイナリ(shared object と表示されればOK) |
| RELRO | GOT Overwrite攻撃 | readelf -l バイナリ | grep GNU_RELRO |
カーネルエクスプロイト緩和策は、個別に「これさえあれば」という銀の弾丸ではなく、複数が重なってはじめて攻撃コストを押し上げる多層防御です。まずは cat /proc/sys/kernel/randomize_va_space で自サーバーのASLR状態を確認するところから始めましょう。主要バイナリに checksec を実行して現状を見える化することが、次の一手につながります。
PR
SELinux・PAM・権限管理からカーネルパラメータ設定まで、Linuxサーバーのセキュリティを体系的に学べる実践書。本記事で紹介した緩和策の背景知識を深めたいエンジニアにおすすめです。
