Apache下root許可權執行CGI
阿新 • • 發佈:2019-01-25
問題場景
Apache預設是以daemon使用者(或者其他other使用者)和daemon使用者組啟動的,所以其worker程序也是daemon許可權的,這樣,worker程序fork的CGI程序,以及CGI再fork的子程序,都是daemon許可權的。如果想在CGI或者CGI子程序中操作一些需要root許可權的檔案或者命令,就會報許可權錯誤。
Apache其實也可以通過root許可權來啟動,需要在編譯時加入特定選項,而且配置中的User和Group都修改成root,但是Apache強烈建議不要這麼做,應該是出於安全考慮。
那麼怎麼解決非root使用者啟動的Apache的CGI程序可以訪問需要root許可權才能訪問的資源呢?
解決方法
宣告:本方法根據網上一些方法整理而來,經驗證有效。
- 在root許可權下編寫並編譯你的CGI;
- 在你的CGI開始的時候新增如下程式碼:
...
uid_t uid = getuid();//獲取當前程序的user id
uid_t euid = geteuid();//獲取當前程序的effective user id
//euid應該為0,即root許可權
printf("befor setreuid uid: %u, euid: %u\n", uid, euid);
if (setreuid(euid, uid)) {//交換有效使用者ID和實際使用者ID
perror("setreuid" );
return -1;//出錯的話還是儘早返回吧,否則後面也會報許可權錯誤
}
//此時的uid應該為0,擁有了root許可權
printf("after setreuid uid: %u, euid: %u\n", getuid(), geteuid());
...
- 對編譯出來的二進位制CGI檔案加s許可權,並拷貝到Apache的CGI執行目錄;
chmod +s your_program.cgi
- 這樣應該就可以了。(不行的話還有別的辦法)
簡單測試
- 首先,假設有一個需要root許可權才能執行的檔案
- 在root許可權下編寫需要訪問a.out的程式test_v1.cpp
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
uid_t uid ,euid;
uid = getuid();
euid = geteuid();
printf("my uid :%u\n", uid);
printf("my euid :%u\n", euid);
system("/home/guest/a.out");
return 0;
}
root許可權編譯,guest許可權執行
可以看到當前uid和euid都是other許可權的,訪問a.out時許可權受限
在root許可權對檔案test_v1加s許可權後,guest許可權再次執行
可以看到,此時的euid已經變成root許可權的了,但是還是無法訪問a.out
- 修改test_v1程式碼,修改後test_v2.cpp如下
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
uid_t uid ,euid;
uid = getuid();
euid = geteuid();
printf("my uid :%u\n", uid);
printf("my euid :%u\n", euid);
if(setreuid(euid, uid))//交換有效使用者ID和實際使用者ID
perror("setreuid");
printf("after uid :%u\n", getuid());
printf("after euid :%u\n", geteuid());
system("/home/polli/test/a.out");
return 0;
}
在root許可權編譯test_v2, 並加s許可權,guest許可權執行test_v2
可以看到交換許可權後,uid變為root許可權,可以正常執行a.out