
vsftpd 3.0.5 - 高 - リモート - 権限残留 - FTPS データは任意の再開チケットを受け入れる
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · vsftpd-ssl-data-any-ticket
クラス: 権限の取りこぼし 到達範囲: リモート
vsftpd 3.0.5 (Chris Evans) - 公式 tarball SHA-256 26b602ae454b0ba6d99ef44a09b6b9e0dfa7f67228106736df1f278c70bc91d3。ディストリビューションの FTPS ビルドは #define VSF_BUILD_SSL を有効化し(素の tarball は #undef)、運用者は ssl_enable=YES を設定する。スタンドアロンの listen=YES はコンパイル時およびサンプルのデフォルトである。
ssl_accept (ssl.c:494-501) はデータチャネルのバインド処理である。これは SSL_session_reused() のみをチェックする。制御用 SSL との SSL_SESSION 比較は存在しない。データ SSL には FTP の USER/PASS がない。スタンドアロンの ssl_init は fork の前にリスナー内で実行される (main.c:147-150) ため、子プロセスは 1 つの SSL_CTX を継承する。SSL_CTX_set_timeout(INT_MAX) (ssl.c:182-186)。SSL_OP_NO_TICKET はない。SSL_session_reused()==1 は、この ClientHello がこのプロセスで復号可能なチケットを運んできたことを意味するだけで、それが Alice の制御セッションであることを意味しない。
require_ssl_reuse の man ページには、再利用は制御チャネルと同じ master secret を証明すると書かれている。C コードはそうなっていない。これは 3.0.3 の Tim Kosse による reuse 失敗時の kill (ftpdataio.c:184-187) とは異なる。あれは新規ハンドシェイクを依然として 522 で拒否し、Mallory が別の制御接続で発行されたチケットを再開することを止められない。
この取りこぼしは 1 回の FTPS 転送である。USER/PASS のスキップではなく、シェルでもなく、chroot エスケープでもない。
| ID | CVE 未採番 |
| クラス | 権限の取りこぼし (FTPS データが任意の再開チケットを受け入れる) |
| 到達範囲 | リモート (同一 IP の PASV。共有 NAT は AC:H) |
| CWE | CWE-345, CWE-287 |
| CVSS | High: 7.4 CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N |
| 製品 | vsftpd (Chris Evans) |
| 影響を受けるバージョン | 3.0.5 で VSF_BUILD_SSL かつ ssl_enable=YES。require_ssl_reuse=YES (デフォルト)。require_cert=NO (デフォルト) |
| 認証 | Mallory: AUTH TLS のみ (USER/PASS なし)。Alice: anonymous の PBSZ/PROT P |
| ライセンス | GNU Affero GPL v3.0 |
| ラボ | 127.0.0.1:18700 制御、PASV 18701-18708。Compose vsftpd-ssl-data-any-ticket |
誰が: Alice の送信元 IP を共有する別の FTPS クライアント (または on-path の攻撃者)。PASV の accept は pasv_promiscuous でない限り制御ピア IP を依然として要求する (privops.c:212-218)。共有 NAT は、require_ssl_reuse が阻止するために追加された典型的な FTPS のケースである。Mallory は決してログインしない。
| 手法 + シンク | 権限 |
|---|---|
Mallory は AUTH TLS のみ、TLS 1.2 ALPN ftp、リスナーの SSL_CTX からセッションチケットを保持。Alice は anonymous で PBSZ/PROT P、PASV、RETR secret.txt を実行し、accept まで get_remote_transfer_fd でブロックされる。Mallory が同一 IP で PASV し、自身のチケットを再開する (session_reused=True) | その 1 回の RETR を復号する。ラボ: データソケット 35 バイト VSFTPD-SSL-DATA-ANY-TICKET-WITNESS。Alice は 150 の後に 226。制御 TLS とパスワードは Alice のまま。その転送を超えたディレクトリ走査はない。 |
ssl_accept ゲートから推測。ラボは RETR 窃取)| 手法 + シンク | 権限 |
|---|---|
Alice の STOR / APPE 中に同じチケットを再開 | Alice が指定したファイルが、Mallory の TLS 平文から、Alice の uid / anonymous ftp uid として、既存の chroot 内に書き込まれる |
| 手法 + シンク | 権限 |
|---|---|
新規データハンドシェイク (reused=False) | 522 session reuse required (3.0.3 の kill)。その転送は失敗する。制御は Alice のまま |
privops.c:212-218)require_cert=YES と提示された証明書は SHA-256 ダイジェストをバインドするPROT C (force_local_data_ssl はデフォルト YES)ssl_init 継承なし)ftp 以外の ALPN (vsftpd は FATAL で終了)GitHub ミラーや Debian/Fedora のツリーではなく、公式の vsftpd 3.0.5 tarball を固定した。19 回のソース探索。SSL の探索は ssl_accept で止まった。reuse はブール値であり、この制御 SSL_SESSION へのバインドではない。リスナーの SSL_CTX と INT_MAX のチケット寿命が残りの部分である。
回り道: ALPN は ftp でなければならず、そうでないと vsftpd は FATAL で終了する (3.0.4 の ALPACA 取りこぼしはすでに修正済み)。Arm64 のリンクには明示的な -lpam -lcap が必要だった。素の vsf_findlibs.sh は x86_64 のパスのみを探索する。3.0.3 の Tim Kosse の kill をこのバグと混同すること: あれは Alice のデータ fd での新規ハンドシェイクを 522 で拒否し、別の制御接続で発行されたチケットを止められない。
cd lab
./run.sh
公式 3.0.5 で #define VSF_BUILD_SSL。設定: ssl_enable=YES、allow_anon_ssl=YES、force_anon_logins_ssl=YES、force_anon_data_ssl=YES、require_ssl_reuse=YES、require_cert=NO。ループバック Docker。同一 IP の 2 クライアント。TLS 1.2 チケット。ALPN ftp。制御 127.0.0.1:18700、PASV 18701-18708。Compose vsftpd-ssl-data-any-ticket。Witness VSFTPD-SSL-DATA-ANY-TICKET-WITNESS。最終行:
SUCCESS vsftpd-ssl-data-any-ticket reused-ticket=yes fresh-handshake=522 VSFTPD-SSL-DATA-ANY-TICKET-WITNESS
データの SSL_SESSION を制御の SSL_SESSION にバインドする (セッション ID / master secret を比較する)。チケット寿命を制御接続に制限する。あるいは SSL_OP_NO_TICKET と、制御接続をキーとするセッションキャッシュ。ProFTPD 1.3.9d はセッションを比較している。
ベンダーの受付窓口は [email protected] (security.appspot.com/vsftpd.html)。vsftpd のいかなるミラーでも公開 GitHub issue を開かないこと。
Abraxas Labs - abraxaslabs.tech - github.com/abraxas - @abraxas_null - [email protected]