
ProFTPD 1.3.9d — высокий — удалённый — остаточные привилегии / запись файла — SFTP copy-file пропускает проверку WRITE для назначения
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · proftpd-sftp-copy-file-write
Класс: Остаточные привилегии / запись файла Достижимость: Удалённая
ProFTPD 1.3.9d (f59f248) - proftpd.org
contrib mod_sftp объявляет copy-file, как только включён SFTPEngine (SFTP_FXP_EXT_DEFAULT). fxp_handle_ext_copy_file выполняет запись в dest и AllowOverwrite только если pr_fsio_stat(dst) завершается успешно. Если dest ещё не существует, эта проверка пропускается. Затем pr_fs_copy_file2 создаёт файл от имени UID сессии, в том числе в рамках <Limit WRITE> DenyAll.
FTP STOR и SFTP OPEN-write по-прежнему проходят через xfer_pre_stor, который всегда выполняет dir_check для WRITE перед созданием. Публичный Issue 2095 — это обратный случай: SITE COPY пропускал READ источника. Данный остаток — это WRITE в dest под новым именем.
| ID | CVE пока нет |
| Класс | Остаточные привилегии / запись файла |
| Достижимость | Удалённая (аутентифицированный SFTP) |
| CWE | CWE-863 |
| CVSS | High: 7.1 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N |
| Продукт | ProFTPD |
| Затронуто | 1.3.9d (f59f248e26bdfa514443e42bf72a145641df635d) contrib mod_sftp |
| Аутентификация | аутентифицированный SFTP (SFTPEngine on) |
| Лицензия | GNU Affero GPL v3.0 |
| Лаборатория | только 127.0.0.1 |
Я зафиксировал тег v1.3.9d и изучил fxp_handle_ext_copy_file. Он выполняет диспетчеризацию PRE_CMD поддельной команды SITE COPY. mod_copy регистрирует copy_copy как CMD, а не PRE_CMD, поэтому проверка WRITE для dest в FTP на этом пути никогда не выполняется. READ источника всегда проходит dir_check. WRITE в dest — нет, если только dest уже не существует. Лаборатория — это loopback SFTP на 127.0.0.1:18710.
| Метод | Точка сброса | Привилегия |
|---|---|---|
SFTP EXTENDED copy-file из читаемого src в имя dest, которое ещё не существует, в рамках <Directory> с <Limit WRITE> DenyAll | pr_fs_copy_file2 | Целостность (доказано в лаборатории): создать этот файл от имени UID сессии. Разведка (доказано в лаборатории): SFTP READ из dest возвращает байты источника, когда READ для dest разрешён. |
| Тот же dest уже существует | dir_check WRITE + AllowOverwrite | Закрыто (доказано в лаборатории): перезапись через copy-file возвращает permission denied. |
| SFTP OPEN / STOR / SCP-загрузка того же dest | xfer_pre_stor | Закрыто (доказано в лаборатории): OPEN write/create возвращает SSH_FX_PERMISSION_DENIED (статус 3). |
| Неаутентифицированный copy-file | Аутентификация SFTP | Закрыто. Шелла нет. Unix DAC по-прежнему применяется. |
Доказано в лаборатории vs предположено: создание dest, READ из dest для свидетеля, запрет OPEN-write и запрет перезаписи существующего dest доказаны в лаборатории. Неаутентифицированный доступ и Unix DAC остаются предположениями, выведенными из модели аутентификации/chroot.
Требуется: загруженный contrib mod_sftp, SFTPEngine on. Типичный SFTP vhost из дистрибутива. SFTPExtensions -copyFile отключает расширение.
cd lab
./run.sh
Loopback 127.0.0.1:18710 сопоставлен с контейнером 2222. Проект Compose proftpd-sftp-copy-file-write. Тег образа proftpd-sftp-copy-file-write:1.3.9d. Свидетель PROFTPD-SFTP-COPY-FILE-WRITE-WITNESS. Последняя строка:
SUCCESS PROFTPD-SFTP-COPY-FILE-WRITE dest-exists=yes open-write=denied copy-file=ok overwrite-denied=yes PROFTPD-SFTP-COPY-FILE-WRITE-WITNESS
Выполнять dir_check для WRITE в dest даже когда dest ещё не существует, перед pr_fs_copy_file2. Либо отключить расширение: SFTPExtensions -copyFile.
f59f248e26bdfa514443e42bf72a145641df635d)fxp_handle_ext_copy_file в contrib/mod_sftp/fxp.cSFTP_FXP_EXT_DEFAULT включает copy-file