Attacks_Through_Environment_Variables

來源:《Computer Security》A Hands-on Approach — Wenliang Du

Chapter02 Attacks Through Environment Variables

書上的內容是很好的。這裏僅僅做個學習筆記。

我把這些整體放在一章。如果對要點進行詳細說明,可能得好幾篇文章才能搞定,比較花時間。而現在網上的文章已經很多,比較舊的知識點應該大體都有不錯的整理。故而,簡略寫之。

當然,還有自身能力的原因。比如動態庫那裏。書上的動態庫那樣寫有它的原因。但我比較喜歡的庫寫法還是 頭文件+編譯參數 來實現。但是我有寫過幾次庫呢?


摘要&&總結

這章是對上一章的補充。

講述環境變量對特權程序的影響。

一般是普通用戶,執行特權程序。而特權程序一般是非特權程序(eg:bash)的子進程。

這導致特權程序的環境變量來自普通用戶。這具有一定的危險性。

從安全的角度,來看本章,並沒有很多知識點。

但是本章提供的背景知識還是不錯的。

要點:

  • 環境變量、shell變量、環境變量與shell變量的關係、環境變量在進程中的位置、shell變量對子進程的影響
  • 靜態庫、動態庫、增加自定義的庫
  • getenv()secure_getenv()
  • Set-UID方法和Service方法
  • built-in命令


環境變量對特權程序的影響

在開始本章之前,我們得先熱身下:linux中環境變量的設置。

我隨意從網上搜了兩篇文章。

linux 環境變量設置(臨時 + 永久)
Linux /etc/profile文件詳解

環境變量與shell變量

Linux 環境變量&&進程 ⭐️ (這篇鏈接文章是很好的。)

(記得當年這內容相關的討論課是我講滴。但是當時我肯定是不懂的)

我這裏僅僅做下總結性的描述,不用實驗進行驗證。詳細內容見書上+鏈接文章。

(1) 環境變量是name-value pairs ,存儲在進程的內存中。

(2) 在程序中,存儲位置是**environ全局變量。可以通過putenv()unsetenv()setenv()getenv()進行環境的增刪該查。

//打印所有環境變量
//strings /proc/$$/environ
#include <stdio.h>
#include <unistd.h>

extern char** environ;

void main(int argc,char *agrv[],char *envp[]){
    int i=0;
    while (environ[i]!=NULL){
        printf("%s\n",envp[i]);
        i++;
    }
    
}

/*******************************************/
//環境變量&&execve()
/*我們現在要構建一個函數
 * ./switch_show_env x
 * 
 * 當參數是1:不傳遞環境變量
 * 當參數是2:傳遞自定義的環境變量
 * 當參數是3:傳遞所有的環境變量
 * 
 * 之後打印所有變量
 * 很漂亮的程序,演示execve的使用,展示了三種不同情況下的環境變量的傳遞
 */

#include <stdio.h>
#include <unistd.h>

extern char **environ;

void main(int argc,char *argv[],char *envp[]){

    char *v[2];
    char *new_envp[3];

    if(argc<2)
        return;
    
    v[0] = "/usr/bin/env";
    v[1] = NULL;

    new_envp[0] = "name=dacao";
    new_envp[1] = "Tel=173";
    new_envp[2] = NULL;

    switch (argv[1][0])
    {
    case '1':
        execve(v[0],v,NULL);
        break;
    case '2':
        execve(v[0],v,new_envp);
        break;
    case '3':
        execve(v[0],v,environ);
    default:
        printf("enter the correct argv");
        break;
    }

}

(3)環境變量在內存給中的位置

在這裏插入圖片描述

(4)shell變量是由shell程序來維護。

(5)環境變量的設置,可以見之前的參考文章。

(6)shell程序(eg:bash)會拷貝環境變量到shell變量中。

(7)書上說,shell變量,也能增添到環境變量中。我嘗試了下:export並不能增添進程自身的環境變量,但可以增添環境變量到子進程。

$ export Tong=haha

$ echo Tong
haha

$ strings /proc/$$/environ | grep Tong 
#(進程自身)輸出空

$ env | grep Tong
Tong=haha
#env不是內置命令,所以作爲(bash)的子進程。子進程中,有增添的環境變量

(8)子進程的環境變量

在這裏插入圖片描述

(9) 當環境變量和predefined shell 變量 名稱相同時,會發生什麼?

比如說:在~/.bashrc中,定義export BASHPID=1000 ;而bash啓動的時候,會隨機有個pid。

首先我們有觀點:

  • 後面的會覆蓋前面的。或者說是後面的起作用。
  • BASHPID被修改對程序暫時沒有什麼影響。就像我們修改PWD之後,並不代表我們的工作目錄是指被改動。這些變量記錄“現象”,但本質沒有改動。

好,我們來驗證下。

#打開一個bash
#查看當前的pid
$ echo $$ (echo $BASHPID)
15812
#修改 ~/.bashrc,在末尾增加 export BASHPID=1000
$ vim ~/.bashrc 
$ cat ~/.bashrc | grep BASHPID
export BASHPID=1000

$ source ~/.bashrc
$ echo $$ (echo $BASHPID)
15812

#關閉shell重開
echo $$ (echo $BASHPID)
不是1000

#直接修改BASHPID,被自動修正
$ BASHPID=1000
$ echo $BASHPID
20040

實驗至此結束。實驗結果未知。


靜態庫&&動態庫

C++靜態庫與動態庫

elf文件格式

以前,編譯程序的時候,報錯缺少庫。缺少的庫名+這個庫默認的查找路徑+增添自定義的庫路徑

這一套下來,大體能把問題解決了。參考:

查看一個可執行文件或者庫的依賴庫

Linux 共享庫LD_PRELOAD環境變量

正確使用環境變量LD_LIBRARY_PATH

靜態程序鏈接的時候,把庫中對應的函數,拷貝過去。這面臨的兩個問題是:程序加載進入內存,比較費內存;當庫更新的時候,已編譯的程序沒有更新。

動態庫,在鏈接的時候,.interp記錄動態鏈接器(ld)的位置生成可執行文件;可執行文件被加載進內存;在.interp中查找連接器的位置;通過鏈接器找到共享庫函數;進入main函數;

在這裏插入圖片描述

特權程序鏈接的時候,我目前感覺沒有什麼風險。因爲:

在特權程序中,當使用到動態鏈接的時候,與鏈接有關的變量的使用,必須要求用戶ID和有效ID相同。

感覺這挺安全的。



其他

getenv() 和 secure_getenv()

我們在特權程序中,一般不會用getenv(),因爲獲取的環境變量來自普通用戶,這並不安全。

另一個要注意的是,我們可能會使用execve(),來喚醒另一個程序。

這被喚醒的程序,可能是普通程序。這個普通程序中,也不要用getenv()。

**可以用secure_getenv(),代替。**當檢測到有效ID和實際ID不同的時候,其返回NULL。即:

特權程序中,無法正常使用secure_getenv()。

如果要使用secure_getenv(),在程序的開頭加上#define _GNU_SOURCE (原因見man getenv)


built-in命令

參考:

什麼是bash shell的內建(build in)命令

Shell 的內置(builtin)命令是什麼,常常傻傻分不清

另外一種 Shell 支持的命令即本文要重點總結的 builtin(“內置”) 命令,builtin 命令是 shell (譬如 bash)裏自帶的命令,由於其作爲 shell 程序(進程)的一部分常駐在內存中,所以和一個普通命令相比起來, builtin 命令的執行速度要快得多。具體的原因很簡單,就是因爲在 Shell 中執行普通命令即運行程序,要先 fork(),然後是 exec(),經歷創建 子 Shell 進程以及從磁盤上調入程序覆蓋原進程的完整過程,而調用一個 builtin 命令本質上只是執行 bash 進程中的一個常駐內存的函數,其速度絕對不可同日而語。

由於各種 Shell 所支持的 builtin 命令各不相同,對於有些常用的命令,爲避免用戶當前所使用的 Shell 不支持,系統會提供同名的程序文件。譬如 echo,既是 bash 的 builtin 命令也是一個獨立的命令程序。根據 bash 中執行命令的優先級,對於同名的命令,內置命令會優先被執行,所以當我們在 bash 中直接輸入 echo 命令時執行的是 bash 的 buildin 命令,如果要執行獨立的命令程序 echo,則需要輸入全路徑 /bin/echo

Set-UID方法和Service方法

Set-UID方法,沒有Service方法安全。但Set-UID方法,節省內存,不需要常駐的後臺服務。

在這裏插入圖片描述

參考文章

Linux 環境變量&&進程 —> 未讀完

C++靜態庫與動態庫

elf文件格式

查看一個可執行文件或者庫的依賴庫

Linux 共享庫LD_PRELOAD環境變量

正確使用環境變量LD_LIBRARY_PATH

c庫函數getenv引起的core dumped

Shell 的內置(builtin)命令是什麼,常常傻傻分不清

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