产品安全设计十大原则
原则1:最小化攻击面:
系统每增加一个功能特性就有可能会引入新的风险,通过安全开发可以减少攻击面进而达到控制系统整体风险的目的。
打个比方说,某在线web应用向用户提供了一个通过搜索来获取帮助的功能,如果后端代码没有正确实现该功能就有可能导致存在SQL注入漏洞,但是即便如此,我们还是有办法降低或消除风险的,比如:
u 该帮助功能只能被授权的用户使用。
u 后端代码对用户输入的数据进行了校验。
u 帮助功能不支持搜索,只支持查看。
可以看到,以上的第一、二点收缩了攻击面,即增加了攻击条件,减少了可以攻击的人数,而第三点则完全避免了风险,即攻击面完全消除了。其中第三点符合“简化系统设计”的原则,即不增加不必要的功能模块和特性。
另外一个典型的例子是:统一登录认证,所有业务都在认证中心登录,避免反复登录,这样的可以防止同样的安全问题在不同的业务上发生,相当于将攻击从面收缩到一个点上,我们只要把这个点做得足够安全即可。
原则2:Secure default:
在软件领域的含义就是:让默认的配置和策略尽可能的安全。比如,在许多场合,安全和产品体验经常会发生冲突,这时候应当选择安全优先,在安全的前提下,可以允许通过手动关闭安全配置或策略来提升产品体验。
比如,产品应该默认打开密码复杂度策略,即不允许用户使用不符合密码复杂度策略的密码,但产品可能可以允许用户关闭这个策略来提升体验。
注:只有充分了解业务安全需求的前提下,才能更好的使用该原则。
原则3:权限最小化:
事物只拥有可以完成他们任务的最小权限,即不赋予不必要的权限。包括但不限于:用户权限和资源权限(比如可以使用的CPU、内存、网络流量和存储容量等等)。
比如,某中间件服务器只需要访问网络、读取数据库和向日志服务器写日志的权限,那就完全没有必要赋予其更多其它的权限(特别是管理级别的特权)。
再比如,在以下PHP样例中,该业务只需要查询的权限,但却使用了root账户进行连接,如果该业务遭受SQL注入攻击,就会造成很大的影响。
<?php
$host = 'localhost';
$userID = 'root';
$password = 'password';
$db = mysql_connect($host, $userID, $password) or die ('Error connecting to mysql');
$name = 'testdatabase';
mysql_select_db($name);
$sql="SELECT * FROM theTable";
$result=mysql_query($sql);
?>
原则4:纵深防御:
从不同的维度去实施安全保护措施来缓解被攻击的风险。实施纵深防御策略,可以让攻击变得更加难以实施,漏洞变得更加难以利用。
比如,为了防止或减少SQL注入带来的危害,我们可以:
u 在应用外围部署WAF。
u 应用对输入数据进行有效性验证或进行参数化查询。
u 数据库连接账户隔离以及权限最小化。
u 敏感数据加密存储。
u 对数据库进行安全配置或关闭不必要的强大功能。
但是,该原则和原则9—“简化系统设计”在一定程度上是相违背的,即当纵深防御机制设计得过于复杂时,同时也增加了系统的复杂性,导致为了解决某些安全问题而引入了其它的安全问题。比如:设计登录认证时,要求用户必须设置过于复杂的口令,由于用户无法难以记住,可能会将其写在纸条贴在桌面上。
因此,本原则也必须结合业务和实际情况进行分析,综合平衡两者矛盾。原则5:Fail securely:
即业务系统能够正确安全地处理各种异常和错误。错误样例代码如下:
isAdmin = true;
try {
codeWhichMayFail();
isAdmin = isUserInRole( “Administrator” );
}
catch (Exception ex) {
log.write(ex.toString());
}
当异常发生时,异常处理代码处理不当,可以导致普通用户直接提升为管理员用户。
原则6:不要信任第三方系统
不少产品需要和第三方的业务系统对接,并使用其提供的数据,但是一般情况下,我们是无法掌控这些第三方系统的安全设计和开发过程的,所以它们也可能会存在安全漏洞,进而被人攻击,因此,我们必须充分考虑到当第三方系统被攻击时,如何保障自己的业务系统的安全性。
比如:当我们向第三方系统查询数据时,必须对数据进行有效性验证后才可以使用(比如使用这些数据进行数据库查询或显示到用户浏览器上)。
原则7:业务隔离:
基本思想是将业务系统尽分成尽可能多的独立单元,但某个单元出现安全缺陷时,可以将损害程度降到最低,通俗地说,就是不要把所有鸡蛋都放在一个篮子里。
比如:将具有核心数据的业务和BBS部署在同一个服务器上,很多BBS站点都使用开源系统(比如 discuz)搭建,经常爆出各种漏洞,一旦BBS被攻陷,将会威胁到核心业务数据的安全性。
注:隔离可以是系统内部功能模块之间的(比如:web服务器和数据库服务器等),也可以业务部署层面之间的(比如:BBS和核心业务)。
原则8:公开设计:
有些人认为,只要产品内部的实现细节不被外人知道,那么产品就是安全的,但其实这是一种保护效果比较差的方法。当然,并不是说这样做毫无意义,也的确增加了攻击的难度,但是不能对其形成过多依赖,甚至把它当成主要或唯一的安全防护手段。
比如:不少公司都实现了自己的私有加密算法,他们认为只要算法不被泄露或公开,那么算法就是安全的,但实际面临以下问题:
u 攻击者可以通过抓包或逆向二进制来进行破解。
u 攻击者通过入侵服务器或给员工机器种植木马的方式来获取到源代码。
u 对公司不满的员工故意公开算法。
一旦以上任意条件满足时,则这种不公开设计方式的保护也就变得没有意义,因此,正确地做法应该是:假设算法被破解或完全公开,同样能保证系统的安全。典型的案例诸如业界广泛使用的对称加密算法(AES)和非对称加密算法(RSA),它们的设计实现都是公开的,但是仍然是安全的。
原则9:简化系统设计
“最小化攻击面”和“简化系统设计”原则是相辅相成的,由于复杂的系统设计会导致攻击面变宽,所以如果存在多种系统设计方案,则应尽量选择最简单的那种方案。
原则10:使用白名单:
白名单的思想为:除了定义为合法的,其它都拒绝。与之相反的黑名单思想为:除了定义为不合法的,其它都允许。使用白名单的好处是它有可能能够防御各种未发现的安全隐患,而这是黑名单所做不到的。
比如:对所有输入数据进行过滤时,适合使用白名单原则,未在白名单范围内的数据将被视为非法,相反地,如果使用黑名单,其规则可能会被预想不到的方法绕过。