Stoned's Blog

A startup hacker.

增长黑客之防御术

在犬校里见了不少被攻击的例子,有些我经历过,有些我也对其他人用过。其实很多时候,稍微了解一些,在设计与开发时,略加注意,提前预防,就能避免遭受类似的攻击。(以下内容针对App的攻防)

给大家讲具体的方法之前,需要先对大家普及一下一些基本的概念。

唯一标识 (unique identifier)。我们会用一些唯一标识来区分不同的用户,常用的唯一标识有

  • UserId,自己产品的用户id
  • OpenId, 第三方产品的唯一用户id,比如微信的openid。
  • IMEI,每个手机都会有不同的IMEI,所以IMEI可以用来标识设备是否相同。(苹果因为禁止获取IMEI,但仍有办法获得类似的标识)。ps:忽略山寨机,12年左右山寨机比较多,好多imei是相同的,但现在极少有imei相同的手机了。
  • 手机号,通过验证的手机号。
  • IP,ip不算是唯一标识,因为一个局域网的用户可以使用相同ip进行登录或者操作,但ip仍可作为一个有效的手段来区分是个体用户还是组团用户。
  • token,因为http是无状态的,这意味着每个请求都是独立的,所以你不能因为用户的上一个请求通过登录了,下一个请求就不检验这个用户是否合法。因此会用token来代表用户的合法性。
  • 签名,我们知道文件下载的时候会检验下载下来的文件签名是否与官方公布的文件签名是否一致,这样就可以避免文件被篡改或者下载不完整。同样的,我们也可以用签名来验证一个客户端api请求的合法性。

攻击(attack)。攻击一般分两种,非法攻击与合理攻击。两者的区别在于是否篡改app设计的功能行为。所以举个例子,合理攻击包括

  • 组织1000个人,每人操作10个手机,定点(比如晚上9点)使用app的上传视频功能,结果服务器搞崩了几个小时。
  • 通过抓包的方式,发现正常请求一个用户的信息的时候,会泄露这个人的密码等隐私信息(虽然没展现在界面上),所以你通过这个办法获取到了某个重要人物的密码,登录他的账号后,给他传了一些不可描述的视频…
  • 人为上传敏感视频或内容…

一般可以进行合理攻击的原因都在于产品/接口设计缺陷,在设计实施时有意识想想这块问题,基本都能避免。所以后面我们主要针对非法攻击这块。

刚才给非法攻击下了一个定义,非法攻击是指篡改了app原本的功能行为的攻击行为,所以,既然与原本的app行为不一致,那很明显,这种攻击是指有人通过代码/工具模拟或篡改app行为,所以这种攻击一般具有以下特征:

  • 高频
  • 大量请求
  • 集中,所有请求通过某一UserId或者某一IP或者某一IMEI发起。

既然我们知道了非法攻击的定义与特征,有什么办法可以避免呢?换言之,有什么办法可以避免别人模拟或篡改app行为呢?其实答案也很简单,那就是

  • 不让其他人发现app行为背后的请求与逻辑
  • 对每个用户请求采用签名验证,拒绝伪造请求。
  • 如果还没办法做到前两项,那么还能根据非法攻击的特征进行预防。

不让其他人发现app行为背后的请求与逻辑,指的是对外界可见的各个层面进行保密/加密,比较常见的办法有

  1. android混淆
  2. android加固/加壳
  3. 重要参数与方法用native的方式写成so,比如key与加密的方法
  4. HTTPS + pinning
  5. 接口级别加密

前三条比较常见,大部分公司都是这么做的,第四条做到的公司不是太多。第四条的核心目的是为了防抓包,也就是说当别人无法通过反编译或者抓包获取你的api方法与参数时,大部分的攻击方法就会失效。但许多公司只上了HTTPS,却没有开pinning。

划重点

请让你的工程师开启HTTPS + pinning

请让你的工程师开启HTTPS + pinning

请让你的工程师开启HTTPS + pinning

这一条简单有效的办法可以在创业中前期(百万之前吧)避开各种蛇虫鼠蚁。

第五条就是比较变态了,有利有弊,弊端是工程师沟通成本、debug成本会增加,优势是接口加密级别提升不少,但个人不太建议这么做,原因是当你做好前4条之后,破解难度已经很高了,大部分人无法突破前四道防线。而能突破前四条防线的人,估计也能突破第五条防线…

当你的app加密级别比较高,相当于你给自己设了一道暗门,只有你自己知道入口在哪里,其他人根本找不到你的入口。虽然这个办法很好,可是你心理还是嘀咕,万一,真的要是万一别人知道了你的暗门,轻轻一推就能进来了,这是不是太不安全了。那好,那就给你的暗门再装一道人脸识别的开关吧,这下除了你之外就没人能进来了。

对于app而言,这人脸识别就是对每个请求采用签名验证。

签名验证的基本原理是只有你自己知道加密秘钥与加密方法,所以你可以对每一个请求进行签名计算,服务器根据传上来的签名进行校验,如果签名有效,就转去相应的逻辑处理,如果签名无效,就直接拒绝请求。

对于签名机制的设计,最好考虑到以下几点:

  1. 对签名加上时间戳,这样可以保证每个请求的签名都不一样
  2. 对签名的内容加上用户相关的信息,比如token
  3. 对签名进行检查,同一合法的签名只允许通过一次,这样可以防御别人发起DDOS攻击。
  4. 请为签名秘钥添加版本管理,避免秘钥泄露带来的秘钥更换的问题。
  5. 注意在客户端保护签名秘钥与签名方法,请参见『增长黑客之防御术2』

划重点:

请开启HTTPS + pinning,以及采取签名验证

请开启HTTPS + pinning,以及采取签名验证

请开启HTTPS + pinning,以及采取签名验证