在阿里聚安全的漏洞扫描器中和人工APP安全审计中,常常发现有开发者将密钥硬编码在Java代码、文件中,这样作会引发很大风险。信息安全的基础在于密码学,而经常使用的密码学算法都是公开的,加密内容的保密依靠的是密钥的保密,密钥若是泄露,对于对称密码算法,根据用到的密钥算法和加密后的密文,很容易获得加密前的明文;对于非对称密码算法或者签名算法,根据密钥和要加密的明文,很容易得到计算出签名值,从而伪造签名。java
密钥硬编码在代码中,而根据密钥的用途不一样,这致使了不一样的安全风险,有的致使加密数据被破解,数据再也不保密,有的致使和服务器通讯的加签被破解,引起各类血案,如下借用乌云上已公布的几个APP漏洞来说讲。c++
某P2P应用客户端,用来加密数据的DES算法的密钥硬编码在Java代码中,而DES算法是对称密码算法,既加密密钥和解密密钥相同。 算法
反编译APP,发现DES算法:安全
发现DES算法的密钥,硬编码为“yrdAppKe”,用来加密手势密码:服务器
将手势密码用DES加密后存放在本地LocusPassWordView.xml文件中:app
知道了密文和加密算法以及密钥,经过解密操做,能够从文件中恢复出原始的手势密码。或者使用新的生成新的手势密码,而与服务器通讯时接口中的Jason字段也用了DES算法和密钥硬编码为“yRdappKY”:函数
和服务器通讯采用http传输,没有使用https来加密通讯,若是采用中间人攻击或者路由器镜像,得到流量数据,能够破解出用户的通讯内容。测试
某租车APP与服务器通讯的接口采用http传输数据,而且有对传输的部分参数进行了加密,加密算法采用AES,可是密钥硬编码在java代码中为“shenzhoucar123123”,可被逆向分析出来,致使伪造请求,结合服务器端的漏洞,引发越权访问的风险,如越权查看其它用户的订单等。 ui
和服务器通讯时的数据为:编码
q字段是加密后的内容。逆向APP,从登陆Activity入手:
分析登陆流程:v1是用户名,v2是密码,v3是PushId,在用户名和密码不为空而且长度不小于11状况下,执行LoginOperate相关操做,追踪LoginOperate的实现,发现继承自BaseOperate,继续追踪BaseOperate的实现:
在BaseOperate的initUrl()方法中,找到了APP是怎么生成请求数据的:
继续追踪上图中的initJsonUrl()方法,发现其调用了AES加密:
继续追踪aes.onEncrypt()函数:
在onEncrypt()函数中调用了encrypt()函数用来加密数据,追踪encrypt()函数的实现,发现其使用AES算法,而且密钥硬编码在java代码中为“shenzhoucar123123”
到如今请求中的数据加密如何实现的就清晰了,另外因为服务器权限控制不严,就能够构造订单id的请求,达到越权访问到其余用户的订单。
构造{“id”:”11468061”}的请求:
其中uid设置为你本身的uid便可,能够成功看到其余人的订单:
攻击者彻底能够作到使用其余脚本从新实现相同的加密功能并拼接出各个接口请求,批量的刷取订单信息和用户其余信息。
某酒店APP和服务器通讯时接口采用http通讯,数据进行了加密,而且对传输参数进行签名,在服务器端校验签名,以检查传输的数据是否被篡改,可是加签算法和密钥被逆向分析,可致使加签机制失效,攻击者可任意伪造请求包,若结合服务器端的权限控制有漏洞,则可引起越权风险等。
APP和服务器通讯的原始包以下图,能够看到有加签字段sign:
逆向APP定位到加密算法的逻辑代码,com.htinns.biz.HttpUtils.class,其实现逻辑为:
原始数据是unSignData,使用RC4算法加密,密钥为KEY变量所表明的值,加密后的数据为signData,传输的数据时的data字段为signData。
加签字段signd的生成方法是用unsignData拼接时间戳time和resultkey,而后作md5,再进行base64编码。时间戳保证了每次请求包都不同。
sendSign()算法是用c或c++写的,放入了so库,其余重要算法都是用java写的。可使用IDA逆向分析so库,找到sendSign()方法
而乌云漏洞提交者采用的是分析sign和getSign(sign)的数据,作一个算法破解字典。其实还有种方法直接调用此so库,来生成字典。
签名破解之后,就能够构造发送给服务器的数据包进行其余方面的安全测试,好比越权、重置密码等。
经过以上案例,并总结下本身平时发现密钥硬编码的主要形式有:
一、密钥直接明文存在sharedprefs文件中,这是最不安全的。
二、密钥直接硬编码在Java代码中,这很不安全,dex文件很容易被逆向成java代码。
三、将密钥分红不一样的几段,有的存储在文件中、有的存储在代码中,最后将他们拼接起来,能够将整个操做写的很复杂,这由于仍是在java层,逆向者只要花点时间,也很容易被逆向。
四、用ndk开发,将密钥放在so文件,加密解密操做都在so文件里,这从必定程度上提升了的安全性,挡住了一些逆向者,可是有经验的逆向者仍是会使用IDA破解的。
五、在so文件中不存储密钥,so文件中对密钥进行加解密操做,将密钥加密后的密钥命名为其余普通文件,存放在assets目录下或者其余目录下,接着在so文件里面添加无关代码(花指令),虽然能够增长静态分析难度,可是可使用动态调式的方法,追踪加密解密函数,也能够查找到密钥内容。
保证密钥的安全确是件难事,涉及到密钥分发,存储,失效回收,APP防反编译和防调试,还有风险评估。能够说在设备上安全存储密钥这个基本无解,只能选择增大攻击者的逆向成本,让攻击者知难而退。而要是普通开发者的话,作妥善保护密钥这些事情这须要耗费很大的心血。
产品设计者或者开发者要明白本身的密钥是作什么用的,重要程度怎么样,密钥被逆向出来会形成什么风险,经过评估APP应用的重要程度来选择相应的技术方案。
因此建议不妨试试阿里聚安全的安全加固和安全组件,其中安全组件中的安全加密功能提供了开发者密钥的安全管理与加密算法实现,保证密钥的安全性,实现安全的加解密操做;安全签名功能实现客户端请求的签名处理,保证客户端与服务端通讯请求不被伪造。安全加固提高安全等级,防止应用被逆向破解。这样同时从应用层、运行层、native层提供多层次全方位立体防御,另外还有安全沙箱、白盒加密、底层加固共同保证客户端数据安全。攻防是不断变化演进的,阿里聚安全提供的服务能实时更新客户端模块,经过阿里聚安全的漏洞扫描来检测应用是否具备密钥硬编码风险,保证在攻防对抗中永远处于上风。
专业的事情交给专业的人来作,本身的主要精力用来作功能开发或者业务逻辑,快速打造能赢得市场的可靠产品才是王道。
[1] http://www.wooyun.org/bugs/wooyun-2010-0187287
[2] http://www.wooyun.org/bugs/wooyun-2010-0105766
[3] http://www.wooyun.org/bugs/wooyun-2015-0162907
[4] http://jaq.alibaba.com/safety?spm=a313e.7837752.1000001.1.zwCPfa
[5] https://www.zhihu.com/question/35136485/answer/84491440
做者:伊樵、呆狐@阿里聚安全,更多安全技术文章,请访问阿里聚安全博客