#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);
}