Solaris下究竟如何使用setuid/seteuid/setreuid
Q: 我被setuid/seteuid/setreuid搞瘋了,到底怎么使用它們?
A: 下面是Solaris 7的setuid(2)手冊(cè)頁(yè)
系統(tǒng)調(diào)用 setuid(2)
名字
setuid、setegid、seteuid、setgid - 設(shè)置UID和GID
摘要
#include |
seteuid()只設(shè)置EUID。如果當(dāng)前EUID為0,形參euid任意指定。否則
形參euid應(yīng)該是RUID、EUID、SUID之一。無(wú)論如何,最終只影響當(dāng)前
EUID。
setegid()只設(shè)置EGID。如果當(dāng)前EUID為0,形參egid任意指定。否則
形參egid應(yīng)該是RGID、EGID、SGID之一。無(wú)論如何,最終只影響當(dāng)前
EGID。
登錄時(shí),RUID、EUID、SUID設(shè)置成登錄ID。
進(jìn)程調(diào)用exec(2)執(zhí)行一個(gè)程序文件,考慮兩種情況:
a. 程序文件set-user-id,則相應(yīng)進(jìn)程EUID、SUID被設(shè)置成這個(gè)程序
文件的屬主ID。
程序文件set-group-id,則相應(yīng)進(jìn)程EGID、SGID被設(shè)置成這個(gè)程
序文件的屬組ID。
b. 程序文件沒(méi)有set-user-id,則相應(yīng)進(jìn)程EUID、SUID不變。
程序文件沒(méi)有set-group-id,則相應(yīng)進(jìn)程EGID、SGID不變。
如果當(dāng)前EUID為0,任意調(diào)用setuid()同時(shí)設(shè)置RUID、EUID、SUID。
如果當(dāng)前EUID為0,任意調(diào)用setgid()同時(shí)設(shè)置RGID、EGID、SGID。
如果當(dāng)前EUID不為0,形參uid等于RUID或者SUID,調(diào)用setuid()后當(dāng)
前EUID被設(shè)置成形參uid,RUID、SUID不受影響。
如果當(dāng)前EUID不為0,形參gid等于RGID或者SGID,調(diào)用setgid()后當(dāng)
前EGID被設(shè)置成形參gid,RGID、SGID不受影響。
返回值
0 成功
-1 失敗,errno被設(shè)置
錯(cuò)誤值
EINVAL 形參uid、gid等不在合法范圍內(nèi)
EPERM 當(dāng)前EUID不為0,形參指定不符合前面描述
屬性
___________________________________________________________ |
參看
intro(2)、exec(2)、getgroups(2)、getuid(2)、attributes(5)
stat(5)
A: 下面是Solaris 7的setreuid(2)手冊(cè)頁(yè)
系統(tǒng)調(diào)用 setreuid(2)
名字
setreuid - 設(shè)置RUID、EUID
摘要
#include |
setreuid()設(shè)置RUID、EUID,最終可能導(dǎo)致SUID改變。
如果形參ruid為-1,RUID不變。如果形參euid為-1,EUID不變。形參
ruid、euid可以不同。
如果EUID為0,形參ruid、euid可以是任意合法值。
如果EUID不為0,形參ruid可以等于當(dāng)前RUID、當(dāng)前EUID,形參euid
可以等于當(dāng)前RUID、當(dāng)前EUID、當(dāng)前SUID。
兩種情況下,如果RUID被成功修改(形參ruid不為-1),或者EUID被成
功修改(形參euid不為-1)并且不等于最終RUID,則最終SUID被設(shè)置成
最終EUID。
返回值
0 成功
-1 失敗,errno被設(shè)置
錯(cuò)誤值
EINVAL 形參ruid、euid等不在合法范圍內(nèi)。
/usr/include/limits.h中定義了合法范圍
[0, 2147483647(UID_MAX)]。
EPERM 當(dāng)前EUID不為0,形參指定不符合前面描述。
用法
一個(gè)set-user-id進(jìn)程調(diào)用setreuid()修改當(dāng)前EUID成當(dāng)前RUID后,
依然可以調(diào)用setreuid()修改當(dāng)前EUID成當(dāng)前SUID
參看
exec(2)、getuid(2)、setregid(2)、setuid(2)
D: 小四
從Solaris 2.6/7源碼中可以看到,由于SUID的存在,存在很多安全隱患。
對(duì)于一個(gè)setuid-to-root的程序,如果需要永久放棄特權(quán),應(yīng)該在當(dāng)前EUID為0的時(shí)
候調(diào)用setuid( not root )放棄特權(quán)。或者調(diào)用setreuid( not root, not root )放
棄特權(quán)。只有這兩種正確辦法,否則始終有機(jī)會(huì)重獲特權(quán)。
假設(shè)當(dāng)前ruid == 500、euid == 0、suid == 0,
setreuid( -1, 500 ); <-- 臨時(shí)放棄特權(quán) ruid == 500、euid == 500、suid == 0
setreuid( -1, 0 ); <-- 恢復(fù)特權(quán) ruid == 500、euid == 0、suid == 0
setuid( 500 ); <-- 永久放棄特權(quán) ruid == euid == suid == 500
某些系統(tǒng)可能不支持SUID,假設(shè)當(dāng)前ruid == 500、euid == 0,
setuid( 0 ); <-- 現(xiàn)在ruid == euid == 0
setreuid( -1, 500 ); <-- 現(xiàn)在ruid == 0、euid == 500
seteuid( 0 ); <-- 現(xiàn)在ruid == euid == 0
顯然在某些shellcode編寫(xiě)過(guò)程中,應(yīng)該是這個(gè)調(diào)用順序成功幾率最大:
seteuid( 0 );
setuid( 0 );
下面這個(gè)程序演示如何調(diào)用setreuid()、setregid()永久放棄setuid、setgid特權(quán)
--------------------------------------------------------------------------
/* gcc -Wall -O3 -o ugtest ugtest.c */ |
而不是setuid(),因?yàn)檫@樣最通用。尤其當(dāng)setuid-to-
根本無(wú)法永久放棄特權(quán)。
如果一個(gè)Solaris下的程序setgid-to-
而不是setgid(),因?yàn)檫@樣最通用。尤其當(dāng)整個(gè)過(guò)程中無(wú)法滿(mǎn)足EUID為0的時(shí)候,
setgid()根本無(wú)法永久放棄特權(quán)。
假設(shè)一個(gè)Solaris下的程序同時(shí)setuid、setgid過(guò),較理想的釋放順序應(yīng)該是先釋放


