exponenta event banner

Неправильный порядок удаления привилегий

Отбрасывание повышенных привилегий перед отбрасыванием пониженных привилегий

Описание

Этот дефект возникает при использовании таких функций, как 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++
По умолчанию: Откл.
Синтаксис командной строки: BAD_PRIVILEGE_DROP_ORDER
Воздействие: Высокое
CWE ID: 250, 696
Представлен в R2016b