第三章:服务的架构一定有漏洞(上)
相较前两章,这一章的内容就相对温和许多了。服务的架构一定会有漏洞,这都是大家心知肚明的事。
反而没什么好吃惊的。
这一部分我会拆成几个章节写。这一章主要是在讲「暴露在外的部分」
关于网站的部分,最常见的攻击有几种:
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% 的风险管理。
所谓「风控」,这个字包含了风险管理和风险控制。
风险管理,它是指如何在项目或者企业在一定的风险的环境里,把风险减至最低的管理过程。它的基本程序包括风险识别、风险估测、风险评价、风险控制和风险管理效果评价等环节。
风险控制是指风险管理者采取各种措施和方法,消灭或减少风险事件发生的各种可能性,或者减少风险事件发生时造成的损失。
这里总结一下你现在可以主动做的事:
如何大规模的技术性降低风险?你可以安装什么服务,一次性大幅上升公司的防御能力。
如何避免「一个人」被渗透,就会产生大规模的损失?关于人类的弱点是什么?
最脆弱的数据环节在哪里?如何自动校验这件事?
如何自动化防范过去的错误不再发生。
第四章:服务的架构一定有漏洞(下)
上一章讲的多半是关于直接暴露在外部用户的架构。
这一章我们要讲的是内部的架构。我会直接以一个区块链交易所作为例子。说明如何设计「相对安全」的架构。
以一个区块链交易所,最脆弱的瓶颈在于以下几点:
用户提币
交易上链
钱包存取
用户存币
在前面一章的状况,我已经说过骇客常见的手法就是窜改数据库,直接假造馀额,进行提款。
关于这一点,其实可以用校验馀额与用户分层行为风控避掉。
比较危险的真不在这一环。而在于更后面的几层环节。
冷热钱包设计
现在坊间币所都夸耀自己有冷热钱包设计。其实这已经是目前标配了。
什么叫做冷热钱包设计呢?
区块链币所的原理是:
存币是扫描区块链帐本记录,扫描到用户专属钱包地址有存款动作以后,相对应的在数据库上记上一笔。
提币是发起提币后,通知币所的热钱包,要提币走人,发起提币。
用户专属的钱包与币所的热钱包,不是同一个钱包。
你可以想像成用户专属的钱包就如同存款机一样,你是把一千元存到机器里面。然而,你可以转身到街头的分行,找柜台,再把这一千元提领出来。
风险在哪里呢?
用户可以在存款机存了假钞 1000 万,然后去银行柜台说他要提 1000 万。
在早期很多币所,只有一台 web,连钱包都放在同一台 web 机器上。黑客甚至不需要改代码,只要在 web 机器上调用提款指令,整间币所的钱就被提走了。
你想,这么蠢的事情怎么可能发生呢?嗯,业界还挺多人是这样的设计的…..你在网上看到的那些新闻,嗯….
这些币所的设计很呆,基本上就是一支机器人,定期归集去用户的小钱包,将钱搜集回来,都堆到银行柜台里。然后抢匪只要去银行柜台假装自己要提款,或直接抢钱,就可以把银行抢空了。
这种真实世界不可能发生的情况,却在业界里面很常见。
当然,这样就被搞到破产,实在太好笑了。所以后来大家改了架构设计,变成机器人去搜集用户的钱,然后通通存到冷钱包里面(可以想像成金库),然后从金库里面只拿 1/10 的钱放在柜台里面。
这样就算柜台被打劫一空,顶多也只是损失 1/10 金额而已。
这就是冷热钱包架构设计的简单版本。
关于钱包的进阶设计,我们会在后面其他的章节深入探讨。
刚刚我们说到了提款这件事。很大的危险在于 Web 服务与钱包放在一起。
所以这里我们必须引入第一个概念。Web 服务不可以直接直通钱包。目前区块链钱包都是走 RPC。也就是提款的方式,是 web 机器直接对钱包发一个指令通知要提币。
这个方式很有风险。比较好的方式应该是:
STEP 1: web 只能跟「提币 Service」请求需要提币,而不是直接「告诉钱包」要提币。只有「提币 Service」可以跟钱包对话,必须「提币 Service」批准提币,才可以将请求上链。
STEP 2:提币 Service 要自带风控功能,也就是异常金额提币,必须直接在这层直接被阻断或 delay。
STEP 3:提币不可以是请求一次就发送一次。应该至少累积一定次数 50 次,或者是至少 10 分钟- 20 分钟,批量放行。以免黑客或洗钱洗币份子的行为无法被阻挡。
STEP 4:黑币钱包地址自动进黑洞。所谓黑币是只有一些资金,是黑客盗币所所得。币所都有联防系统,只要地址被加入黑名单,存款与提款行为,都会自动失效。
STEP 5:非热门时段,主动降低提币速度与提高风控层级。我们是亚洲币所,服务时间很集中都会再 +0800 的特定时段。如果有大额提币发生在冷门时段,这些提币应该要被 delay 到上班时间由人工介入处理。避免重大损失。
所以这里的概念,主要是不能「用户告诉你什么,就执行什么」,而是得向「风控系统」「申请通过」,而且利用「批量审核」做出时间差,若有什么差池,有机会挽救。
前面我们讲到的是提币风险。其实存币也有风险。
几个业界曾经有出现的状况是:
洗币。用户大额存币并同时大额提币。害交易所背锅。(以前 EOS 就考虑要对经手黑钱的钱包进行冻结制裁,被许多交易所反对。因为如此,锁到的不是黑客,而是交易所的钱会牵连被冻。只经手 1000 EOS,结果 100 万 EOS 钱包被冻,也太倒楣了吧)
智能合约攻击。有一些 Token 的智能合约没有写好。合约 owner 或甚至路过 user 可以任意增发。充进交易所砸盘换取其他币提现。
51% 算力攻击。前一阵子行情不好,有心人针对某些币发起 51% 算力攻击,制造大笔假交易,充入币所,再提款。
币本身的 security 问题,许多币都是 opensource 软件,而且只有少量业馀程序员维护(甚至活跃的维护者数量都比起一般正规币所的程序员少上许多)。bug 一堆,而这些 bug 可能会造成假充值。黑客发现这些 0day 以后,往往没有兴趣攻击一般 user,而是直接攻击交易所。如果交易所的钱包工程师,没有时时更新钱包,很容易被盯上。
好在这一类的情形都有一些特征,就是
针对交易所
单次大额
冷门时段
所以交易所的防御只是辛苦,但不那么复杂。
可以从两个方向去防御:
1) 审核大额存币
大量存币直接 drop / delay,或者是直接打入可疑款项。
以我们站上的情况,除非是经常交易的大户。否则很少人有大量存币的情况。也就是在风控上就要针对用户分层。
如果是不常交易的用户,突然间存进大量币,然后马上就要交易或提款。这绝对非常可疑。关于提款与交易行为要先全部暂停。
2) 加入由资安谘询公司的币所联防联盟
我们公司的资安顾问是慢雾安全。专注于区块链生态。
加入这一类资安公司组织的联防联盟有很多好处。首先是其他币所要是被入侵了。类似的入侵手法,会在脱敏后,告诉参与联盟的会员,所以第一时间这些洞会被补起来。
第二,洗币地址是共享的。联盟内交易所能够整合,第一时间自动防御。
第三,建设一个互联网项目,大家都有一些共用插件(如 TradingView),或者是底层 library ,或者是币本身的 0day。
资安公司会主动跟踪,告知,甚至发布自己的临时 patch。省去自己追踪的精力。
在这一章节里面,我提到的属于区块链行业的示范。其实同样的思路适合互联网上大多数行业。
这里的思路是你的思路整个架构都应该解耦合,不允许一个系统可以 command all。
也就是某些业务模块在逐渐成熟之后,应该单独抽出一个 service,用 API 形式呼叫,并且加上权限校验。
不管是使用者的 App 与系统沟通,或者是内部系统与系统之间的沟通,都应该使用 API + ACL + persmission management。
当然,经营这件事最挑战的事在于。区块链行业是一阵风,在一年内吹起,明明所有竞争者都是初创团队,需要用初创团队的极速打法。但是架构设计上却得用 5-6 年成熟互联网公司的成熟安全架构。否则只要一不留神,币所都不是没生意倒的,而是被黑客黑倒的。
所以虽然业界有万间交易所,但是最后真正能存活下来的交易所并不多。主要这个赛道真是综合能力的考核。如何兼顾币所的业务以及开发速度以及风控上的防御。更别说在人才招聘的速度与品质。这才是区块链从业者的考验。
这里总结一下你现在可以主动做的事:
立刻加入签约一间资安公司。资安公司不是你出事时才要找。还没出事就得先找好。请他们立刻帮你做体检以及架构调整。
团队自我检查找出脆弱瓶颈点,改版成独立 service,并加上风控设计
对自己的项目解耦合。不能预设内部节点的操作都是可信的。而是如果都不可信,怎么样设计出合理的白名单。