编程中如何安全执行shell命令?system与exec函数安全差异咨询
system与exec系列函数的核心安全差异
二者的核心风险差异来自是否触发shell解析逻辑:
system()函数执行时会默认调用shell程序解析传入的命令字符串,这是它最大的风险来源:如果传入的命令包含用户可控的内容,攻击者注入的;、&、$()等shell元字符会被直接解析执行,造成任意命令注入漏洞。同时system()会继承程序运行的环境变量,攻击者可以篡改PATH等环境变量,诱导特权程序执行恶意的可执行文件。- 正确使用exec系列函数时,不会触发shell解析逻辑,而是直接加载指定路径的可执行文件运行,传入的所有参数都会直接作为目标程序的启动参数,不会被当成命令片段解析,就算参数中包含shell元字符也只会被当作普通文本处理,从根源上避免了命令注入的风险。同时如果使用指定绝对路径的exec接口(如
execve、execl),不需要依赖PATH环境变量查找可执行文件,也不会被环境变量篡改的问题影响。
注意:exec系列中的
execlp、execvp仍然会依赖PATH查找可执行文件,所以特权程序中也要避免使用这两个接口。
exec系列不是绝对安全的银弹,它只是消除了system()自带的两个核心风险点,如果传参不规范、执行的外部程序本身存在漏洞,仍然可能出现安全问题。
安全执行系统命令的最佳实践
- 优先使用系统原生API、编程语言自带的库实现需求,能不调用外部命令就尽量不调用,从根源消除风险
- 必须调用外部命令的场景,严禁使用
system()、popen()等会触发shell解析的接口,一律使用exec系列(排除execlp、execvp) - 调用的可执行文件必须写死绝对路径,禁止使用相对路径,禁止由用户输入提供可执行文件路径
- 所有传入外部程序的参数必须做严格的白名单校验,仅允许符合规则的内容传入,特殊字符、危险参数一律拦截
- 所有参数必须以独立的argv项形式传入exec接口,严禁将用户可控内容和固定参数拼接成字符串传入
- 特权程序调用外部命令前,尽量先降低运行权限,执行完成后立刻回收权限,减少漏洞被利用后的影响范围
内容的提问来源于stack exchange,提问作者Wahalez
相关产品推荐
相关产品推荐

