Home

Awesome

iOSSignatureAnalysis

Sign加密

概述&原理

【简述】当客户端像服务端发起请求时,以POST请求为例,如果提交的请求体内容未经过加密,请求可能存在被篡改的危险,即使是https请求也是如此(https抓包、修改请求只需要信任根证书即可)。可以通过众多代理抓包、网卡抓包的程序对请求进行拦截,修改请求内容或是使用程序模拟客户端请求发送,达到仿造请求、脱机请求等目的。例如抢购、秒杀类业务;以及一些要求客户端信息准确的业务(如打卡等);应该对请求进行加密,例如使用aes对整个请求体进行对称加密、使用sign对请求体进行签名等。以下介绍sign签名的大致流程,因为aes加密流程相对比较简单,后续也会在密码加密中简要说明。

【进阶①:加盐】此时大家可能就在想了,我们完全可以仿造客户端的签名,自己计算sign值一并传给服务端,就可以绕过这个验证了。确实如此,因为我们已经知道了sign校验的基本流程和规则,但是事实上sign签名中md5之前的值并不是需要固定使用key=value&key=value拼接,只需要客户端与服务端私下约定好规则即可,例如可以在前后拼接约定好的字符串73281937jjdsa key=value&key=value dsjahdjsah,或者对md5进行加盐操作,这样攻击者希望仅仅通过抓包和自己尝试生成sign的梦想就完全破灭了。

【进阶②:添加时间戳,防止请求重放】在上述示例中,我们添加了timestamp这个时间戳,它的作用就是防止请求重放;通过上述的分析我们发现确实达到了可以防止请求体中的内容被篡改的问题,可以很大程度保证客户端数据的真实性,但是遇到类似抢购、秒杀业务的时候我们需要思考一个问题:当我们需要通过程序来抢购一个商品时,实际上不需要仿造任何请求,只需要通过抓包抓到提交商品订单的请求,然后通过程序不断重放,例如在1秒内请求10次,就可以获得远胜于手动点击的抢购速度,这对于一般的用户是不公平的,对服务器的负担也会大大增加。服务端可以通过nginx等对相同ip的请求次数加以限制,但是又有ip池等反制措施,所以对请求重放的限制也是必须的。而在添加timestamp参数后,客户端获取当前timestamp一并传给服务端,服务端只需要将校验相等的sign存在缓存中,并且在下一次请求时,判断sign是否在之前缓存的sign中即可。若在之前缓存的sign中,则直接响应错误信息。因正常的客户端每次请求都会生成最新的毫秒级的timestamp,则不会受任何影响(因为每次生成的sign必然不同),但通过请求重放方式提交的请求将被视为无效请求。

AES加密

aes对称加密,即加密和解密的密钥是相同的,客户端可以和服务端私下约定好一个密钥,然后客户端通过这个密钥对请求体进行加密,服务端通过这个密钥进行解密,若服务端能正常解密,则认为这是一个有效请求,通过aes加密可以有效防止请求被篡改,因为通过抓包看到的是aes加密之后的密文,抓包者不知道密钥的情况下无法获得明文信息,也无法修改明文内容。aes加密后的内容一般需要进行base64处理,因为有些aes加密后的字符串是不可读的。

MD5加密

md5加密是一种不可逆的加密,也就是明文通过md5加密后获得密文后,无法通过密文解密获得明文,且相同明文加密后获得的密文必定相同且唯一,所以md5一般也用作密码加密(这就是为什么大多数网站只能提供"重置密码功能"而不能提供"查询密码"功能的原因,因为即使是开发者也不知道用户的明文密码是什么,服务端验证密码也只是对比md5之后的密码)和sign加密(因md5是不可逆并且唯一的,所以可以避免泄露sign签名的规则,并且可以保证前后端计算出的sign的一致性)。

但是md5也不是完全不可逆的,一些网站也推出了md5解密功能,但是实际基本都是使用暴力破解字典的方案,例如123456通过md5加密后的结果为49ba59abbe56e057,则已知密文为49ba59abbe56e057可以推算出明文为123456。因此密码不宜过于简单,如果是字母+数字的情况下,破解就几乎不可能。近年有报道指明md5已可逆、已不再安全,但是目前而言md5依然被广泛应用在各个需要加密的场景中,总体还是依旧可靠的。

实现sign签名+密码aes加密(示例)

iOS App

JAVA后端接口

验证

逆向分析

【目的&思路】

【方案1】函数hook(class-dump+Logos)

【方案2】方法追踪(class-dump+monkeyDev)

【方案3】UI分析+IDA反编译(monkeyDev+IDA)

End