CERT C: Rule POS36-C

Соблюдайте правильный порядок отзыва при отказе от привилегий

Описание

Определение правила

Соблюдайте правильный порядок отзыва при отказе от привилегий.[1]

Реализация Polyspace

Эта проверка проверяет неверный порядок удаления привилегий.

Примеры

расширить все

Проблема

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

Риск

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

Зафиксировать

Уважайте этот порядок удаления повышенных привилегий:

  • Удаление (повышенных) привилегий вспомогательной группы, а затем удаление (повышенных) привилегий основной группы.

  • Удаление (повышенных) привилегий основной группы, а затем удаление (повышенных) привилегий пользователя.

Пример - Удаление привилегий пользователя в первую очередь
#define _BSD_SOURCE
#include <sys/types.h>
#include <unistd.h>
#include <grp.h>
#include <stdlib.h>
#define fatal_error() abort()

static void sanitize_privilege_drop_check(uid_t olduid, gid_t oldgid)
{
    if (seteuid(olduid) != -1)
    {
        /* Privileges can be restored, handle error */
        fatal_error();
    }
    if (setegid(oldgid) != -1)
    {
        /* Privileges can be restored, handle error */
        fatal_error();
    }
}
void badprivilegedroporder(void) {
    uid_t
        newuid = getuid(),
        olduid = geteuid();
    gid_t
        newgid = getgid(),
        oldgid = getegid();

    if (setuid(newuid) == -1) {
        /* handle error condition */
        fatal_error();
    }
    if (setgid(newgid) == -1)  { 
        /* handle error condition */
        fatal_error();
    }
    if (olduid == 0) {
        /* drop ancillary groups IDs only possible for root */
        if (setgroups(1, &newgid) == -1) {
            /* handle error condition */
            fatal_error();
        }
    }

    sanitize_privilege_drop_check(olduid, oldgid);
}

В этом примере существуют две капли привилегий, сделанные в неправильном порядке. setgid пытается удалить привилегии группы. Однако setgid требует прав пользователя, которые были ранее удалены с помощью setuid, для выполнения этой функции. После удаления привилегий группы эта функция пытается удалить привилегии вспомогательных групп при помощи setgroups. Эта задача требует более высоких привилегий основной группы, которые были удалены с setgid. В конце этой функции можно вернуть групповые привилегии, поскольку порядок удаления привилегий был неправильным.

Коррекция - порядок сброса сторнирования привилегий

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

#define _BSD_SOURCE
#include <sys/types.h>
#include <unistd.h>
#include <grp.h>
#include <stdlib.h>
#define fatal_error() abort()

static void sanitize_privilege_drop_check(uid_t olduid, gid_t oldgid)
{
    if (seteuid(olduid) != -1)
    {
        /* Privileges can be restored, handle error */
        fatal_error();
    }
    if (setegid(oldgid) != -1)
    {
        /* Privileges can be restored, handle error */
        fatal_error();
    }
}
void badprivilegedroporder(void) {
    uid_t
        newuid = getuid(),
        olduid = geteuid();
    gid_t
        newgid = getgid(),
        oldgid = getegid();

    if (olduid == 0) {
        /* drop ancillary groups IDs only possible for root */
        if (setgroups(1, &newgid) == -1) {
            /* handle error condition */
            fatal_error();
        }
    }
    if (setgid(getgid()) == -1)  {
        /* handle error condition */
        fatal_error();
    }
    if (setuid(getuid()) == -1) {
        /* handle error condition */
        fatal_error();
    }

    sanitize_privilege_drop_check(olduid, oldgid);
}

Проверяйте информацию

Группа: Правило 50. POSIX (POS)
Введенный в R2019a

[1] Это программное обеспечение было создано MathWorks, включающее фрагменты: «Сайт SEI CERT-C», © 2017 Университет Карнеги Меллон, Веб-сайт SEI CERT-C + + © 2017 Университет Карнеги Меллон, "Стандарт кодирования SEI CERT C - Правила разработки безопасных, Надежные и безопасные системы - 2016 Edition ", © 2016 Университет Карнеги Меллон, и "Стандарт кодирования SEI CERT C++ - Правила разработки безопасных, Надежные и безопасные системы в C++ - 2016 Edition "© 2016 Университет Карнеги Меллон, с специального разрешения от его Института программной инженерии.

ЛЮБОЙ МАТЕРИАЛ УНИВЕРСИТЕТА КАРНЕГИ МЕЛЛОН И/ИЛИ ЕГО ИНЖЕНЕРНОГО ИНСТИТУТА ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ, СОДЕРЖАЩИЙСЯ В НАСТОЯЩЕМ ДОКУМЕНТЕ, ПОСТАВЛЯЕТСЯ НА БАЗИСЕ «КАК ЕСТЬ». УНИВЕРСИТЕТ КАРНЕГИ МЕЛЛОН НЕ ДАЕТ НИКАКИХ ГАРАНТИЙ, ВЫРАЖЕННЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ, В ОТНОШЕНИИ ЛЮБОГО ВОПРОСА, ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ, ГАРАНТИЮ ПРИГОДНОСТИ ДЛЯ ЦЕЛЕЙ ИЛИ КОММЕРЧЕСКОЙ ВЫГОДЫ, ИСКЛЮЧИТЕЛЬНОСТИ, ИЛИ УНИВЕРСИТЕТ КАРНЕГИ МЕЛЛОН НЕ ДАЕТ НИКАКИХ ГАРАНТИЙ В ОТНОШЕНИИ СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКИХ ПРАВ.

Это программное обеспечение и связанная с ним документация не были рассмотрены и не одобрены Университетом Карнеги-Меллон или его Институтом программной инженерии.