Bash脚本参数校验无法拦截&、()字符引发命令注入问题
Bash脚本参数校验&字符提前解析失效问题修复
核心问题原因
你遇到的&、(、)字符无法拦截的问题,本质不是脚本内校验规则写错了,而是这些特殊字符在传入脚本之前,就已经被当前使用的交互Shell解析拆分了:
- 当你直接在终端输入
bash test.sh pra& whoami时,Bash会默认把&识别为命令分隔符,含义是把前半段命令放到后台执行。实际执行逻辑是:后台运行bash test.sh pra(此时脚本拿到的$1只有pra,长度3,所以触发长度过短报错),同时前台单独运行whoami命令。 - 带&的完整字符串根本没有作为参数传入你的脚本,脚本内部的校验逻辑自然不可能拦截到根本没收到的字符。
- 你原本用的黑名单匹配特殊字符的思路本身存在漏判风险,没有覆盖&、()只是次要问题,就算补全了黑名单,也解决不了字符提前被解析的问题。
正确实现代码
校验规则不要用黑名单枚举特殊字符,直接用白名单正则,仅允许符合要求的小写字母通过,从根源避免漏判,修复后的完整脚本如下:
#!/bin/bash initials=$1 initials_buffer(){ if [[ ${#initials} -ge 5 ]] ; then echo "Error: Bad initials. Too long!!!" exit 1 elif [[ ${#initials} -le 3 ]] ; then echo "Error: Bad initials. Too short!!!" exit 1 # 白名单正则:仅允许全小写a-z字符,不符合就直接拦截 elif [[ ! $initials =~ ^[a-z]+$ ]] ; then echo "Hey!! No special chars, only lowercase letters in a-z range are allowed" exit 1 else echo "properly string" fi } initials_buffer exit 0
传参规范说明
如果参数本身包含&、空格、括号、*这类Shell元字符,必须在调用脚本时对参数加引号或者转义,这是Bash的基础语法规则,没有任何脚本内的写法可以绕过这个解析逻辑:
- 给参数包裹单引号,引号内的所有特殊字符都会被原样传入脚本,不会被提前解析:
bash test.sh 'pra&whoami' - 也可以用反斜杠对单个特殊字符转义:
bash test.sh pra\&whoami,效果和单引号包裹一致
测试验证
按照规范传参后,校验逻辑可以正常拦截所有非法输入:
# 传入带&的参数(加单引号) ┌──(root💀kali)-[/] └─# bash test.sh 'pra&whoami' Hey!! No special chars, only lowercase letters in a-z range are allowed # 传入4位符合规则的小写字母 ┌──(root💀kali)-[/] └─# bash test.sh pran properly string # 传入带括号的参数 ┌──(root💀kali)-[/] └─# bash test.sh 'pra()' Hey!! No special chars, only lowercase letters in a-z range are allowed
提示:未加引号/转义的元字符解析是Shell层面的行为,发生在脚本启动之前,脚本本身无法获取到被解析拆分掉的命令内容,这类风险只能通过规范传参+白名单校验共同规避。
内容的提问来源于stack exchange,提问作者przem.exe
相关产品推荐
相关产品推荐

