问题的背景:参数注入

在shell中,我们希望将参数传递给子命令,如下面的例子:
假设我们有一个http服务,它接受一个cmd参数,并将其传递给bash -c执行:

// curl 'localhost:8080/demo?cmd=echo hello'
handler(req,res){const cmd = req.query.cmd;const process = child_process.exec(`bash -c "${cmd}"`);// ...
}

显然,因为cmd将被拼接在字符串中,所以上面的处理方式有很明显的问题:如果cmd中含有双引号,或者其他特殊字符,甚至cmd=':";rm -rf /, 那么执行的命令就变成了bash -c ":";rm -rf /,是极其危险的。

其实,这在编程领域是非常常见的注入问题,和SQL注入是同样的道理:参数将被拼接到命令中执行,因此不能信任参数。

解决方法

解决方法就是对要拼接的参数进行转义,防止其中的任何特殊字符造成期望之外的结果。
比如,bash -c "${cmd}"的含义是: cmd将作为一个完整的字符串被双引号包围。所以,需要对cmd进行转义:

function quoteShell(cmd){return cmd.replaceAll("\\", "\\\\").replaceAll("$", "\\$").replaceAll("`", "\\`").replaceAll("\"", "\\\"").replaceAll("\n", "\\n")
}

上面的例子一种常见的情况,即参数只会被命令行解析一次,因此需要保证命令行解析的结果就是原始的参数字符串。所以,本质上quote函数可以视为bash解析参数的逆过程。

还有另外一种情况,参数通过printf进行传递:

printf "${cmd}" | bash

在这种情况下,参数不仅要被bash解析,还要被printf解析,如何保证经过这两个解析过程之后,得到原始的参数字符串?

我们分析解析的过程:首先是bash解析,然后printf解析bash解析的参数,即实际参数 -> bash -> printf -> 原始参数,所以,我们将这条链反转过来就是如何从原始参数到实际参数的过程: 原始参数->printf->bash->实际参数。因此,我们需要定义quotePrintf:

function quotePrintf(cmd){cmd = cmd.replaceAll("\\","\\\\").replaceAll("%","%%")return quoteShell(cmd)
}
  1. 先将printf中的特殊字符\和%转义
  2. 再将转义后的字符串进行quoteShell

注意:对printf来说,"不是特殊字符,那只是bash的特殊字符。

例子:

quoteShell:'\n' -> '\\n'$A   -> "\$A""\n  -> \"\\n"quotePrintf:'\n' ->  '\\\\n'$A   ->  \$A"\n  -> \"\\\\n%s  -> %%s

关于bash quote的认识相关推荐

  1. linux命令帮助 man bash

    BASH(1) BASH(1)NAMEbash - GNU Bourne-Again SHell (GNU 命令解释程序 "Bourne二世")概述(SYNOPSIS)bash [ ...

  2. shell变量加单引号sql_关于shell:在Bash中的命令中扩展变量的单引号

    我想从bash shell脚本中运行一个命令,该脚本在单引号和变量中包含单引号和一些其他命令. 如repo forall -c '....$variable'. 在这种格式中,对$进行转义,不展开变量 ...

  3. Bash For Loop Examples for Your Linux Shell Scripting--ref

    There are two types of bash for loops available. One using the "in" keyword with list of v ...

  4. Bash 中的特殊字符大全

    Linux下无论如何都是要用到shell命令的,在Shell的实际使用中,有编程经验的很容易上手,但稍微有难度的是shell里面的那些个符号,各种特殊的符号在我们编写Shell脚本的时候如果能够用的好 ...

  5. Bash+R: howto pass parameters from bash script to R(转)

    From original post @ http://analyticsblog.mecglobal.it/analytics-tools/bashr/ In the world of data a ...

  6. gitlab bash_如何编写Bash一线式以克隆和管理GitHub和GitLab存储库

    gitlab bash Few things are more satisfying to me than one elegant line of Bash that automates hours ...

  7. Bash字符串处理(与Java对照) - 18.格式化字符串

    From: http://codingstandards.iteye.com/blog/1198098 In Java class Formatter 参见:http://download.oracl ...

  8. Bash中单引号和双引号之间的区别

    本文翻译自:Difference between single and double quotes in Bash 在bash,什么是单引号(之间的差异'' )和双引号( "" ) ...

  9. 认识 BASH Shell

    认识 BASH Shell 切换解析度为 800x600 最近更新日期:2005/08/30 文字模式 (command line) 这种指令下达的方式,在 Linux 里面,其实就相当于是 bash ...

最新文章

  1. 动态规划算法-01爬楼梯问题
  2. js优化工具:ECMAScript Cruncher
  3. 利用wojilu框架仿一个网站的全过程(Step by Step利用wojilu框架开发网站系列二 附源码)...
  4. Linux shell 脚本入门教程+实例
  5. error code ELIFECYCLE
  6. 阿里P8架构师分享:如何从0到1设计一个类Dubbo的RPC框架
  7. 第十章第二节 阿基米德原理
  8. 强网杯2019线上赛-misc
  9. java项目 分模块管理_java 工程项目模块划分及各模块功能梳理
  10. WPS Linux 2019领先的背后
  11. 20210525电力通信网
  12. 腾讯不缺少梦想,但是缺算法与数据管理
  13. Netlogo仿真初步学习总结
  14. 单身职场人士怎么利用晚上时间提高自己?
  15. 记一次触发器定义者不同导致的sql异常TRIGGER command denied to user 'XXX' @'%' for table '...
  16. 学UI设计需要会手绘吗
  17. 同是数据分析产品, 为什么200万App企业都选择友盟+
  18. 51nod-2534 最小旅行路线
  19. 【Linux开发环境搭建】之Nginx安装
  20. Xilinx FPGA 配置之ICAP

热门文章

  1. linux cs go鼠标灵敏度,CSGO鼠标调试方法 选择适合自己的鼠标速度
  2. 记一次打包源码的过程
  3. 说说Android桌面(Launcher应用)背后的故事(八)——让桌面的精灵穿越起来
  4. 【附源码】计算机毕业设计SSM社区居家养老服务管理系统
  5. python keys模块_python自动化常用模块
  6. datadashboard下载_Data Dashboard for LabVIEW
  7. Android闪动的文字效果
  8. 解决Chrome浏览器想要弹出警告框时会卡死的问题
  9. apachebench_使用ApacheBench对PHP应用进行压力测试
  10. MAC系统安装Wireshark网络抓包工具