exponenta event banner

CERT C: POS36-C правил

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

Описание

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

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

Внедрение 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 Университет Карнеги-Меллон, со специальным разрешением от его Института программного обеспечения.

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

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