2014-12-12 109 views

回答

9

system()execve()以不同的方式工作。 system()將始終調用shell,並且該shell將作爲單獨的進程執行該命令(這就是爲什麼當您使用system()時可以在命令行中使用通配符和其他shell工具的原因)。

execve()(和exec()家族中的其他函數)將當前進程替換爲直接生成的進程(execve()函數不會返回,除非發生故障)。實際上,system()實現應該使用一系列調用fork(),execve()wait()來執行其功能。

當然,這兩者都是危險的,具體取決於當進程具有root權限時正在執行的內容。但是,由於它使用了額外的shell「層」,因爲它會在您的問題(即進程具有suid位)的情況下調用根shell時打開機房安全漏洞,所以它會帶來一些額外的危險。

+0

所以,當使用execve()..你提到它取代當前進程..該進程仍然setuid? – Jake 2014-12-12 10:44:55

+0

是的。由execve啓動的「新」進程繼承了被替換的一些屬性,例如filedescriptors,sockets等,而有效的uid就是其中之一,但是在執行execve期間uid會發生變化,比如如果execve參數指向的可執行文件已設置suid位。在這種情況下,uid會根據文件系統中的定義更改爲文件所有者。 – Marcelo 2014-12-12 10:54:17

12

system將調用shell(sh)執行作爲參數發送的命令。 system的問題,因爲shell行爲取決於運行該命令的用戶。一個小例子:

創建文件test.c

#include <stdio.h> 

int main(void) { 
    if (system ("ls") != 0) 
     printf("Error!"); 
    return 0; 
} 

然後:

$ gcc test.c -o test 

$ sudo chown root:root test 

$ sudo chmod +s test 

$ ls -l test 
-rwsr-sr-x 1 root root 6900 Dec 12 17:53 test 

創建在當前目錄中名爲ls腳本:

$ cat > ls 
#!/bin/sh 

/bin/sh 

$ chmod +x ls 

現在:

$ PATH=. ./test 
# /usr/bin/id 
uid=1000(cuonglm) gid=1000(cuonglm) euid=0(root) egid=0(root) groups=0(root), 
24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),105(scanner), 
110(bluetooth),111(netdev),999(docker),1000(cuonglm) 
# /usr/bin/whoami 
root 

糟糕,你有一個擁有root權限的shell。

execve不調用shell。它執行傳遞給它的程序作爲第一個參數。該程序必須是二進制可執行文件或腳本以shebang行開頭。

+0

不說'system()'沒有問題,但不會通過在二進制可執行文件中使用絕對路徑來解決上述問題嗎? – Bratchley 2014-12-12 12:07:25

+1

@JoelDavis,不,你至少需要清除整個環境,給一些envvars(PATH,HOME ...)提供理智的默認值,如果需要,在消毒後保存一些env vars(TERM,DISPLAY,LANG。 ..)確保fds 0,1,2是開放的...基本上做什麼sudo。即使那樣,我也不會去那裏。如果可以避免,請不要在特權升級上下文中調用shell。請注意,'ls'可以用它的環境做一些奇特的事情,所以即使沒有'system()',你也應該清理環境。在使用setuids時,您希望儘量減少以root身份執行的操作(通常不執行命令)。 – 2014-12-12 14:07:52

+3

@JoelDavis:不,即使使用完整路徑,仍然存在問題。如果你使用'/ bin/ls',用戶可以將'/'添加到'$ IFS',導致shell將'/ bin/ls'分割爲'bin'和'ls'。現在,在我的答案中,當前目錄中名爲'bin'的可執行文件可以與'ls'做同樣的事情。 – cuonglm 2014-12-12 16:39:12

0

除了提及的system()安全問題之外,產生的進程繼承了主程序的環境。當使用suid時,例如當調用進程設置LD_LIBRARY_PATH-環境變量時,這可能是非常有問題的。

exec()-家庭調用程序可以調用exec()之前調用程序所需的(和安全)所需的環境設置。

當然,由system()調用的shell本身可能有安全問題。