Ключевые слова:suid, security, (найти похожие документы)
Date: Sun, 16 Jun 2002 07:09:07 +0000 (UTC)
From: Valentin Nechayev <netch@segfault.kiev.ua>
Newsgroups: fido7.ru.unix.prog
Subject: Описание проблем безопасности при написании suid программ
>> А почему-бы не одну суидную? Потом она fork'ается и одна из них делается
>> setuid(geteuid()), а вторая остаётся root.
DG> setuid(getuid()). Это во-первых.
DG> Во-вторых:
DG> А вдруг она до setuid(getuid()) зачитает данные, которые ей по должности
DG> (которая == getuid) не положены? А уронят ее? И из корки лишнего
DG> прочтут?
Вообще-то, во всех нормальных юниксах давно уже есть контроль того,
что процесс с момента exec'а делал изменение uid или gid - и в этом случае
ставится флаг P_SUGID или сбрасывается флаг dumpable или еще как-то помечается
факт "грязности" памяти процесса - и после этого корку она не спечет,
и сделать к ней attach не получится, если ты не root.
Признак "грязности" хранится все время жизни процесса через все fork'и,
пока не сделан exec - тогда предыдущий сбрасывается, но может возникнуть
новый, если exec был на suid/sgid бинарник и при этом возникло ruid!=euid
или rgid!=egid именно по причине этих флагов бинарника, а не в наследство.
(Это чуть упрощенное описание, но показывающее направление действия.)
Вот из freebsd (4.5-stable):
=== cut ptrace() ===
/* not owned by you, has done setuid (unless you're root) */
if ((p->p_cred->p_ruid != curp->p_cred->p_ruid) ||
(p->p_flag & P_SUGID)) {
if ((error = suser(curp)) != 0)
return error;
}
=== end cut ===
=== cut coredump() ===
if (((sugid_coredump == 0) && p->p_flag & P_SUGID) || do_coredump == 0)
return (EFAULT);
=== end cut ===
Вот из linux (2.4.18):
=== cut ptrace_attach() ===
if (!task->mm->dumpable && !capable(CAP_SYS_PTRACE))
goto bad;
=== end cut ===
=== cut do_coredump() ===
if (!current->mm->dumpable)
goto fail;
=== end cut ===
На чем можно получить проблемы:
- На том, что где-то старая система, которая этого не умеет.
- На простейшем эксплойте к коду, которому права пофиг.
- На явно включенном sysctl kern.sugid_coredump в BSD системах
(хотя такие корки, AFAIR, доступны только руту)
(это по умолчанию выключено и его можно включать только для отладки в
тяжелых ситуациях)
- На явном сбросе флага dumpable самим процессом в Linux
- На еще каком-то действии, прорвавшемся через такой контроль из-за неполноты
представления кодописателей о происходящем. Например, методом, аналогичным
взлому через ptrace в 2.2.16 и близких к тому линуксах - атомарность
проверки не выполняется из-за того, что по дороге производится sleep().
- На передаче от исходного процесса в процесс, получивший suid или sgid,
какого-то элемента окружения, который влияет на функционирование процесса
и вышел за пределы контроля кода. Например, переменные окружения, rlimits...
DG> С суидностью надо осторожно. А если можно без нее, то лучше таки без нее.
Действительно, сейчас стараются максимально избавиться от всего описанного
спектра граблей путем сокращения прав, даваемых программам, и сокращения
цепочек выполнения, начатых из такого untrusted источника, как пользовательский
процесс. Например, запустив sendmail -bm -v, можно увидеть весь ход доставки
и получить цепочку user's process -> injecter -> background runner ->
local mailer; для postfix цепочка ограничится укладкой в очередь, причем
sgid, а не suid, процессом, и сообщением qmgr'у про новое письмо.
/netch