進一步理解特權程序

來源:《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)

參考:setuid和seteuid

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/shvi 這樣的程序,從安全的角度來考慮,是不應當被設置成特權程序。

否則,普通的用戶可能會獲得具有root權限的sh和vi。

我們應當:

  • 避免Capability Leaking
  • 使用 execve() 代替 system()
  • 代碼和數據分離等

下面會用具體的示例展示。

這些展示網上很多,我偷懶在簡單寫寫。詳細內容見書上。

SEED實驗——Environment Variable and Set-UID Program實驗描述與實驗任務

SET-UID 程序漏洞實驗


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;
}

在這裏插入圖片描述

參考文章

Linux 特殊權限 SUID,SGID,SBIT

真實uid(real user id), 有效uid(effective user id), 被保存的uid(saved user id)

SEED實驗——Environment Variable and Set-UID Program實驗描述與實驗任務

Linux 下/etc/passwd文件詳解

system()函數的使用

利用capability特徵加強Linux系統安全 —>沒看懂

Linux id命令

id會顯示用戶以及所屬羣組的實際與有效ID。若兩個ID相同,則僅顯示實際ID。

SEED:一套計算機安全教育的教學實驗機制

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章