Содержание PF указывает на пакетах UDP = проблема безопасности?

Linux обеспечивает два механизма для того, чтобы следить за развитием событий файловой системы; dnotify и inotify.

Более старые из этих двух, dnotify, был представлен в версии 2.4.0 ядра. Это позволяет приложениям регистрироваться для получения уведомлений на изменениях в каталоге через fcntl() интерфейс. Сами уведомления поставляются через сигналы. dnotify механизм ограничен наблюдением изменений в каталоге, это не позволяет контролировать отдельных файлов. Кроме того, это требует поддержания открытого дескриптора файла к контролируемому каталогу. dnotify механизм удерживался от использования в 2.6.13, когда inotify был представлен.

Новые программы должны использовать inotify механизм, который поддерживает контроль обоих каталогов и отдельных файлов. Это, однако, не на основе сигналов. inotify экземпляр связан с дескриптором файла. Уведомления о событии могут быть прочитаны из этого дескриптора файла.

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


Пример (dnotify):

#define _GNU_SOURCE
#include 
#include 
#include 
#include 

/* For error handling */
#include 
#include 
#include 

static volatile int event_fd;

static void handler(int sig, siginfo_t *si, void *data)
{
    event_fd = si->si_fd;
}

int main(int argc, char *argv[])
{
    struct sigaction sa;
    int fd;

if(argc < 2)
    error(EXIT_FAILURE, 0, "missing argument");

    sa.sa_sigaction = handler;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = SA_SIGINFO;
    sigaction(SIGRTMIN + 1, &sa, NULL);

    if((fd = open(argv[1], O_RDONLY)) < 0)
        error(EXIT_FAILURE, errno, "failed to open '%s'", argv[1]);

    if(fcntl(fd, F_SETSIG, SIGRTMIN + 1) < 0)
         error(EXIT_FAILURE, errno, "failed to set dnotify signal");

    if(fcntl(fd, F_NOTIFY, DN_MODIFY|DN_CREATE|DN_DELETE|DN_MULTISHOT))
    error(EXIT_FAILURE, errno, 
              "failed to register notification for '%s'", argv[1]);

    while (1) {
        pause();
        printf("event occured for fd=%d\n", event_fd);
    }
}

Объяснение:

fcntl(fd, F_SETSIG, SIGRTMIN + 1)

Устанавливает сигнал, отправленный, когда события уведомления имеют место. Значение нуля указывает на это SIGIO (значение по умолчанию), отправляется. Любое другое значение, включая SIGIO, интерпретируется как сигнал, который будет отправлен вместо этого. В последнем случае обработчик сигналов получает a siginfo_t структура как ее второй аргумент, и si_fd поле структуры будет содержать дескриптор файла, который генерировал событие.

Если сигнал в реальном времени (>= SIGRTMIN) используется для уведомлений, несколько событий I/O могут быть поставлены в очередь с помощью того же числа сигнала (в зависимости от доступной памяти). Сигнал в реальном времени должен использоваться особенно при использовании DN_MULTISHOT.

fcntl(fd, F_NOTIFY, DN_MODIFY|DN_CREATE|DN_DELETE|DN_MULTISHOT)

Устанавливает события, которые вызовут уведомления, когда каталог, упомянутый fd или любыми файлами, которые он содержит, будет изменен. Доступные типы событий:

  • DN_ACCESS К файлу получают доступ.
  • DN_MODIFY Файл изменяется.
  • DN_CREATE Файл создается.
  • DN_DELETE Файл является несвязанным.
  • DN_RENAME Файл переименован в рамках каталога.
  • DN_ATTRIB Атрибуты файла изменяются.

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


Пример (inotify):

#include 
#include 
#include 

/* For PATH_MAX */
#include 

/* For error handling */
#include 
#include 

int main(int argc, char *argv[]) {
    int fd, wd, len, i;
    char buf[sizeof(struct inotify_event) + PATH_MAX];

    if (argc < 2)
        error(EXIT_FAILURE, 0, "missing argument");

    if ((fd = inotify_init()) < 0)
        error(EXIT_FAILURE, errno, "failed to initialize inotify instance");

    for (i = 1; i < argc; i++) {
         if ((wd = inotify_add_watch (fd, argv[i], 
                                      IN_MODIFY | IN_CREATE | IN_DELETE)) < 0)
             error(EXIT_FAILURE, errno,
                   "failed to add inotify watch for '%s'", argv[i]);
    }

     while ((len = read(fd, buf, sizeof(buf))) > 0) {
         i = 0;
             while (i < len) {
                 struct inotify_event *ie = (struct inotify_event*) &buf[i];

                 printf("event occured for '%s': ", argv[ie->wd]);
                 if (ie->mask & IN_MODIFY)
                     printf("%s was modified\n", ie->len ? ie->name : "file");
                 else if (ie->mask & IN_CREATE)
                     printf("%s was created\n",  ie->name);
                 else if (ie->mask & IN_DELETE)
                     printf("%s was deleted\n",  ie->name);
                 else
                     printf("unexpected event\n");

                 i += sizeof(struct inotify_event) + ie->len;
             }
     }

    error(EXIT_FAILURE, len == 0 ? 0 : errno, "failed to read inotify event");
}

Объяснение:

fd = inotify_init()

Инициализирует новое inotify экземпляр. Возвращаемое значение является дескриптором файла, связанным с недавно созданный inotify очередь событий. По умолчанию дескриптор файла блокируется.

wd = inotify_add_watch (fd, argv[i], IN_MODIFY | IN_CREATE | IN_DELETE)

Новые объекты к списку часов, иначе часы добавляются с inotify_add_watch(). Третьим аргументом является битовая маска, используемая для указания inotify события для наблюдения за. Доступные типы событий:

  • IN_ACCESS К файлу получают доступ.
  • IN_ATTRIB Атрибуты файла изменяются.
  • IN_CLOSE_WRITE Файл, открытый для записи, закрывается.
  • IN_CLOSE_NOWRITE Файл, открытый только для чтения, закрывается.
  • IN_CREATE Файл или каталог создается в рамках наблюдаемого каталога.
  • IN_DELETE Файл или каталог удален в рамках наблюдаемого каталога.
  • IN_DELETE_SELF Наблюдаемый файл или каталог удален.
  • IN_MODIFY Файл был изменен.
  • IN_MOVE_SELF Наблюдаемый файл или каталог перемещен.
  • IN_MOVED_FROM Файл перемещен из наблюдаемого каталога.
  • IN_MOVED_TO Файл перемещен в наблюдаемый каталог.
  • IN_OPEN Файл открыт.
  • IN_ALL_EVENT Все вышеупомянутое.
  • IN_MOVE Эквивалентный IN_MOVED_TO|IN_MOVED_FROM
  • IN_CLOSE Эквивалентный IN_CLOSE_WRITE|IN_CLOSE_NOWRITE

Следующие опции могут также быть установлены в аргументе маски inotify_add_watch():

  • IN_DONT_FOLLOW Не следуйте за символьными ссылками.
  • IN_EXCL_UNLINK Не генерируйте события для несвязанных файлов, которые раньше были в наблюдаемом каталоге.
  • IN_MASK_ADD Добавьте наблюдаемые события кумулятивно, если часы уже существуют.
  • IN_ONESHOT Автоматически удалите часы после одного события от него.
  • IN_ONLYDIR Только наблюдайте путь, если это - каталог.

Значение, возвращенное inotify_add_watch() дескриптор часов, связанный с объектом файловой системы, наблюдаемым в inotify экземпляр, обозначенный fd. Если за указанным объектом уже наблюдают, дескриптор для существующих часов возвращается.

while ((len = read(fd, buf, sizeof(buf))) > 0) {
    i = 0;
    while (i < len) {
        struct inotify_event *ie = (struct inotify_event*) &buf[i];
        /* ... */
        i += sizeof(struct inotify_event) + ie->len;
    }
}

Каждый успешный read() от дескриптора файла, связанного с inotify экземпляр возвращает один или несколько inotify_event структуры со следующими полями.

  • int wd Наблюдайте дескриптор инициированных часов.
  • uint32_t mask Маска событий, которые инициировали часы.
  • uint32_t cookie Уникальный cookie, связывающий связанные события.
  • uint32_t len Размер поля имени.
  • char name[] Дополнительное завершенное пустым указателем название файла, который инициировал событие в наблюдаемом каталоге.

В дополнение к битам, соответствующим типам событий, передал inotify_add_watch(), полю маски можно было установить следующие биты состояния:

  • IN_IGNORED Часы были удалены (через inotify_rm_watch(), путь, несвязанный и т.д.).
  • IN_ISDIR Событие инициировано каталогом.
  • IN_Q_OVERFLOW Очередь событий переполнена. Кроме того, wd установлен на-1.
  • IN_UNMOUNT Файловая система, содержащая наблюдаемый путь, была размонтирована.

Длина каждого inotify_event структура sizeof(inotify_event) + len из-за переменной длины name поле.

До версии 2.6.21 ядра, если буфер передал read() является слишком маленьким, чтобы провести следующее мероприятие, читать (), возвратился бы 0. С тех пор 2.6.21, read() сбои и errno установлен на EINVAL.

4
05.10.2016, 03:59
3 ответа

Любой другой брандмауэр будет иметь ту же проблему, что и PF, поскольку все они должны сохранить некоторое тип «состояния», чтобы позволить пакетам вернуться к устройству за Nat или другим видом Входящий блок, который позволяет ответить, но останавливает новые пакеты.

0
27.01.2020, 21:05

Случай 1: клиент UDP внутри брандмауэра инициирует обмен данными с сервером UDP. Брандмауэр создает запись сопоставления, чтобы разрешить продолжение разговора. Злоумышленник использует это для подмены некоторых пакетов в обратном направлении.

Во-первых, пакеты необходимо подделать, чтобы они выглядели так, как будто они исходят от сервера, иначе они не будут совпадать на удаленном адресе. Они также должны быть направлены на IP-адрес и UDP-порт клиента, иначе они не пройдут через брандмауэр. Таким образом, эти поддельные пакеты достигают клиента, который думает, что они исходят от сервера: они принимаются клиентским приложением, даже если его сокет дейтаграммы помечен как подключенный к серверу. Если приложение написано надежно, они в конечном итоге отбрасываются на уровне внутреннего протокола, потому что не проходят проверки целостности (шифрование и контрольные суммы). Поддельные дейтаграммы UDP, конечно же, нанесут ущерб изначально небезопасным приложениям; это не вина брандмауэра.

Случай 2: UDP-сервер внутри брандмауэра имеет постоянный переадресацию порта. Конечно, любой может отправить туда UDP; ему просто нужно проверять пакеты и поддерживать только безопасные сеансы с аутентификацией.

0
27.01.2020, 21:05

No es un riesgo significativo en el escenario que describe.

Un atacante capaz de espiar el tráfico UDP ya se encuentra en una posición muy privilegiada. En realidad, no es particularmente relevante que una conexión esté o no listada en una tabla de seguimiento de conexiones.

Desde la perspectiva de la red, un atacante normalmente querrá a )observar el tráfico y los datos que van y vienen del host yb )modificar algunos de ellos para adaptarlos a un propósito particular. Luego, según el objetivo, la información podría usarse para hacerse pasar por el host o una entidad, intentar comprometer el host, atacar a otros hosts, etc.

0
27.01.2020, 21:05

Теги

Похожие вопросы