LoginSignup
5
3

More than 1 year has passed since last update.

hardening のための sysctl と カーネル起動オプションと kconfig

Last updated at Posted at 2021-12-01

Linux advent カレンダー の二日目です。一日目は hoglet氏の Linux入門 1-2 各コマンドとviコマンドの基本です。基本的にemacsを使っていますが、viも1億行程度のテキストファイルでも問題なく編集できるので重宝しています。

Hardening とは堅牢化です。非root一般ユーザーがroot権限を奪取したり、アカウントを持たない攻撃者がネットワーク経由でLinuxを操作する手段を減らすのが主な目的です。Debian を前提にしていますが他のディストロでも使えることは多いはずです。Linux 5.15とARM64とIntel/AMD64で使えることを確認済み。性能の低下に気づくようなhardeningは避けています。以下の設定をラズパイ4を用いて、1Gbit光回線でIPv4 over IPv6変換器を作っても、 https://minsoku.net を用いて回線速度を無駄なく使い切れてることを確認しています。

sysctl を用いたhardening

以下の内容を /etc/sysctl.d/local.conf に書いておくと次回の起動以降で有効になります。

TCP/IP以外

kernel.randomize_va_space=2
アドレス空間配置のランダム化 を行う
vm.mmap_rnd_bits=32
vm.mmap_rnd_compat_bits=16
アドレス空間配置をよりランダムにする
vm.mmap_min_addr=32678
アドレス空間の最初の32 KiBを使わないようにする
net.core.bpf_jit_harden=2
kernel.unprivileged_bpf_disabled=1
BPFを安全にする
vm.unprivileged_userfaultfd=0
root以外がuser fault fd機能を使わないなら0にしたほうがよい
fs.protected_hardlinks=1
fs.protected_symlinks=1
fs.protected_fifos=2
fs.protected_regular=2
/tmp などの誰でも書けるディレクトリにあるファイルやFIFOを保護する

TCP/IP関連

net.ipv4.conf.default.rp_filter=1
net.ipv4.conf.all.rp_filter=1
net.ipv4.conf.default.accept_source_route=0
net.ipv4.conf.all.accept_source_route=0
net.ipv4.conf.default.arp_announce=1
net.ipv4.conf.all.arp_announce=1
net.ipv4.conf.default.arp_ignore=2
net.ipv4.conf.all.arp_ignore=2
net.ipv6.conf.default.accept_source_route=0
net.ipv6.conf.all.accept_source_route=0

説明は https://www.kernel.org/doc/html/latest/networking/ip-sysctl.html を参照

カーネル起動オプションを用いたhardening

grub を用いて起動している場合(AMD/Intel) ときは /etc/default/grub の内容を編集して update-grub を実行すると次回起動時のカーネル起動オプションに反映される。ラズパイの場合は起動パーティションにある cmdline.txt を編集する。

init_on_alloc=1
あるプロセスが新たに獲得したメモリ領域をゼロで初期化し、前に書き込まれた情報が漏れないようにする
slab_nomerge
page_alloc.shuffle=1
カーネルがユーザープロセスに割り付けるメモリ領域のアドレスをよりランダムにする
panic=1
oops=panic
OOPSが起きたらすぐにパニックする。おかしな状態になっているのに無理やり実行を続けることは付け込まれる危険性を増やすため
kpti=1 (ARM) または pti=on (AMD/Intel)
PTI (Page Table Isolation) を行いユーザープロセスに漏れるメモリに関する情報を減らす
vsyscall=none (AMD/Intelのみ)
危険なので今は避けるべきvsyscallを禁止する

カーネルを自分でコンパイルしなおして行うhardening

ディストロが提供するカーネルを用いて自動更新を有効にしておけば放っておいてもセキュリティホールが修正されていく。自分でカーネルをコンパイルする場合には、安全性を保つためにこまめに再コンパイルを行う必要があることに注意。以下の記事などを参考にして、www.kernel.org などから持ってきたカーネルのソースをコンパイルできる環境を整備しておく

-march=native (AMD/Intel), -mcpu=native (ARM) などを付けてCPUに合わせた最適化をCコンパイラにさせるとよい。例えば make KCFLAGS="-march=native -pipe" bindeb-pkg などとする。

キツイ最適化

最適化レベルを高めてカーネルをコンパイルすると起動しないことがよくあるが、以下のようなきつい最適化を掛けても手元のカーネルは取り敢えず起動している…(clang13 + Linux 5.15.2)

sed -i 's/-O2/-O3/g' Makefile
sed -i 's/-Os/-Oz/g' Makefile
sed -i 's/-flto/-flto -fwhole-program-vtables -fvirtual-function-elimination/g' Makefile
yes '' | make KCFLAGS="-fintegrated-cc1 -mcpu=native -faddrsig -fforce-emit-vtables -frtti -frtti-data -pipe -mllvm -polly -mllvm -polly-ast-use-context -mllvm -polly-invariant-load-hoisting -mllvm -polly-opt-fusion=max -mllvm -polly-run-inliner -mllvm -polly-vectorizer=stripmine -mllvm -polly-run-dce"  LLVM=1 LLVM_IAS=1 bindeb-pkg

gcc で使えるKconfig項目

CONFIG_ZERO_CALL_USED_REGS=y
関数から戻る際に使用したレジスタの内容を消す
CONFIG_GCC_PLUGINS=y
以下の設定項目を使えるようにする
CONFIG_GCC_PLUGIN_LATENT_ENTROPY=y
/dev/randomで使える乱数を増やす
CONFIG_GCC_PLUGIN_STACKLEAK=y
ユーザープロセスに制御を戻す前にカーネルスタックの内容を消す
CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF_ALL=y
カーネルが使うスタック領域を使う前に内容を消す

clang で使える項目

clangを用いてカーネルを作るためには make LLVM=1 LLVM_IAS=1 bindeb-pkg などとする

CONFIG_INIT_STACK_ALL_ZERO=y
カーネル内でスタック領域を使用する前に内容を消す
CONFIG_SHADOW_CALL_STACK=y
関数の呼び出し元アドレスなどを通常の変数とは別のスタックに格納し書き換えられにくくする
CONFIG_LTO_CLANG_FULL=y
LTO (Link Time Optimization)する。以下の項目にはLTOが必要
CONFIG_TRIM_UNUSED_KSYMS=y
LTOによる最適化の効果を高める
CONFIG_CFI_CLANG=y
CONFIG_CFI_CLANG_SHADOW=y
CFI (control flow integrity) を用いてcontrol flowが勝手に書き換えられておかしなコードが実行されることを検出する

gcc, clang に共通のhardening項目

linux-config-5.15 パッケージに含まれる、 /usr/src/linux-config-5.15 に置いてあるDebian の標準 Kconfig で既に適切に設定されている項目については触れていない。Debianで既に適切に選ばれている項目も含めた一覧は https://kernsec.org/wiki/index.php/Kernel_Self_Protection_Project/Recommended_Settings ならびに https://github.com/a13xp0p0v/linux-kernel-defence-map がよい

CONFIG_UBSAN=n
CONFIG_UBSAN_BOUNDS=y
CONFIG_UBSAN_ONLY_BOUNDS=y
CONFIG_UBSAN_ARRAY_BOUNDS=y
CONFIG_UBSAN_LOCAL_BOUNDS=n
CONFIG_UBSAN_SANITIZE_ALL=y
CONFIG_UBSAN_MISC=n
CONFIG_UBSAN_UNREACHABLE=y
CONFIG_UBSAN_SHIFT=y
CONFIG_UBSAN_OBJECT_SIZE=n
未定義動作サニタイザ(UBSAN)。C言語で言うところの未定義動作がカーネル内部で生じているのは明らかにおかしいので、実行時に検出する。false positiveが出る項目といきなりトラップ処理に入る項目はnにしている。目に見える性能低下は見られない
CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT=y
カーネルスタックの場所をランダム化する
CONFIG_ARM64_SW_TTBR0_PAN=y
PAN (Privileged Access Never)のエミュレーション (ARMのみ)
CONFIG_DEBUG_STACK_USAGE=y
スタックオーバーフローを検査する
CONFIG_CRYPTO_JITTERENTROPY=y
/dev/randomが使える乱数を増やす
CONFIG_WQ_WATCHDOG=y
work queueが固まったことを検出する
CONFIG_MCORE2=y
CONFIG_MK8=y
CONFIG_MATOM=yなど
(AMD/Intelのみ) Intel ATOMなどの新しいCPUに合わせたカーネルを作る。対象のCPUに合わせて適切に選択する。

あまり使われない項目の削除

自分の用途で使わない機能は攻撃者の踏み台になるだけなので、自分でカーネルをコンパイルしなおす場合削除することが望ましい。そういう意味で make yes2modconfig してすべての設定項目をモジュールに変更してから作ったカーネルで再起動し、 make localmodconfig で使わないモジュールを削るのも良い

CONFIG_DEVKMEM=n
CONFIG_DEVMEM=n
CONFIG_DEVPORT=n
これらは /dev/kmem, /dev/mem, /dev/port を有効にするが今どきそれらを使うプログラムは無い
CONFIG_KEXEC=n
カーネルを置き換える危険なkexecシステムコールを禁止
CONFIG_USERFAULTFD=n
User Fault FDはオラクルのデータベースくらいでしか使われず過去の攻撃で使われているため禁止
CONFIG_UIO=n
CONFIG_VFIO=n
ユーザースペースのアプリケーションからデバイスを操作する枠組みだが、ユーザースペースからデバイスを操作されると当然危険なので使わないなら禁止
CONFIG_VGA_SWITCHEROO=n
CONFIG_VGA_ARB=n
今はもう使われないハードウェア
CONFIG_SND_OSSEMUL=n
ALSAの前身であったOSSは今はもう使われない
CONFIG_HYPERVISOR_GUEST=n
CONFIG_KVM_GUEST=n
CONFIG_HYPERV=n
CONFIG_VBOXGUEST=n
CONFIG_PARAVIRT=n
CONFIG_XEN=n
CONFIG_VIRTIO=n
CONFIG_VIRTIO_PCI_LIB=n
CONFIG_VIRTIO_PCI_LIB_LEGACY=n
CONFIG_VIRTIO_MENU=n
CONFIG_VIRTIO_PCI=n
仮想マシンのゲストとして動作しないならこれらは不要
CONFIG_NUMA=n
CONFIG_HOTPLUG_CPU=n
CONFIG_HOTPLUG_PCI=n
CONFIG_HOTPLUG_PCI_PCIE=n
NUMAやCPU・PCIホットプラグは普通の計算機には無い
CONFIG_NR_CPUS=個数
「nproc」コマンドの表示結果を書いておく。NR_CPUSの値によってRCUで用いられる処理が変わったりする

/dev/random から読み出せる乱数の増加

セキュリティ関連のアプリケーションでは /dev/random からの読み出しを行うが、乱数が足りないと読み出しでアプリケーションが停止する。これを防ぐには

/etc/environment
SYSTEMD_RANDOM_SEED_CREDIT=true

と書いておくこと、ならびに、ハードウェア乱数生成器 (/dev/hwrng など) が付いている場合には rngd が有効である。

5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3