shell基础
自定义变量
一般来说,自定义变量都是局部变量,一个shell中的局部变量不会被另一个shell读取到,包括子shell。而使用export,将变量设置成环境变量后,可以实现在子进程中该变量依然有效,同时,子进程无法修改父进程中的变量,即使使用export也不行。
env命令
用于显示系统中已存在的环境变量以及在定义的环境中执行指令。
语法=>
env(选项)(参数)
选项=>
-i/- :开始一个新的空的环境 -u<变量名> :从当前环境中删除指定的变量
参数=>
变量定义:定义在新的环境中变量,定义多个变量则用空格隔开。格式为"变量名=值"。
指定:指定要执行的指令各参数
echo命令
用于输出指定内容,其中:
单引号:将' '的内容都作为字符串而忽略所有的命令和特殊字符
双引号:解析内部特殊字符,若需要忽略则利用''来转义
反引号:包含一个命令字符串,其中的命令会先执行得到的结果会返回到层命令执行
=>这是一个实验过程中遇到的小问题:
正常实例
小于4.3的bash版本中=>
Bash允许在Bash的shell中使用环境变量来定义函数,如果环境变量的值以字符"( ){"开头,那么这个变量就会被当作是一个导入函数的定义(Export),并且这种定义只有在shell启动的时候生效。
可以看到,在上面这次尝试中我们的VAR变量并没有引入环境变量中。
使用export成功看到环境变量VAR被当作函数执行了。
这里使用env命令在新的环境中先设置了变量,再执行了指定的指令,并且执行完成后当前的环境变量不受影响。bash -c是为了启动bash时就执行VAR函数,这里必须新起一个bash,因为只有bash启动时才会解析函数的定义。
bash 4.4.20中=>
在环境bash 4.4.20版本中, Bash 会把满足 "BASH_FUNC_函数名%%=() { 函数体" 格式的环境变量作为函数源码解析并导入。因此,两个同名的变量和函数也不会冲突,可以同时导入:
env 'BASH_FUNC_var%%=() { echo "1";}' bash -c 'var'
==>1
env 'var=2' 'BASH_FUNC_var%%=() { echo "1";}' bash -c 'var'
==>1
env 'var=2' 'BASH_FUNC_var%%=() { echo "1";}' bash -c 'echo $var'
==>2
漏洞原理
看了几份大神们分析源码的报告(也没看明白啥就是了awtcl),大部分都认为漏洞主要利用的地方在于parse_and_execute()
这一函数,下面这部分源码在variables.c中代码的315行处,借助注释我们可以看到代码用于初始化当前环境的环境变量:
/* Initialize the shell variables from the current environment. If PRIVMODE is nonzero, don't import functions from ENV or parse $SHELLOPTS. */ void initialize_shell_variables (env, privmode) char **env; int privmode; { char *name, *string, *temp_string; int c, char_index, string_index, string_length, ro; SHELL_VAR *temp_var; create_variable_tables (); for (string_index = 0; string = env[string_index++]; ) { char_index = 0; name = string; while ((c = *string++) && c != '=') ; if (string[-1] == '=') char_index = string - name - 1; /* If there are weird things in the environment, like `=xxx' or a string without an `=', just skip them. */ if (char_index == 0) continue; /* ASSERT(name[char_index] == '=') */ name[char_index] = '