
OliveTinのパスワード引数処理におけるコマンドインジェクション(CVE-2026-27626)を利用した概念実証(PoC)エクスプロイトスクリプト。巧妙に細工されたAPIリクエストを介してRCEを可能にします。
OliveTin を使用すると、管理者は「アクション」を定義できます。これは、ユーザーが Web UI または API からトリガーできるパラメータ化された引数を持つシェルコマンドです。ユーザー指定の値をシェルコマンドにテンプレート展開する前に、OliveTin はそれを checkShellArgumentSafety() に通すことになっています。この関数は、string、int、bool、choice の 4 つの引数タイプをチェックします。password は完全にスキップされ、値をまったく検査せずに「安全」を意味する true を返します。
したがって、アクションに password タイプの引数があり、その引数がシェルコマンド文字列に置換される場合、その中に任意のものを入れることができます。セミコロン、バッククォート、$() など、何でもです。基になるコマンドで引数が引用符で囲まれている場合(データベースのパスワードなどでよくあるパターン)、引用符を抜け出すだけで十分です。
func checkShellArgumentSafety(argType string, value string) bool {
dangerousTypes := []string{"string", "int", "bool", "choice"}
for _, dt := range dangerousTypes {
if argType == dt {
return sanitizeInput(value)
}
}
// password type falls through here, unchecked
return true
}
影響を受けるのは OliveTin 3000.10.0 までです。3000.11.1 ライン(コミット 0.0.0-20260222101908-4bbd2eab1532)で修正され、チェック対象のタイプに password が追加されました。アドバイザリ: GHSA-49gm-hh7w-wfvf。CVSS 9.9。
パスワードタイプの引数がシェル文字列の中に入れられるものはすべて対象です。通常は引用符で囲まれます。
- title: Backup database
id: backup_db
shell: "mysqldump -u {{ db_user }} -p'{{ db_pass }}' {{ db_name }} > /tmp/backup.sql"
arguments:
- name: db_user
type: ascii_identifier
- name: db_pass
type: password
- name: db_name
type: ascii_identifier
db_pass はシングルクォートで囲まれており、それをチェックするものは何もありません。値として '; id ;' を送信すると、OliveTin は不正な mysqldump 呼び出しが失敗する前に id を実行します。失敗は問題になりません。注入されたコマンドは、OliveTin が実行されるユーザーとしてすでに実行されているからです。多くのセットアップでは、それは root です。なぜなら、人々は User= 行なしで systemd の下で実行し、その後それについて考えないからです。
インスタンスに authRequireGuestsToLogin: false が設定されている場合、これには資格情報は一切必要ありません。これは、小規模または趣味のデプロイメントでは一般的です。
pip install requests
python3 exploit.py -u <target> --action backup_db --arg db_pass -x "id"
アクションが、注入したコマンドが実行される前にエラーにならずに実行されるために他の引数を必要とする場合は、--extra-arg でそれらを渡します:
python3 exploit.py -u 10.0.0.5 --action backup_db --arg db_pass \
--extra-arg db_user=admin --extra-arg db_name=prod -x "whoami"
このスクリプトは StartAction に POST し、2 秒待ってから ExecutionStatus をポーリングし、返ってきた内容を出力します。通常、注入したコマンドの出力が、その後に実行されて失敗した正規のコマンドからのエラーの上に表示されます。これは想定どおりです。エラーは見かけ上のものであり、あなたのコマンドはすでに実行されています。
OliveTin を 3000.10.0 より新しいバージョンに更新してください。まだできない場合は、信頼できないユーザーが到達できるアクションからパスワードタイプの引数をすべて外し、ゲスト実行を無効にし、可能であれば引数の値をシェル文字列に補間すること自体をやめてください。代わりに、シークレットは環境変数または OliveTin が固定パスで読み取るファイルを介して渡してください。また、サービスを root として実行しないでください。タスクランナーが root である理由はありません。
exploit.py: PoC スクリプトREADME.md: このファイルこれは、自分の OliveTin インスタンスにパッチを適用する人、検出ルールを作成する人、またはテストを許可されたシステムをテストする人のためにあります。所有していないものや、触る許可がないものに対して使用しないでください。その結果については、作成者ではなく、あなた自身に責任があります。
| フラグ | 用途 | デフォルト |
|---|
-u, --url | 対象ホストまたは IP | 必須 |
-p, --port | OliveTin のポート | 1337 |
--action | 脆弱なアクションの bindingId | 必須 |
--arg | パスワードタイプの引数の名前 | 必須 |
-x, --cmd | 注入するコマンド | id |
--extra-arg | アクションが必要とするその他の引数。name=value 形式で、繰り返し指定可能 | なし |