Linux

程序啟動後更改 /proc/PID/environ

  • April 15, 2020
$ k=v p &
[1] 3028

有什麼辦法可以仍在執行時更改不提及p的內容嗎?/proc/3028/environ``k=v p

在 Linux 上,您可以覆蓋堆棧上環境字元串的值。

因此,您可以通過用零或其他任何內容覆蓋條目來隱藏條目:

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char* argv[], char* envp[]) {
 char cmd[100];

 while (*envp) {
   if (strncmp(*envp, "k=", 2) == 0)
     memset(*envp, 0, strlen(*envp));

   envp++;
 }

 sprintf(cmd, "cat /proc/%u/environ", getpid());

 system(cmd);
 return 0;
}

執行為:

$ env -i a=foo k=v b=bar ./wipe-env | hd
00000000  61 3d 66 6f 6f 00 00 00  00 00 62 3d 62 61 72 00  |a=foo.....b=bar.|
00000010

k=v被 覆蓋\0\0\0

請注意,setenv("k", "", 1)覆蓋該值將不起作用,因為在這種情況下,"k="會分配一個新字元串。

如果您沒有使用/以其他方式修改k環境變數,那麼您還應該能夠執行類似的操作來獲取堆棧上字元串的地址(嗯,其中之一):setenv()``putenv()``k=v

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int main(int argc, char* argv[]) {
 char cmd[100];
 char *e = getenv("k");

 if (e) {
   e -= strlen("k=");
   memset(e, 0, strlen(e));
 }

 sprintf(cmd, "cat /proc/%u/environ", getpid());

 system(cmd);
 return 0;
}

但是請注意,它僅刪除環境中收到的條目之一**。**k=v通常,只有一個,但沒有什麼能阻止任何人在傳遞給的 env 列表中同時傳遞k=v1k=v2(或k=v兩次)execve()。這一直是過去安全漏洞(例如CVE-2016-2381)的原因。當以相同的名稱導出變數和函式時,它可能真的發生bash在 shellshock 之前。

在任何情況下,總會有一個小視窗,在此期間 env var 字元串尚未被覆蓋,因此您可能希望找到另一種方法將秘密資訊傳遞給命令(例如管道),如果通過/proc/pid/environ是一個問題。

另請注意,與 , 相反/proc/pid/cmdline/proc/pid/environment只能由具有相同 euid 或 root 的程序訪問(或僅當程序的 euid 和 ruid 看起來不同時才可訪問)。

您可以在 中向他們隱藏該值/proc/pid/environ,但他們仍然可以獲取您在記憶體中對字元串所做的任何其他副本,例如通過將調試器附加到它。

請參閱https://www.kernel.org/doc/Documentation/security/Yama.txt以了解至少防止非 root 使用者這樣做的方法。

引用自:https://unix.stackexchange.com/questions/302948