歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Unix知識 >> 關於Unix >> Solaris下究竟如何使用setuid/seteuid/setreuid

Solaris下究竟如何使用setuid/seteuid/setreuid

日期:2017/2/28 11:22:44   编辑:關於Unix


Solaris下究竟如何使用setuid/seteuid/setreuid
Q: 我被setuid/seteuid/setreuid搞瘋了,到底怎麼使用它們?
A: 下面是Solaris 7的setuid(2)手冊頁
系統調用 setuid(2)
名字
setuid、setegid、seteuid、setgid - 設置UID和GID
摘要
#include
#include
int setuid ( uid_t uid );
int seteuid ( uid_t euid );
int setgid ( gid_t gid );
int setegid ( gid_t egid );
描述
seteuid()只設置EUID。如果當前EUID為0,形參euid任意指定。否則
形參euid應該是RUID、EUID、SUID之一。無論如何,最終只影響當前
EUID。
setegid()只設置EGID。如果當前EUID為0,形參egid任意指定。否則
形參egid應該是RGID、EGID、SGID之一。無論如何,最終只影響當前
EGID。
登錄時,RUID、EUID、SUID設置成登錄ID。
進程調用exec(2)執行一個程序文件,考慮兩種情況:
a. 程序文件set-user-id,則相應進程EUID、SUID被設置成這個程序
文件的屬主ID。
程序文件set-group-id,則相應進程EGID、SGID被設置成這個程
序文件的屬組ID。
b. 程序文件沒有set-user-id,則相應進程EUID、SUID不變。
程序文件沒有set-group-id,則相應進程EGID、SGID不變。
如果當前EUID為0,任意調用setuid()同時設置RUID、EUID、SUID。
如果當前EUID為0,任意調用setgid()同時設置RGID、EGID、SGID。
如果當前EUID不為0,形參uid等於RUID或者SUID,調用setuid()後當
前EUID被設置成形參uid,RUID、SUID不受影響。
如果當前EUID不為0,形參gid等於RGID或者SGID,調用setgid()後當
前EGID被設置成形參gid,RGID、SGID不受影響。
返回值
0 成功
-1 失敗,errno被設置
錯誤值
EINVAL 形參uid、gid等不在合法范圍內
EPERM 當前EUID不為0,形參指定不符合前面描述
屬性
___________________________________________________________
| ATTRIBUTE TYPE | ATTRIBUTE VALUE |
| ____________________________|_____________________________|
| MT-Level | setuid() and setgid() and|
| | Async-Signal-Safe |
|_____________________________|_____________________________|
參看
intro(2)、exec(2)、getgroups(2)、getuid(2)、attributes(5)
stat(5)
A: 下面是Solaris 7的setreuid(2)手冊頁
系統調用 setreuid(2)
名字
setreuid - 設置RUID、EUID
摘要
#include
int setreuid ( uid_t ruid, uid_t euid );
描述
setreuid()設置RUID、EUID,最終可能導致SUID改變。
如果形參ruid為-1,RUID不變。如果形參euid為-1,EUID不變。形參
ruid、euid可以不同。
如果EUID為0,形參ruid、euid可以是任意合法值。
如果EUID不為0,形參ruid可以等於當前RUID、當前EUID,形參euid
可以等於當前RUID、當前EUID、當前SUID。
兩種情況下,如果RUID被成功修改(形參ruid不為-1),或者EUID被成
功修改(形參euid不為-1)並且不等於最終RUID,則最終SUID被設置成
最終EUID。
返回值
0 成功
-1 失敗,errno被設置
錯誤值
EINVAL 形參ruid、euid等不在合法范圍內。
/usr/include/limits.h中定義了合法范圍
[0, 2147483647(UID_MAX)]。
EPERM 當前EUID不為0,形參指定不符合前面描述。
用法
一個set-user-id進程調用setreuid()修改當前EUID成當前RUID後,
依然可以調用setreuid()修改當前EUID成當前SUID
參看
exec(2)、getuid(2)、setregid(2)、setuid(2)
從Solaris 2.6/7源碼中可以看到,由於SUID的存在,存在很多安全隱患。
對於一個setuid-to-root的程序,如果需要永久放棄特權,應該在當前EUID為0的時
候調用setuid( not root )放棄特權。或者調用setreuid( not root, not root )放
棄特權。只有這兩種正確辦法,否則始終有機會重獲特權。
假設當前ruid == 500、euid == 0、suid == 0,
setreuid( -1, 500 ); <-- 臨時放棄特權 ruid == 500、euid == 500、suid == 0
setreuid( -1, 0 ); <-- 恢復特權 ruid == 500、euid == 0、suid == 0
setuid( 500 ); <-- 永久放棄特權 ruid == euid == suid == 500
某些系統可能不支持SUID,假設當前ruid == 500、euid == 0,
setuid( 0 ); <-- 現在ruid == euid == 0
setreuid( -1, 500 ); <-- 現在ruid == 0、euid == 500
seteuid( 0 ); <-- 現在ruid == euid == 0
顯然在某些shellcode編寫過程中,應該是這個調用順序成功幾率最大:
seteuid( 0 );
setuid( 0 );
下面這個程序演示如何調用setreuid()、setregid()永久放棄setuid、setgid特權
--------------------------------------------------------------------------
/* gcc -Wall -O3 -o ugtest ugtest.c */
#include
#include
#include
#include
int main ( int argc, char * argv[] )
{
uid_t temp_ruid, temp_euid, orig_ruid, orig_suid;
gid_t temp_rgid, temp_egid, orig_rgid, orig_sgid;
orig_ruid = temp_ruid = getuid();
orig_suid = temp_euid = geteuid();
orig_rgid = temp_rgid = getgid();
orig_sgid = temp_egid = getegid();
printf( "ruid = %d euid = %d suid = %d\n", ( int )temp_ruid,
( int )temp_euid, ( int )orig_suid );
printf( "rgid = %d egid = %d sgid = %d\n", ( int )temp_rgid,
( int )temp_egid, ( int )orig_sgid );
if ( setregid( orig_rgid, orig_rgid ) < 0 )
{
perror( "Faint setregid" );
}
if ( setreuid( orig_ruid, orig_ruid ) < 0 )
{
perror( "Faint setreuid" );
}
temp_ruid = getuid();
temp_euid = geteuid();
temp_rgid = getgid();
temp_egid = getegid();
printf( "ruid = %d euid = %d\n", ( int )temp_ruid, ( int )temp_euid );
printf( "rgid = %d egid = %d\n", ( int )temp_rgid, ( int )temp_egid );
if ( setegid( orig_sgid ) < 0 )
{
perror( "I see setegid" );
}
if ( seteuid( orig_suid ) < 0 )
{
perror( "I see seteuid" );
}
return( EXIT_SUCCESS );
} /* end of main */
--------------------------------------------------------------------------
[scz@ /export/home/scz/src]> ls -l ./ugtest
-rwsr-sr-x 1 warning3 root 5416 6月 7 15:29 ./ugtest*
[scz@ /export/home/scz/src]> ./ugtest
ruid = 500 euid = 501 suid = 501 <-- setuid-to-
rgid = 100 egid = 0 sgid = 0 <-- setgid-to-root
ruid = 500 euid = 500 <-- 即使整個過程中沒有EUID為0的機會,
rgid = 100 egid = 100 還是成功地永久釋放了特權
I see setegid: Not owner
I see seteuid: Not owner
[scz@ /export/home/scz/src]>
如果一個Solaris下的程序setuid-to-,應該盡量使用setreuid()永久放棄特權,
而不是setuid(),因為這樣最通用。尤其當setuid-to-的時候,setuid()
根本無法永久放棄特權。
如果一個Solaris下的程序setgid-to-,應該盡量使用setregid()永久放棄特權,
而不是setgid(),因為這樣最通用。尤其當整個過程中無法滿足EUID為0的時候,
setgid()根本無法永久放棄特權。
假設一個Solaris下的程序同時setuid、setgid過,較理想的釋放順序應該是先釋放
setgid特權,後釋放setuid特權。
Copyright © Linux教程網 All Rights Reserved