shell语言编程规范安全篇是针对bash语言编程中的数据校验、加密与解密、脚本执行、目录&文件操作等方面,描述可能导致安全漏洞或风险的常见编码错误。该规范基于业界最佳实践,并总结了公司内部的编程实践。该规范旨在减少SQL注入、敏感信息泄露、环境变量攻击、临时文件攻击、社会工程学等方面的安全问题发生。
使用对象
本规范的读者及使用对象主要为使用bash脚本的研发人员和测试人员等
适用范围
该规范适用于基于bash脚本的产品开发
术语定义
规则:编程时必须遵守的约定
建议:编程时加以考虑的约定
说明:某个规则的具体解释
错误示例:对此规则/建议从反面给出例子
推荐做法:对此规则/建议从正面给出例子或建议
例外情况:相应规则不使用的场景
信任边界:位于信任边界之内的所有组件都是被系统本身直接控制的,所有来自不受控的外部系统的连接与数据,包括客户端与第三方系统,都应该被认为是不可信的,要先在边界处对其校验,才能允许进一步与本系统交互。
非信任代码:非产品包中的代码,如通过网络下载到本地虚拟机中加载并执行的代码。
通用原则
规则1:校验跨信任边界传递的不可信数据
说明:软件最为普遍的缺陷就是没有对来自外部环境(系统/程序信任域之外)的数据进行合法性校验,校验缺失可导致系统的各种缺陷,比如DOS、SQL注入等,所以对于来自外部环境的输入,默认为不可信,需要执行合法性校验,校验必须在信任边界以内进行(比如对于web应用,需要服务端做校验)。不可信数据可能来自(包括但不局限与):用户输入、外部接口输入、配置文件、网络数据、环境变量。
数据校验可以参考如下几种策略(包括但不限于):
1).接受已知好的数据:该策略被称为白名单或者正向校验,重点检查数据是否属于一个可接受的数据集合。如下代码用于确保name参数只包含字母、数字以及下划线且必须以字母开头:
check
2).拒绝已知坏的数据:该策略被称为黑名单或者负向校验,相对于正向校验,是一种较弱的校验方式,这种策略存在缺陷,因为潜在的坏数据可能是一个无限集合,采用这种策略意味着必须维护一个系统不可接受的列表(如字符或模式),否则列表中的信息会很快过时,系统安全性会降低。
3).白名单方式净化:删除、编码或者替换系统不能接受的字符/数据,就是系统只接受某个确定的数据列表,比如期望接收一个电话号码,则可以剔除输入数据中所有非数字字符。
4).黑名单方式净化:为确保输入数据安全,剔除某些字符或转换某些字符,跟黑名单校验类似,该策略需要持续维护,且黑名单通常也不全面,因为大部分输入域有其特殊的业务或格式要求,对比对应于当前和未来所有攻击方式而使用的一个复杂、迟钝的校验程序,针对正确输入的正向校验显得更为简单、高效。
错误示例1:环境变量容易被篡改,如果脚本中使用系统环境变量,建议优先使用系统命令取值,如下代码中,直接使用环境变量USER判断当前用户是否为root用户,如果该环境变量USER被人篡改,会得到非预期的结果。
check
推荐做法:使用id -un命令可以准确安全地判断当前用户,如下:
check
规则2 禁止直接使用不可信数据来拼接SQL语句
说明:SQL注入是指原始SQL操作被动态更改成一个与程序预期完全不同的操作,执行更改后SQL可能导致信息泄露或者数据被篡改。防止SQL注入主要需对不可信数据进行校验,推荐对不可信数据做如下校验以防SQL注入:
对于字符型字段,需要对数据做转义
1).将单引号替换为两个单引号
2).如果字符类型输入数据作为SQL语句中like部分,需要参考后面的附录A做转义。
3).系统根据具体业务场景,确定需要校验的特殊字符,特殊字符可以参考附录A和附录B
对于整型字段,需要对输入数据进行类型校验,拒绝传入不合法数字。
错误示例1:该例子中直接使用输入数据拼接SQL语句,没有对输入数据做校验,存在SQL注入风险。当username输入值为tom'OR '1' = '1'的时候,SQL语句变成了"SELECT * FROM db_user WHERE username = 'tom OR '1' = '1' AND password = '${pvalue}'" ,这样就绕开了对口令的验证。
get
推荐做法:
get
规则3 禁止在界面或日志中输出敏感信息
说明:敏感数据的范围应该基于系统场景以及威胁分析的结果来确定,典型的铭感数据包括口令、银行账号、个人信息、通讯记录、秘钥等,如果shell脚本中往界面或日志中输出敏感信息,都可能会有助于攻击者尝试发起进一步的攻击,因此shell脚本中禁止往界面或日志中输出敏感信息,避免被攻击者所获取并利用。敏感信息举例(包括但不限于):
1).口令与秘钥:口令包括口令明文和口令密文。
2).环境变量:命令set、env、declear、export以及typeset会把操作系统的环境变量显示出来,其中可能会存在关键信息。
3).产品相关信息:产品License、日志中如password、passwd等关键字信息。
对敏感信息建议采取以下措施:
1).不输出到界面或日志中
2).若特殊原因必须要输出到界面或日志,则使用*号代替,并且不显示敏感信息的长度。
错误示例1:该例子中,功能实现时为方便定位问题,在日志和界面上输出了详细信息,其中包括了数据库密码,存在被利用的风险。
db
推荐做法:不将敏感信息输出到界面以及日志中,避免被利用。
db
错误示例2:如下示例中,如果环境变量plvaule为关键信息,如下
env
而脚本如下,会将环境变量输出至日志及界面,存在信息泄露风险。
env
推荐做法:禁止在shell脚本中把set、env、declare、export及typeset命令的回显打印到日志及界面上。
例外情况:可以将命令执行结果赋值给一个变量,但需要保证该变量不输出到日志和界面,如下所示:
env
规则4 禁止在shell脚本中保留敏感信息
说明:敏感数据的范围应该基于应用场景以及产品威胁分析的结果来确定,shell脚本在产品发布版本中以文本方式存在,如果脚本中包含敏感信息,可能会被恶意利用造成安全隐患,比如脚本中注释中包含员工的个人信息,虽然不违反安全红线,但是带有员工个人信息的注释可能会泄露具体的开发人员信息,从而引入社会工程学方面的风险,因此要从脚本注释中删除员工个人信息。
脚本中敏感信息包括(但不限于):
1).用户名、密钥、密码明文和密文:如果脚本中存在这类信息,一旦泄露,与其相关的数据的机密性将受到严重的影响,因此不能在脚本中体现出来。
2).公司内部信息:如代码作者的工号、姓名、联系方式等
错误示例1:如下代码中,硬编码了默认的用户名和密码,在执行时会导致用户名和密码这类敏感信息很容易泄露出来。
input
推荐做法:shell脚本里面禁止硬编码密码等敏感信息,需要密码时通过手工输入,如下:
input
例外情况:在系统初始化安装的shell脚本中可以使用默认的用户名和密码密文,但是需要在调测及管理员操作指南中提醒用户及时修改缺省密码。
错误示例2:该例子中,发布版本中的shell脚本中包含了公司内部信息,可能导致社会工程学方面的风险。
info
推荐做法:把脚本中的开发人员个人信息清除掉。
规则5 禁止在PATH环境变量中使用相对路径
说明:环境变量攻击是用来操控脚本行为的最常见的方式,通过修改环境变量攻击者可以改变一个依赖环境变量值的脚本的执行过程或执行结果。其中最常被修改的环境变量是PATH,该变量值的路径集决定了用户在执行不包含完整路径的单独命令时,查找该命令的路径及路径查找先后顺序。
假设PATH变量的内容是:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin,
正常情况下命令会顺序在/usr/local/sbin、/usr/local/bin、/usr/sbin、/usr/bin中查找并执行,如果PATH环境变量内容设置不当,存在如"."这样的相对路径,攻击者可以在当前目录下创建与系统命令同名的恶意程序或者脚本,当用户执行该命令是,就会触发执行恶意程序,导致恶意攻击。
防护措施:PATH环境变量中必须使用绝对路径,或者直接使用绝对路径命令进行操作。
May you share freely, never taking more than you give.
愿你宽心与人分享,所取不多于你所施与。
转自
https://www.toutiao.com/i6498345706607084046/