# 02 Environment Variables and Attacks NTNU 資安攻防演練 ##### [Back to Note Overview](https://reurl.cc/XXeYaE) ##### [Back to Information Security: A Hands-on Approach](https://hackmd.io/z5PJjK7eTJ29YEhMjyAaCw) <!-- {%hackmd @sophie8909/pink_theme %} --> ###### tags: `攻防演練` `110-1` `CSIE` `選修` `NTNU` <!-- tag順序 [學校] [系 必選] or [學程 學程名(不含學程的 e.g. 大師創業)] [課程] [開課學期]--> ## Overview - Environment Variables - Attack Interfaces Caused by Environment Variables - Attack via Dynamic Linker - Attack via External Program - Attack via Library - Attack via Application Code - Appendix ## Environment Variables - An environment variable is a <font color=red> dynamic-named value </font> that can affect the way running processes will behave on a computer. - You can treat them as <font color=red> **systemwise configuration**</font>. - By default, when a process is created, it **inherits** a <font color=blue> duplicate run-time environment of its parent process</font>, except for explicit changes made by the parent when it creates the child. - You can use **env** to check the environment variables in your computer. ```c= // First Method #include <stdio.h> int main(int argc, char *argv[], cahr *envp[]){ int i = 0; while(envp[i] != NULL){ printf("%s\n", envp[i]); } return 0; } ``` - main() is called by <font color=red> __libc_start_main() </font> which you can find its definition in **glibc/csu/libc-start.c**. You can see how the environment variables are transfered. ```c= // Second Method #include <stdio.h> // you can find it in glibc/posix/enviro.c extern char **environ; // also can get env int main(){ ... } ``` ```c= // Third Method #include <stdlib.h> char *getenv(const char *name); int setenv(const char *name, const char *value, int overwrite); int unsetenv(const char *name); ``` ```c= #include <unistd.h> int execve( const char *pathname, char *const argv[], char *const envp[]); ``` - **execve()** is different to **fork()**. <font color=red> There is no new process when using **execve()**</font>. - You can pass the envoronment variables through the third argument in **execve()**. ### shell variable - A shell script is a computer program designed to be run by the shell, a command-line **interpreter**. - Since there are lots of shells, there are lots of grammars. - The most horrible part is that **they are similar** and therefore, it is hard to debug. - Shell variables are interval variables maintained by the shell. ![](https://i.imgur.com/MsrNICY.png) ```shell= $ strings /proc/$$/environ | grep LOGNAME LOGNAME=seed $ echo $LOGNAME seed $ LOGNAME=neokent $ echo $LOGNAME neokent $ strings /proc/$$/environ | grep LOGNAME LOGNAME=seed $ unset LOGNAME $ echo $LOGNAME $ strings /proc/$$/environ | grep LOGNAME LOGNAME=seed ``` - Since <font color=red> **env** is a child process </font> to shell, so you cannot observe the shell's environment variables through this command. - > $$ is the current shell's PID. ```shell= $ strings /proc/$$/environ | grep LOGNAME LOGNAME=seed $ LOGNAME2=alice $ export LOGNAME3=bob $ env | grep LOGNAME LOGNAME=seed LOGNAME3=bob $ strings /proc/$$/environ | grep LOGNAME LOGNAME=seed $ unset LOGNAME $ env | grep LOGNAME LOGNAME3=bob ``` ## Attack Interfaces Caused by Environment Variables - The environment variable is a kind of interface for the attacker to input some malicious (惡意的) data to your program. - This path is hard to be noticed. - Even worse, it is obvious that the user can **change the environment variables without root privilege**. ![](https://i.imgur.com/28krSAz.png) - **Linker**: A linker is used to <font color=blue> **find** </font> the external libraries used by a program. The lookup place is determined by the <font color=red> environment variables</font>. - **Library**: Most programs invoke functions from external libraries and they may use <font color=red> environment variables</font>. - **External Program**: A program may invoke external programs and they may use <font color=red> environment variables</font>. - **Application Code**: A program may use <font color=red> environment variables</font> in its code but the developer may not realize it. ## Attack via Dynamic Linker - **Static Linking**: - At compile time, all required functions and variables are copied into a target application by a compiler, linker, producting an object file. - The executable is <font color=blue> self-contained </font>. - The executable's size is larger than dynamic linking file. - There will be no <font color=red> **dependency hell issus**</font>. - **Dynamic Linking**: - A dynamic linker loads and links the shared libraries needed by an executable <font color=red> at run time</font>, by copying the content of libararies from persistent storage to RAM. filling jump tables and relocating pointers. - Save memory ```shell= $ gcc -o hello_dynamic hello.c $ gcc -static -o hello_static hello.c $ ls -al hello* -rw-rw-r-- 1 seed seed 79 Jun 29 11:17 hello.c -rwxrwxr -x 1 seed seed 16696 Jun 29 11:17 hello_dynamic -rwxrwxr -x 1 seed seed 871704 Jun 29 11:18 hello_static $ ldd hello_static not a dynamic executable $ ldd hello_dynamic linux -vdso.so.1 (0 x00007ffedc7dc000) libc.so.6 => /lib/x86_64 -linux -gnu/libc.so.6 (0 x00007f517a38b000) /lib64/ld-linux -x86 -64.so.2 (0 x00007f517a597000) ``` - <font color=blue> **LD_PRELOAD** </font>: This contains a list of shared libraries, which will be serached first by the dynamic linker. - <font color=blue> **LD_LIBRARY_PATH** </font>: This contains a list of directories, where the dynamic linker will search. - > These two variables can be set by the user. ```shell= $ gcc mytest.c -o mytest $ ldd mytest linux -vdso.so.1 (0 x00007ffdb7fe3000) libc.so.6 => /lib/x86_64 -linux -gnu/libc.so.6 (0 x00007fd7b96a1000) /lib64/ld-linux -x86 -64.so.2 (0 x00007fd7b98ad000) $ gcc -c mysleep.c $ gcc -shared -o libmysleep.so mysleep.o $ export LD_PRELOAD =./ libmysleep.so $ ldd mytest linux -vdso.so.1 (0 x00007fffd2b7d000) ./ libmysleep.so (0 x00007ff1e800f000) libc.so.6 => /lib/x86_64 -linux -gnu/libc.so.6 (0 x00007ff1e7e0a000) /lib64/ld-linux -x86 -64.so.2 (0 x00007ff1e801b000) $ ./mytest I am not sleeping !! $ unset LD_PRELOAD $ ./mytest # sleep for a second $ ``` - <font color=purple> If a process's RUID and EUID are different, the dynamic linker will **ignore** LD_PRELOAD and LD_LIBRARY_PATH</font>. ```shell= $ cp /usr/bin/env ./myenv $ sudo chown root myenv $ sudo chmod +s myenv $ export LD_PRELOAD =./ libmysleep.so $ export LD_LIBRARY_PATH =. $ export LD_MYOWN=neokent $ env | grep LD_ LD_PRELOAD =./ libmysleep.so LD_MYOWN=neokent LD_LIBRARY_PATH =. $ ./myenv | grep LD_ LD_MYOWN=neokent ``` ## Attack via External Program - **system()**: The system() library function uses <font color=red> fork(2) </font> to create a child process that executes the shell command specified in command using execl(3) as follows: execl(<font color=blue>”/bin/sh”</font>, ”sh”, ”-c”, command, (char *) NULL); - **execve()**: execve() executes the program referred to by pathname. This causes the program that is currently being run by <font color=red> the calling process to be replaced </font>with a new program, with newly initialized stack, heap, and (initialized and uninitialized) data segments. - Conclusion: We should use **execve() family** instead of system(). ## Attack via Library - Example: A locale is a set of parameters that defines the user's language, region and any special variant preferences that the user wants to see in their user interface. - LANG - NLSPATH - $\cdots$ - User can not control a locale-based program's output