BadUSBを阻止する:USBGuardによるLinuxの要塞化、6ヶ月間の運用経験

Security tutorial - IT technology blog
Security tutorial - IT technology blog

おそらく見過ごされている物理セキュリティの隙間

私たちは、ネットワーク層を保護するために、高価なファイアウォールやSSHの要塞化、WAFに多額の費用を投じています。しかし、半年前のエッジコンピューティングノードの定期的なセキュリティ監査中に、物理ポートが完全に無防備であることに気づきました。15ドルのDigisparkボードやHak5のRubber Duckyは、キーボードをエミュレートし、毎分1,000語以上の速度でリバースシェルを注入できます。攻撃者が3秒間物理的にアクセスできれば、ソフトウェア側の暗号化は役に立ちません。

この穴を塞ぐために、本番環境全体にUSBGuardを導入しました。USBGuardは、厳格なホワイトリスト/ブラックリストポリシーを適用することで、不正なUSBデバイスからシステムを保護する強力なソフトウェアフレームワークです。半年間これらのポリシーを管理し、42件の不正接続試行をブロックした経験から、自分自身を締め出すことなくサーバーをロックダウンするために必要なワークフローを洗練させました。

5分で完了するロックダウン

数分で基本的な防御を構築できます。この設定では、キーボードやYubiKeyなどの現在接続されている周辺機器の動作を維持しつつ、新しいUSBデバイスをすべてブロックします。

1. インストール

USBGuardは、主要なほとんどのLinuxディストリビューションの標準リポジトリで利用可能です。

# Ubuntu/Debianの場合
sudo apt update && sudo apt install usbguard

# CentOS/RHEL/Fedoraの場合
sudo dnf install usbguard

2. 初期ポリシーの作成

単にサービスを開始してはいけません。そうすると、デフォルトのポリシーによってキーボードの接続が即座に切断される可能性があります。代わりに、現在マシンに接続されているデバイスに基づいてルールセットを生成します。

# 現在のハードウェア構成をスナップショットとしてポリシーファイルに保存する
sudo usbguard generate-policy > /etc/usbguard/rules.conf

3. デーモンの起動

ポリシーを保存したら、サービスを有効にして、再起動後も設定が維持されるようにします。

sudo systemctl enable --now usbguard

この瞬間から、手動で許可しない限り、カーネルはサーバーに接続された新しいデバイスをすべて無視します。

実際に機能するルールの作成

rules.confファイルは防御の要です。導入後の1ヶ月で、高セキュリティゾーンでは単に「許可」するだけでは不十分であることを学びました。高度ななりすましを防ぐには、より具体的な指定が必要です。

ルールの構文解説

本番環境グレードのルールは以下のようになります:

allow id 0951:1666 serial "0014857749E5F831171E01D7" name "DataTraveler 3.0" hash "asdf..." with-interface 08:06:50
  • Target(ターゲット): 信頼できる機器にはallow、無視するにはblock、ツリーから論理的に削除するにはrejectを使用します。
  • ID: ベンダーIDとプロダクトIDです。便利ですが、BadUSBデバイスによって簡単に偽装されます。
  • Serial(シリアル): 必ずシリアル番号を含めてください。特定の管理者用ハードウェアを検証するために不可欠な層となります。
  • With-interface(インターフェース制限): これが最強の防御策です。デバイスを特定の機能に制限します。例えば、USBヘッドセットのオーディオインターフェースは許可しつつ、隠されたキーボードエミュレーション機能はブロックすることができます。

ハッシュ化が不可欠な理由

特に機密性の高いサーバーでは、hash属性を使用しています。USBGuardはデバイスのバイナリ記述子のハッシュを計算します。攻撃者が管理者のフラッシュドライブのIDとシリアルを複製しても、内部ファームウェアが異なればハッシュが一致しません。その結果、デバイスはブロックされたままになります。

現場でのデバイス管理

運用環境では、設定ファイルを手動で編集すべきではありません。usbguard CLIを使用して、動的にハードウェアを管理します。データセンターの技術者がメンテナンス用ドライブを接続する必要がある場合は、次の3つのステップに従います。

1. ブロックされたデバイスの特定

sudo usbguard list-devices

「blocked」とマークされたエントリを探します。デバイスID(例:5)が表示されます。

2. 一時的アクセス vs 恒久的アクセス

次の再起動までアクセスを許可するには、以下を使用します:

sudo usbguard authorize-device 5

ホワイトリストに恒久的に追加するには、-pフラグを使用します:

sudo usbguard allow-device 5 -p

設定のセキュリティを確保する

USBGuardの強度は、その設定自体のセキュリティに依存します。/etc/usbguard/usbguard-daemon.confを確認し、rootユーザーまたは特定の管理者グループのみがルールを変更できるようにしてください。これらのシステムに管理者パスワードを設定する場合は、プロセス中に認証情報が漏洩しないよう、toolcraft.appにあるパスワード生成のようなローカルのみで動作するツールを使用することをお勧めします。

本番運用6ヶ月で得た教訓

厳格なUSBポリシーへの移行は、必ずしもスムーズとは限りません。以下の4つのヒントは、深夜にデータセンターへ駆け込む事態を防いでくれるはずです。

1. キーボードの締め出しは本当に起こる

物理ハードウェアを管理している場合、キーボードもUSBデバイスです。キーボードを抜いた状態でポリシーを生成すると、サービスが開始された瞬間にローカルコンソールから締め出されます。Enterキーを押す前に、rules.confにHID(Human Interface Device)のエントリが含まれているか必ず再確認してください。

2. USBハブに注意

USBGuardはハブを個別のデバイスとして扱います。ハブをブロックすると、そのハブに接続されているデバイスのルールに関係なく、すべてのポートが使用不能になります。私は通常、マザーボード内蔵のハブはallow(許可)し、外部の未認証ハブはすべてblock(ブロック)しています。

3. 監査ログの集約

ブロックされたUSBデバイスはセキュリティイベントです。私はUSBGuard’のログを中央監視システムに転送しています。これにより、未認証のデバイスがサーバーに接触した瞬間にセキュリティチームにアラートが飛びます。以下のコマンドで、ローカルでイベントを監視することもできます:

journalctl -u usbguard -f

4. 能動的防御には「Reject」を使用する

blockコマンドは単にデバイスの動作を停止させますが、rejectコマンドはカーネルに論理的な切断を指示します。これは、OSに対してデバイスが意図的に拒否されたという明確な信号を送るため、トラブルシューティングにおいて非常に有用です。

要塞化された設定テンプレート

私が本番環境で使用している/etc/usbguard/usbguard-daemon.confの設定は以下の通りです:

  • ImplicitPolicyTarget=block: ルールがない場合は、すべて遮断する。
  • PresentDevicePolicy=keep: サービス再起動時に、現在接続されているキーボードの接続を維持する。
  • IPCAllowedGroups=wheel: wheelグループの管理者のみが新しいハードウェアを承認できる。

USBGuardは、私たちの物理的な攻撃対象領域を劇的に縮小させました。新しいハードウェアを追加する際に多少の手間は増えますが、それによって得られるセキュリティ上のメリットは計り知れません。これでようやく、サーバーラックへの物理的なアクセス権を誰が持っているかについて、過度に心配する必要がなくなります。

Share: