
著者: IJ Baig
日付: 2026年7月7日
1.8.2~1.8.31p2、および安定版バージョン1.9.0~1.9.5p1。1.9.5p1この脆弱性を安全に分析するために、脆弱なSudoバージョンを隔離された非本番環境内でコンパイルしました。

Sudo 1.9.5p1のソースコードをダウンロードし、標準のmakeユーティリティを使用してローカルでコンパイルしました。ホストシステムのネイティブでパッチ適用済みのsudoバイナリを上書きしないよう、ローカルディレクトリから実行するように注意しました。

ビルド確認: コンパイル後、カスタムバイナリを実行して、正しい脆弱なバージョンがビルドされたことを確認しました。


plugins/sudoers/sudoers.cset_cmnd() (バージョン1.9.5p1の約864行目)
言葉のリストからエスケープ文字(バックスラッシュ)を取り除き、新しく割り当てられた保管ボックス(ヒープバッファ)に入れる仕事をするヘルパーを想像してみてください。そのヘルパーは、すべてのバックスラッシュの後には常に有効な文字が続くと盲目的に想定しているため、バックスラッシュを見つけるたびにそれをスキップして次の文字をコピーします。
しかし、sudoedit -sを実行する際のプログラムの引数処理に欠陥があります。これにより、ユーザーは単一のバックスラッシュ(\)で正確に終わり、その直後に目に見えない単語の終わりを示すマーカー(ヌル終端文字、\0)が続く単語をこっそりと差し込むことができます。
ヘルパーのコードがこの末尾のバックスラッシュに到達すると、それをスキップして次の文字、つまりヌル終端文字を見ます。停止する代わりに、if文のロジックによりヘルパーはヌル終端文字もスキップしてしまいます。ループは続行し、次に続く任意の範囲外メモリを保管ボックスにコピーし続けます。この意図された単語の長さを超えた連続コピーにより、指定されたバッファがオーバーフローし、深刻なヒープベースのバッファオーバーフローを引き起こします。
脆弱なコードスニペット:
/* Unescape characters, skipping over backslashes */
for (to = user_args, av = NewArgv + 1; (from = *av); av++) {
while (*from) {
// VULNERABILITY: If from[0] is '\' and from[1] is '\0',
// the loop evaluates to true, increments 'from', skipping the null terminator.
if (from[0] == '\\' && !isspace((unsigned char)from[1]))
from++;
*to++ = *from++;
}
*to++ = ' ';
}
*--to = '\0';
Sudo開発者は、バージョン1.9.5p2で厳格な境界チェックを追加してこのロジックエラーを修正しました。コードは現在、バックスラッシュの後に続く文字がヌル終端文字でないことを明示的に確認してから、アンエスケープを試みます。
パッチ差分:
- if (from[0] == '\\' && !isspace((unsigned char)from[1]))
+ if (from[0] == '\\' && from[1] != '\0' && !isspace((unsigned char)from[1]))
これが根本原因を修正する理由:
from[1] != '\0'の追加により、範囲外読み取りが即座に停止します。コードが文字列の末尾に来たバックスラッシュに遭遇した場合(つまりfrom[1]がヌル終端文字の場合)、if文はfalseと評価されます。ポインタは時期尚早にインクリメントされず、ヌル終端文字は文字列の終わりとして正しく処理され、ループはヒープをオーバーフローさせることなく安全に終了します。
この再現では、セキュリティ研究者Worawitによって開発された広く認識されているPythonエクスプロイト(特にexploit_nss.pyバリアント)を利用しました。
PoCを実行する前に、その仕組みを理解することが重要です。スクリプトは単にプログラムをクラッシュさせるわけではありません。コード実行を得るために、メモリの高度に精密な操作を調整します。
以下はPoCの操作のステップバイステップの内訳です:
.so)にします。このペイロードは/bin/shをrootとして実行するように設計されています。LC_ALL、LANG、TZなど)を設定します。Sudoは起動時に環境変数をヒープにロードするため、スクリプトはヒープを予測可能なレイアウトに配置するために必要な正確なサイズを計算します。sudoedit -sを実行し、単一のバックスラッシュで終わるコマンドライン引数を渡します。これにより、セクション2で説明したオフバイワン脆弱性がトリガーされ、範囲外書き込みが発生します。service_user構造体を正確に上書きします。この構造体は、ネームサービススイッチ(NSS)がシステム情報を検索するために使用されます。service_user構造体が破損され、ステップ1でコンパイルされた悪意のある.soライブラリを指すようになります。Sudoがユーザー権限を検索しようとすると、攻撃者のライブラリを盲目的にロードして実行し、rootシェルを獲得します。まず、脆弱性が存在することを証明するために、武器化せずに基本的なクラッシュテストを実施しました。

次に、完全なWorawitのexploit_nss.pyスクリプトを脆弱なバイナリに対して実行しました。

公式修正を検証するために、まったく同じPoCトリガーをパッチ適用済みのSudoバイナリに対して実行しました。
sudoedit -s '\' 2>&1 | grep -q "sudoedit:" && echo "Vulnerable" || echo "Not vulnerable"

Sudoは、当社のサーバー全体で使用される標準的な管理プログラムですが、バックスラッシュを含むテキスト入力の処理方法に重大な欠陥があります。不正な形式のコマンドを慎重に送信することで、基本的なユーザーアクセス権を持つ攻撃者は、システムをだまして指定されたメモリ領域の外にデータを書き込ませることができます。このミスにより、彼らはセキュリティ制御を完全にバイパスし、パスワードを一切必要とせずにマシンに対する完全な不正な管理制御を得ることができます。
課題: 主な課題の1つは、ヒープ操作の脆弱性でした。特定のOSバージョンを標的としたエクスプロイトペイロードは、基盤となる標準Cライブラリ(glibc)がメモリチャンクを異なる方法で管理するため、他のバージョンではしばしば失敗します。この脆弱性を正常に武器化するには、ターゲット環境に固有のメモリアラインメントと環境変数レイアウト(ヒープ風水)の正確な理解が必要でした。
学んだ教訓: 防御およびセキュリティ運用の観点から、この深掘りはいくつかの重要な概念を強化しました:
sudoedit -sコマンドのプロセス実行テレメトリを監視することで、SOCチームはパッチがインフラ全体に完全に展開される前にエクスプロイトの試行を検出できる可能性があります。並行CVE: CVE-2019-14287(Sudoセキュリティバイパス)
同じSudoコードベース内の別の顕著な脆弱性も、同様の根本原因パターンを持っています。ユーザー入力の不適切な解析と検証です。CVE-2019-14287では、SudoがユーザーID(UID)を解析する方法のロジックの欠陥により、攻撃者がユーザーID -1または4294967295を指定することでrootとしてコマンドを実行できました。
並行点: Baron Samedit(CVE-2021-3156)はメモリ破損の欠陥であり、CVE-2019-14287は認証バイパスですが、両方のケースの根本原因は初期の引数解析ロジックの失敗です。両方の脆弱性は、Sudoがコアの特権関数を実行する前に、エッジケースのコマンドライン引数(末尾のバックスラッシュと予期しない整数ラップ)を誤って信頼し、誤って処理することに起因しています。
安全性と倫理に関する宣言: このレポートで実証されたすべてのエクスプロイトとテストは、隔離された承認済みのローカル仮想マシン内で完全に実施されました。この演習中に、本番システムや不正なネットワークを標的にしたり、それらとやり取りしたりすることはありませんでした。