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