今天被同事问到env与set的区别,感觉很久不看忘了,所以简单的记一笔,方便后续查阅
初识env
env命令可以显示当前用户的环境变量,还可以用来在指定下执行其他命令
env查看有哪些环境变量,并且可以用$ 变量读取env中的变量名对应的变量值
set,env和export、以及declare命令的异同:
set命令显示当前的变量,包括当前用户的变量
env命令显示当前用户的变量;
export命令显示当前导出成用户变量的shell变量
declare命令可以明确进行变量类型的声明。
declare [+/-] [变换选项] 变量名
shell默认是字符串型,如果需要加减乘除,需要定义为整型
declare命令:改变默认变量的类型
-给变量设定类型属性
+取消变量类型属性
-a声明为数组类型
-i声明为整型
-x 将变量设置为环境变量 相当于export命令 declare -x test=123(export是简化命令。最终执行的是declare -x命令)
-r 讲变量声明为只读变量
-p 显示指定变量的被声明的类型
每个shell有自己特有的变量(set)显示的变量,这个和用户变量是不同的,当前用户变量和你用什么shell无关,不管你用什么shell都在,比如HOME,SHELL等这些变量,但shell自己的变量不同shell是不同的,比如BASH_ARGC,BASH等,这些变量只有set才会显示,是bash特有的,export不加参数的时候,显示哪些变量被导出成了,因为一个shell自己的变量可以通过export “导出”变成一个用户变量。
前面学过Shell是一个弱类型的语言,默认情况下给变量赋什么值都是字符串型,不能直接进行数值运算。declare命令可以明确进行变量类型的声明。
env查见变量查询
env | egrep -i "user|mail|pwd|loginname| histsize"
service命令的源代码中用到了env命令
可以看出service在执行别的命令式,只有三个环境变量:LANG, PATH, TERM。
[root@www.linuxidc.com ~]# grep env /sbin/service
env -i LANG="$LANG" PATH="$PATH" TERM="$TERM" "${SERVICEDIR}/${SERVICE}" status
env -i LANG="$LANG" PATH="$PATH" TERM="$TERM" "${SERVICEDIR}/${SERVICE}" stop
env -i LANG="$LANG" PATH="$PATH" TERM="$TERM" "${SERVICEDIR}/${SERVICE}" start
env -i LANG="$LANG" PATH="$PATH" TERM="$TERM" "${SERVICEDIR}/${SERVICE}" ${OPTIONS}
[root@www.linuxidc.com ~]#
declare改变变量的类型:
[lily@JUMPERBOX-OFFICE-02 ~]$ aa=11
[lily@JUMPERBOX-OFFICE-02 ~]$ bb=22
[lily@JUMPERBOX-OFFICE-02 ~]$ cc=$aa+$bb
[lily@JUMPERBOX-OFFICE-02 ~]$ echo $cc
11+22
[lily@JUMPERBOX-OFFICE-02 ~]$ declare -i cc=$aa+$bb
[lily@JUMPERBOX-OFFICE-02 ~]$ echo $cc
33
[lily@JUMPERBOX-OFFICE-02 ~]$
查看变量属性
[lily@JUMPERBOX-OFFICE-02 ~]$ declare -p cc
declare -i cc="33"
环境变量修改总结:
- /etc/profile (建议不修改这个文件 ) 全局(公有)配置,不管是哪个用户,登录时都会读取该文件。
- /etc/bashrc (一般在这个文件中添加系统级环境变量) 全局(公有)配置,bash shell执行时,不管是何种方式,都会读取此文件。可以设置系统提示符 PS1等。比如 PS1=\h:\W \u$,那么提示符的格式就是:主机:当前目录 用户名$
- ~/.bash_profile 或者 ~/.profile (一般在这个文件中添加用户级环境变量) 每个用户都可使用该文件输入专用于自己使用的shell信息,当用户登录时,该文件仅仅执行一次!
[lily@JUMPERBOX-OFFICE-02 ~]$ set | wc -l
57
[lily@JUMPERBOX-OFFICE-02 ~]$ env | wc -l
20
[lily@JUMPERBOX-OFFICE-02 ~]$ export | wc -l
19
[lily@JUMPERBOX-OFFICE-02 ~]$
用env检测bash漏洞:
[lily@JUMPERBOX-OFFICE-02 ~]$ env x='() { :;}; echo vulnerable' bash -c "echo this is a test"
vulnerable
this is a test
[lily@JUMPERBOX-OFFICE-02 ~]$ cat /etc/redhat-release
CentOS release 6.3 (Final)
[lily@JUMPERBOX-OFFICE-02 ~]$ bash --version
GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
[lily@JUMPERBOX-OFFICE-02 ~]$
升级修复,修复后看下版本,并且用env再次验证下
yum -y update bash
我们先来看 env x='() { :;}; echo vulnerable' 命令大家一般都了解(不了解的跟随传送门去看)。env为接下来的执行命令提供环境变量,拿测试代码解释来说就是:
bash -c "echo this is a test"在执行的时候存在一个环境变量x,而x呢等于 () { :;}; echo vulnerable ,我们都知道环境变量在使用前都会被初始化,那么 () { :;}; echo vulnerable 就自然而然的被执行了。() { :;};定义了一个函数(function)并且它什么也不做,而后的echo vulnerable被解析后得到了执行权。那么echo vulnerable换成其他更具破坏性的代码后果就不堪设想了。(没错,env还支持function作为环境变量,不信执行:env FUNC='() { echo OK;};' bash -c "FUNC")
#注:如果想以env xxx='zzz' bash -c 'yyy'这种形式的渗入式攻击,zzz就必须写成这样: () { :;}; BAD-CODE-HERE
博客参考地址:
bash漏洞原理
目录结构,内置变量
declare申明不同的变量类型
declare申明不同的变量类型
declare命令参数详解
linux bash
变量的键盘读取、数组与声明: read, array, declare type别名