相较前两章,这一章的内容就相对温和许多了。服务的架构一定会有漏洞,这都是大家心知肚明的事。
反而没什么好吃惊的。
这一部分我会拆成几个章节写。这一章主要是在讲「暴露在外的部分」
关于网站的部分,最常见的攻击有几种:
- XSS 攻击:盗取用户 cookie
- SQL Injection:存取数据库,捞取资料,窜改数据
- Directory Traversal Attack:摸清机器档案目录,甚至获取机器权限 等等....
诸如此类的攻击手法,我在这本书里面就不讲得太详细了。
关于此类的内容,在 OWASP 里面有非常非常多的内容。如果你对于这些常见扫描攻击陌生,建议去读读 OWASP 出的一些指南。
http://www.owasp.org.cn/owasp-project/secure-coding
这本书我想讲的是解法、防御。
这些基础漏洞,主要出自于语言、框架,或者是低阶程序员的疏失。有几个方向你可以进行。
- 安装代码扫描工具
我自己擅长的是 Rails 框架上的项目开发,Rails 的开发观念以及第三方生态相对于完善。框架自带 XSS 防御、 SQL Injection 防御、XSRF 防御。如果硬要在里面写出不安全的代码,得程序员硬干 override 才能办到。
至于 Rails 界有一套服务叫 codeclimate,除了扫描代码质量,也可以扫描可能可能出现漏洞的代码。
另外,也有一套服务叫 sqreen,这套服务能充当 WAF,自动阻拦可疑扫描,并且追踪所有 rubygems 的更新与 security patch,当架构上的第三方库太老旧或是有安全疑虑,系统会自动通知开发者需要更新。
- 雇用白帽黑客、 资安谘询公司
安装代码扫描工具,可以很大程度防御与过滤一般的「机械式攻击」。
但「机械式」攻击,不是一般互联网服务最大的威胁。而是黑客的「手工攻击」。
机器是死的,人是活的。
如果你的服务非常重要,保卫著许多人的资产。我建议还是雇用正统资安谘询公司,人工灰盒审计(等于是请资安顾问对自己的公司实施各种攻击,找到所有可能性的攻击与脆弱点,出具报告修复)一次。而且这个灰盒审计得定期执行。
第二种状况,是针对「后台合法攻击」。
什么是针对后台合法攻击呢?我在这里揭露一个事实吧:
许多服务的架构都是这样设计的,后台只可能在两个地方:
- example.com/admin
- admin.example.com
命中率高达 99%。
而且呢,在外网就能够存取。
也就是如果你的其中一位客服或员工被猜到密码,这套服务马上就沦陷。而且因为是正常操作,不会触发任何警报。
首先,这个架构有几个地方需要改变。当然有时候你的财力物力不一定马上可以做到。但起码可以降低相当大的风险。
- 改名,换网域
绝对不能叫
- example.com/admin
- admin.example.com
你可以叫
example.cc/admin
或者
a.example.cc
至少不那么好猜,以及防御黑客盗到员工 cookie 就能打进来。
- 限制存取来源
这里有一个小细节,example.cc 不能是真实网域,得是一个你虚构的域名。唯有修改 /etc/hosts 才能正确的 mapping。
这样避免了被猜到域名,直接在公开网段上被存取得知的可能性。
再来,将该机器限制只能从特定 IP 连线,也就是员工必须要使用 VPN 或者是办公室才能连入。
当然最好的情况是将 admin 放在内网里面,当然如果短时间作不到,这也是一个暂时可以接受的 workaround。
- 读写分离
什么叫读写分离呢?也就是 admin 与 public service 是两套服务。public service 是给用户的服务,用户只能读以及有限的改写自己有权限改的资料(比如个人 profile 等等)
而 admin 的代码,是跑在另外一份机器上与另外一份架构上。这些「写」「变更」的部分是与用户接触的服务完全阻隔开来。
- Log 机制
因为资料变更写入通常会造成安全性。所以有几个机制需要加入设计:
- 网站只能做软删除,而不允许硬删除操作。
- 任何操作都要记录 Log,谁在什么时候,做了某事。并打到 slack 进行记录通知。做多重 Log 备份。
- 关键操作,需要三重确认,多人签名,放行机制审核。
大家的服务都是暴露在互联网上的。这里有一个危险但真实的思路。黑客极有可能直接打进 service,合法的用 web shell,操作数据库改数据。
这边我翻译成白话:以币所的情况就是骇客直接改数据库,改成自己馀额有100颗 BTC,然后合法提走。
如何防御这样的攻击呢?
- 建立历史变动记录
互联网实做点数与储值系统都是直接更改「最后馀额」。
而相对安全的架构是:将帐号馀额做版本控制,就是经过「合法操作」的加扣馀额都会被纪录。如果当下馀额,与帐号的历史版本不一致,那么这笔纪录就是「伪造的」。
而在进行任何馀额上的合法变动(如买卖,提领,兑换)等等的操作,都必须再次验证过去历史数据是否匹配,若为伪造,该个帐号会立刻被冻结。
- 数据验证
分个人与全站。
一个个人有无数笔的帐号版本,但对到最后,应与当下馀额一致。
全站资产,站上也就是比如站上的应有多少 BTC,经过变动以后应该还是应有相对应的 BTC。
每几个小时扫描一次。只要发现异常,立刻冻结与 slack 与简信发出警告。
- 建立行为白名单与黑名单
内部风控可以先自我列出什么是「不可能」的「状况」。直接写入风控系统。
比如说「注册一两天」的新帐号,立刻要提领超过 10 颗比特币。(洗钱或盗号嫌疑)
或者已经超过 60 天没有登入,突然间登入,登入后两分钟内马上要提空馀额。(盗号嫌疑)
真实状况不是不可能没有。只是看起来「可疑」。
而这一类的「可疑行为」。一律 delay 动作或冻结,进人工审核处理。
针对站上的用户,建立分级评分机制。按照风控分数自动锁定与放行。
有一些黑客,入侵服务器后,并不急著马上「下手」。
而是潜扶在机器里面,跑后门。「传资料」回去,这些资料包括但不限于「数据库密码」「使用者数据」「其他机器的 ip 清单」「管理员的密码」等等等等….
有几个方向可以防范与侦测:
- 不正常的流量
数据库往往非常庞大。为了将数据库运走,往往会产生「不正常」的流量与使用量。
- 防火墙白名单
只准机器被连某些 port,而不准机器连外
- 管理员登入 log
管理员登入机器,必定发送 log 到 slack,且 cc 管理员群。
- 使用「容器」部署
一台机器如果你发现被入侵,虽然没有造成实质损坏,但这一台服务器绝对不能再上线。以免有什么你不知道的后门等等。
比较好的方式,是一开始就用容器如 Docker 架构部署。机器从 OS/ 套件 / 代码都是 script 自动拼组而成的。
而不是手工安装的。摧毁被污染的服务器时,成本才不会过大。
一个互联网服务是活的。我们不能强求一个服务是绝对安全绝对没有 bug 的。但起码要是相对安全的。
有一些状况是之前这个 bug 被修复了。但是在几个月后,因为其他机制的引入,bug 又被打开了。
这里你可以引入一个架构概念,叫 security as test。就是写 integration test,将入侵手法的行为写成 test。确保代码更动时,这个 bug 不会被触发。
关于架构的潜在问题还有很多,在此我只列出最常见的五个情形。
这里面的思维我想强调一个概念,就是绝对的安全是不存在的。你的程序员也不可能阻挡所有的攻击。毕竟程序员的思路主业是「建设」。黑客的思路主要是「破坏窃取」。
而攻击往往比较简单。而身为架构建设者,在规划改善这些架构时你的思路应该是,我如何用 20% 的精力,做到 80% 的风险管理。
所谓「风控」,这个字包含了风险管理和风险控制。
风险管理,它是指如何在项目或者企业在一定的风险的环境里,把风险减至最低的管理过程。它的基本程序包括风险识别、风险估测、风险评价、风险控制和风险管理效果评价等环节。
风险控制是指风险管理者采取各种措施和方法,消灭或减少风险事件发生的各种可能性,或者减少风险事件发生时造成的损失。
这里总结一下你现在可以主动做的事:
- 如何大规模的技术性降低风险?你可以安装什么服务,一次性大幅上升公司的防御能力。
- 如何避免「一个人」被渗透,就会产生大规模的损失?关于人类的弱点是什么?
- 最脆弱的数据环节在哪里?如何自动校验这件事?
- 如何自动化防范过去的错误不再发生。