Bad order of dropping privileges

Сбросить более высокие повышенные привилегии перед тем, как сбросить более низкие повышенные привилегии

Описание

Этот дефект возникает, когда вы используете такие функции, как setuid и 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 (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);
}

Информация о результатах

Группа: Безопасность
Язык: C | C++
По умолчанию: Off
Синтаксис командной строки: BAD_PRIVILEGE_DROP_ORDER
Влияние: Высокий
ИДЕНТИФИКАТОР CWE: 250, 696
Введенный в R2016b