bash中常见环境变量env、set、export 、declare与bash漏洞原理

今天被同事问到env与set的区别,感觉很久不看忘了,所以简单的记一笔,方便后续查阅

初识env

env命令可以显示当前用户的环境变量,还可以用来在指定环境变量下执行其他命令

env查看有哪些环境变量,并且可以用$ 变量读取env中的变量名对应的变量值

setenvexport、以及declare命令的异同:

set命令显示当前shell的变量,包括当前用户的变量

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"

环境变量修改总结:

  1. /etc/profile (建议不修改这个文件 )
    全局(公有)配置,不管是哪个用户,登录时都会读取该文件。
  2. /etc/bashrc (一般在这个文件中添加系统级环境变量)
    全局(公有)配置,bash shell执行时,不管是何种方式,都会读取此文件。可以设置系统提示符 PS1等。比如 PS1=h:W u$,那么提示符的格式就是:主机:当前目录 用户名$
  3. ~/.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命令大家一般都了解(不了解的跟随传送门去看)。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

博客参考地址:

https://www.cnblogs.com/lichmama/p/3993136.html bash漏洞原理

https://www.cnblogs.com/wfwenchao/p/6139039.html 目录结构,内置变量

https://blog.csdn.net/tstbdt/article/details/45369959 declare申明不同的变量类型

https://blog.csdn.net/shu15121856/article/details/77823978 declare申明不同的变量类型

https://blog.csdn.net/qq_28391549/article/details/79204744 declare命令参数详解

https://www.cnblogs.com/wy2185/p/5127023.html linux bash

变量的键盘读取、数组与声明: read, array, declare type别名

原文地址:https://www.cnblogs.com/kissit/p/9928240.html