随着网络的发展, 特别是移动互联网的发展, 网络服务与我们个人生活联系得越来越紧密; 办理金融业务, 生活缴费, 获取资讯等等, 都从线下搬到了线上. 一个新的时代必将到来或者已经到来, 那就是万物互联的时代. 与此同时, 网络安全事件频发, 安全事故的危害越来越大, 互联网从业者需要越来越注重安全问题. 这里分享一些心得给刚刚接触网络安全的开发者们.
一,"安全" 是什么
对于没有接触过安全的开发人员来讲, 一个常见的问题是: 如何写出安全的代码或做出安全的系统. 为了找到答案, 我们就必须对安全的定义有所了解."安全" 是一个很宽泛的概念, 那这里给出一个很宽泛的定义: 被保护的对象不被破坏, 篡改, 泄漏, 系统功能可以正常运行. 是不是一头雾水?"安全" 定义的关键问题是, 什么是需要保护的对象, 保护的需求是什么; 没有明确的安全的需求, 我们就无法谈论安全. 比如常见的安全问题有, 通信协议是否安全, 数据存储是否安全等等; 此外还有运行环境是否安全, 代码是否安全. 所以当我们想要写安全的代码或者实现一个安全的系统之前, 我们可以先问问自己, 我想要保护的对象是什么. 不同的安全的需求, 需要做出的安全的防护方式也是不同的. 如果不知道你想要的是什么, 那么你就不会得到它.
明白了安全的定义, 下一个问题是: 如何知道实施的安全措施是否足够安全. 安全防御和安全攻击是一个动态博弈的过程, 就像抗生素和细菌一样, 防御和攻击的技术都在进行不断升级. 所以我们说没有绝对的安全, 安全问题是成本问题. 通常我们需要寻找的是如何以最低成本来满足我们安全需求的最佳实践.
二, 如何入门 "安全"
孙子云 "知彼知己, 百战不殆", 所以读几本黑客如何攻击和防御的书是一个不错的选择. 这些书的内容可能会涉及到一些计算机的基础知识, 所以这些知识也是不可少的, 否则只能做到知其然而不知其所以然. 由黑客攻击和防御的引子, 又会引出计算机系统, 网络, 计算机体系结构, 编译原理, 虚拟机等等一些基础的知识.
黑客如何攻击和防御是理论基础, 有了理论基础我们可以看看这个真实的世界存在哪些比较流行的安全问题; CWE 是通用缺陷, 里面列举了很多通用的安全缺陷, 我们可以先从最流行的 25 个问题看起, 可以帮助我们在编码的时候避免许多安全问题. 如果开发的系统是 web 系统, 那么 OWASP 是不容错过的一个资料库; OWASP 包含 Web 常见的问题和最佳实践, 可以了解一下 OWASP 最流行的 10 个问题. 比如 SQL 注入, 这种常见的高发的已经有了几十年历史的问题, 在这两个榜单中都有提及.
接下来我们可以看看业界比较好的安全实践. SEI CERT Coding Standards 是一个安全编码标准, 分门别类得列出了 C,Java 等语言常见的安全问题, 并且对安全问题做出解释, 给我们提供了不安全的代码样例和安全的代码样例. 这个规范是一个很好的切入点, 帮助我们快速了解安全问题, 实践安全编码.
三, 对 "安全" 问题的宏观分类
安全问题五花八门, 令人眼花缭乱, 那么这些安全问题是否有共性呢? 答案是有的. 我们尝试将安全问题分入以下几个宏观类别之中.
1. 不受信的输入, 输出
壁立千仞, 无欲则刚; 如果一个系统没有与不受信的环境进行的交互, 那么这个系统的安全问题是比较小的. 大多数系统, 特别是 Web 系统, 需要和不受信的环境进行交互; 在交互过程中, 我们需要特别注意的问题有两点: 输入是否合法, 输出数据是否包含敏感信息.
输入数据包括并不限于用户输入的参数, 传入的文件, 读取的环境变量, 依赖的运行库等等. 如果用户输入的数据超出程序处理的范畴, 那么可能造成意想不到的结果. 对于这些不受信的数据, 我们通常可以限制输入范围, 只接受我们可以处理的输入, 比如网站注册时对密码的符号有一些限制, 就是这种解决方案; 我们还可以将输入的数据进行清洗, 去除不支持的内容.
对于输出数据我们需要关心输出的内容是否包含敏感信息, 比如程序路径, 用户名, 密码, IP 地址等等. 如果我们泄漏了服务器的用户名和密码, 那么服务器上的所有信息都有泄漏的风险. 这需要我们在程序发布之前, 仔细检查输出内容.
2. 程序本身有错误
如果程序本身有错误, 那么就会给攻击者可乘之机; 一旦程序触发到错误逻辑, 程序有可能偏离正常的运行流程, 比如运行了攻击者提供的程序.
对于 C 语言来讲, 常见的程序错误有空指针引用, 内存没有释放, 多次释放内存, 数组引用越界, 返回栈上地址, 整数溢出等等. 这需要代码编写者提高代码编写质量, 尽量减少程序错误.
对于 Java 语言来讲, 不存在 C 语言中的内存管理类似的问题, 但一样存在整数溢出, 数组引用越界, 引用空对象等问题, 此外, Java 语言还存在错误调用运行时库函数, 类型定义错误, 序列化和反序列化错误等等 Java 语言特有的问题.
3. 其它错误问题
我们将其它安全问题归入单独分类, 这些安全问题包括并不限于以下几点:
业务设计错误: 如没有经过认证就读取用户信息
通信协议不安全: 如使用了不安全的加密, 散列算法
调用的库不安全: 如 Web Server 存在安全漏洞
......
四, 一些安全实践的建议
安全问题不是纸上谈兵, 而是真刀 ** 实践出来的, 只有在实践中才能出真知, 安全性才能得到提升, 这里给大家一些小的建议.
第一个建议是重视安全问题, 针对安全问题进行设计和实现, 并且针对安全问题进行测试. 西方哲人讲 "解决问题的第一步是承认问题", 老子讲 "知不知", 都是此意.
第二个建议是发现和利用工具帮助解决安问题. 业界已经存在许多工具可以在各个阶段帮助我们检测安全问题.
语法检测工具, 避免一些低级错误;
静态检测工具, 在开发过程中, 对程序进行静态检测, 可以检测程序安全问题, 可以分析库文件是否存在漏洞, 这是解决安全问题十分有效的手段; 老牌的静态检测工具有 OCLint,Fortify,Coverity,Checkmarx 等, 一些新秀也在冉冉升起, 例如鉴释的 XcalScan;
动态检测工具, 将程序运行起来检测安全问题; 比如可以用 Valgrind,Panda 等工具;
自动化渗透工具, 可以模拟渗透行为, 对系统进行渗透以发现安全问题; 比如有 Zed Attack Proxy,W3AF,Wapiti 等等工具.
安全问题不是某一个单点问题, 它是系统问题, 这里没有银弹, 没有包治百病的特效药. 我们能做的是, 在安全问题发生以前, 充分了解, 模拟, 预警问题, 并作出有效的防范. 我们做的防护越多, 攻击者的攻击面就越窄, 攻击成本就越高, 我们的系统发生安全问题的概率就越低. 千里之行, 始于足下; 现在就开始了解, 重视安全问题, 正当其时.
来源: http://www.tuicool.com/articles/QbMVR3I