來源:《Computer Security》A Hands-on Approach — Wenliang Du
Chapter01 SetUID Programs
書上的內容是很好的。這裏僅僅做個學習筆記。
我的文筆似乎弱的有點出奇。不流暢,像說明書一樣🙂
題目標題:進一步理解特權程序 (我不敢命名叫深入理解特權程序😄)
有點像:一些水水的內容,總是命名爲”基於…"的很很高大上的名字。而裏面就用了個很淺淺的內容。
文章目錄
前言
一本書適合的閱讀人羣,書中涵蓋的內容一般會在書的前言部分展現。這本書也是如此。
閱讀這本書,我們希望:
- 理解多種攻擊和防禦是如何工作的
- 對抗攻擊,評估系統所面臨的風險
這本書的三個主要點:軟件安全、web安全、網絡安全
這本書的作者:Wenliang(Kevin) Du. 所展現的是一個很有想法的人。
I hear and I forget. I see and I remember. I do and I understand
荀子曰:不聞不若聞之,聞之不若見之,見之不若知之,知之不若行之。學至於行而止矣。行之,明也。
所學的東西,用於實踐是快樂的事情。
但是我的本科階段有所欠缺。
課外閱讀與實驗是書本內容必不可少的補充。
但是這些我明白的晚了些。比較頭疼的是,我還喜歡偷懶。
江山易改,本性難移。所以還是找個好些的環境,對於我而言是比較好的方式。
摘要&&總結
特權程序,雖然給我們帶來了便利,但是要注意它的安全性問題。
而關於setuid,如何寫出安全的代碼。我還不曉得。
但是目前,我們要注意能力泄露,”中間商sh“,不要使用system()等。
下面思路:特權程序的介紹 + 特權程序產生的原因 + 理解特權程序 + 編寫特權程序的注意事項
特權程序
筆記,必然是建立在我的背景知識之上的。
在這之前,我先回憶下。
我的linux入門書籍是《鳥哥私房菜》。當然目前我感覺《linux就該這麼學》比較好入門些。
有節討論課的有關內容是:SUID/SGID/SBIT.
當時我是挺懵的。在之後的時間,漸漸對linux比較熟悉,大體知道怎麼回事。
後面的內容,建立在我們已經理解SUID
的基礎之上。
可以參考:Linux 特殊權限 SUID,SGID,SBIT
特權程序的產生
上面鏈接的passwd
命令我們稱爲特權程序。
首先,我還是贅述下,爲什麼需要特權程序。
我們的密碼保存在/etc/shadow
文件中。shadow的權限如下
dacao@dacao-X555LJ:~$ ls -alh /etc/shadow
-rw-r----- 1 root shadow 1.4K 3月 12 18:21 /etc/shadow
除了root用戶,其他用戶都沒有修改shadow的權限。
但是每個用戶都應該有修改自身密碼的權限。否則總是得麻煩root用戶總是很不好的。
-
第一個方法,是寫一個更細粒度的程序。用戶可以修改shadow文件。但每一個用戶只能修改shadow中自己對應的密碼。但是這個機制的程序會比較複雜。
-
第二種方法,是提供服務(service)。每次修改密碼的時候,需要後臺守護進程的幫助。(這個概念,我不清楚。)
-
第三種方法,是我們這裏的特權程序。
Set-UID
的特權程序,執行過程中獲得root用戶權限,從而可以修改shadow文件。
書中是用超人的故事來比喻的,挺好。
不得不說,特權程序獲得到特權,過大。比如說修改密碼passwd的過程中,它暫時得到了所有的root權限。所以我們必須慎重的創建特權程序的代碼,使其僅僅能執行我們指定的行爲。
理解特權程序
也許,在前面的鏈接中,我們已經基本上理解了SUID的基本用法。但是我們這裏還是得補充。
(或許這篇文章,可以換個方向:eg,你真的理解了SUID嗎?三分鐘真正理解SUID。😄)
補充三個概念:真實uid(real user id), 有效uid(effective user id), 被保存的uid(saved user id)
real uid表示進程的實際執行者, 只有root才能更改real uid, effective uid用於檢測進程在執行時所獲得的訪問文件的權限(既 但進程訪問文件時, 檢測effective uid有沒有權限訪問這個文件), saved uid用於保存effective uid, 以便當effective uid設置成其他id時可以再設置回來
一般情況下, 當一個程序執行時(既調用exec), 進程的effective uid會和real uid一致, 但是可執行文件有一個set-user-ID位, 如果這個set-user-ID位被設置了, 那麼執行exec後, 進程的effective uid會設置成可執行文件的屬主uid, 同時saved uid也會被設置成effective uid.
舉例說明: 用戶zzz執行了文件a.out, a.out的屬主爲hzzz且設置了set-user-ID位. 現在本進程的real uid爲zzz, effective uid = saved uid = hzzz.
一個例子幫助理解set-uid
#當前目錄:/tmp
$ cp /bin/cat ./mycat
#從某種角度來說,特權程序的所屬用戶是root用戶(組員),特權程序纔有意義。
$ sudo chown root mycat
$ ls -alh mycat
-rwxr-xr-x 1 root seed 50K Apr 4 22:41 mycat
$ ./mycat /etc/shadow
./mycat: /etc/shadow: Permission denied
$ sudo chmod 4755 mycat
$ ls -alh mycat
-rwsr-xr-x 1 root seed 50K Apr 4 22:41 mycat
#虛擬機中
$ ./mycat /etc/shadow
root:$6$NrF46O1p$.vDnKEtVFC2bXslxkRuT4FcBqPpxLqW05IoECr0XKzEEO5wj8aU3GRHW2BaodUn4K3vgyEjwPspr/kqzAqtcu.
編寫特權程序的注意事項
首先,我們簡單思考下。像/bin/sh
、vi
這樣的程序,從安全的角度來考慮,是不應當被設置成特權程序。
否則,普通的用戶可能會獲得具有root權限的sh和vi。
我們應當:
- 避免Capability Leaking
- 使用 execve() 代替 system()
- 代碼和數據分離等
下面會用具體的示例展示。
這些展示網上很多,我偷懶在簡單寫寫。詳細內容見書上。
SEED實驗——Environment Variable and Set-UID Program實驗描述與實驗任務
Capability Leaking
在特權程序降級之前,/etc/zzz
的文件描述符沒有釋放。導致降級之後/特權程序結束之前,任然可以修改/etc/zzz
文件。
這裏稍微難點是:setuid(getuid())
.參考:setuid和seteuid
//文件名:cap_leak.c
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
void main(void){
int fd;
char *v[2];
fd = open("/etc/zzz",O_RDWR|O_APPEND);
if(fd == -1){
printf("Cannot open /etc/zzz\n");
exit(0);
}
printf("fd is %d\n",fd);
//disable privilege
setuid(getuid());
v[0] = "/bin/sh";v[1]=0;
execve(v[0],v,0);
}
Unsafe Approach: Using system()
一方面,system()會系統PATH來查找命令,這是不安全的。
另一方面,數據和命令放在一個字符串中。雖然簡單些,但卻帶來了安全性問題。
//文件名:cat_all.c
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char *argv[]){
char *cat = "/bin/cat";
if(argc < 2){
printf("Please type a file name \n");
return 1;
}
char *command = malloc(strlen(cat) + strlen(argv[1]) +2);
sprintf(command,"%s %s",cat,argv[1]);
system(command);
free(command);
return 0;
}
Safe Approach: Using execve()
我們使用execve(),代替system() ,將數據和命令分離。
//文件名(not good):safecatall.c
#include <string.h>
#include <stdio.h>
#include <unistd.h>
int main(int agrc, char *argv[]){
char *v[3];
if(agrc < 2){
printf("Please type a file name .\n");
return 1;
}
v[0] = "/bin/cat";
v[1] = argv[1];
v[2] = 0;
execve(v[0],v,0);
return 0;
}
參考文章
真實uid(real user id), 有效uid(effective user id), 被保存的uid(saved user id)
SEED實驗——Environment Variable and Set-UID Program實驗描述與實驗任務
利用capability特徵加強Linux系統安全 —>沒看懂
id會顯示用戶以及所屬羣組的實際與有效ID。若兩個ID相同,則僅顯示實際ID。