Назад | Перейти на главную страницу

Клиент SFTP не может писать в собственный домашний каталог, когда находится там chrooot

Это более жесткий вариант предыдущего вопроса неправильное владение или режимы для компонента каталога chroot.

В этом другом вопросе мы узнаем, что openssh отказывается chroot пользователя в его собственный домашний каталог, если этот домашний каталог имеет обычные разрешения. Вместо этого вам нужно сделать root владельцем домашнего каталога пользователя. Это предотвращает загрузку пользователем в свой домашний каталог.

Я работаю с программой, которую позвоню stupid_legacy_application или SLA для краткости, который хочет отправить мне свой вывод через sftp upload. И он настаивает на загрузке в корневой каталог (который кажется клиенту). Загрузка не выполняется, и в журнале сервера остаются следующие сообщения:

Jun 17 18:05:53 sftphost sftp-server[29031]: open "/SLA\\SLA_Data_ 2018617_18551.zip" flags WRITE,CREATE,TRUNCATE mode 0666  
Jun 17 18:05:53 sftphost sftp-server[29031]: sent status Permission denied

Обратите внимание на сочетание косой черты и обратной косой черты в пути. Я предполагаю, что это было предназначено для разговора с каким-то сервером Windows sftp, и /SLA должен быть каталогом.

Если я не исключаю пользователя, он пытается загрузить в настоящий корневой каталог и терпит неудачу. Если я исключаю пользователя и не подключаю каталог к ​​корневому, sshd не разрешает вход в систему. Если я исключаю пользователя и подключаю каталог к ​​корневому, он снова терпит неудачу. Если я добавлю разрешение на запись для пользователя через биты группы или мира, sshd не разрешит вход в систему.

Я даже пытался обмануть его с помощью ACL, думая, что sshd не заметит ничего, кроме традиционных разрешений, но я обманул только себя (см. этот вопрос почему это не работает).

Перекомпиляция sshd с взломанной проверкой прав доступа к каталогам выглядит единственным способом решить эту проблему. Есть ли другой путь? Он не должен быть чистым, так как мне нужно, чтобы он работал только один раз, а сервер - это одноразовая виртуальная машина.

Я нашел несколько рабочих решений этой проблемы, большинство из которых можно было использовать только из-за моей готовности выбросить сервер после того, как я получил эту загрузку. Но есть один, который я считаю довольно разумным.

Сначала самое уродливое решение:

Плохая идея №1 - Забудьте о chroot и chmod 777 /. Openssh проверяет наличие нормальных разрешений только при chroot.

Плохая идея №2 - разрешить клиенту писать в настоящий корневой каталог (как в плохой идее №1) можно сделать более тонко, с разрешениями группы или пользовательским ACL.

Плохая идея №3 - Как я уже писал в вопросе, можно взломать проверку разрешений из sshd. Просто найдите сообщение об ошибке bad ownership or modes for chroot в источнике измените ближайший 022 к 002 и он больше не заметит потерю разрешений групп и ACL в chroot.

Хорошая идея (?) - Эта обратная косая черта является источником проблемы. Если бы клиент просто загрузил в /SLA/SLA_Data_blah_blah.zip все было бы хорошо. Итак, давайте просто исправим обратную косую черту в точке, где она попадает в файловую систему, обернув open системный вызов:

/* wrapopen.c */
#define _GNU_SOURCE
#include <string.h>
#include <sys/types.h>
#include <dlfcn.h>

static int (*libc_open)(const char *, int, mode_t);

/* Behave like normal open() but translate backslashes to slashes. */
int open(const char *fn, int flags, mode_t mode)
{
  char fn_fixed[strlen(fn)+1], *p;

  strcpy(fn_fixed, fn);
  for(p=fn_fixed;*p;++p)
    if(*p == '\\')
      *p = '/';

  if(!libc_open)
    libc_open = dlsym(RTLD_NEXT, "open");

  return libc_open(fn_fixed, flags, mode);
}

Использование:

$ gcc -fPIC -shared wrapopen.c -o wrapopen.so -ldl
$ /etc/init.d/ssh stop
$ LD_PRELOAD=$PWD/wrapopen.so /usr/sbin/sshd

Теперь, когда sshd пытается создать SLA\SLA_Data_blah_blah это фактически создает SLA/SLA_Data_blah_blah. Пользователь может иметь chroot-права, chroot принадлежит root-режиму 755, SLA каталог в chroot принадлежит пользователю, и загрузка работает.