Android应用安全之脆弱的加密 - bamb00

标签: android 应用 安全 | 发表时间:2015-04-08 10:41 | 作者:bamb00
出处:

程序员希望通过加密来提升程序的安全性性,但却缺乏专业的密码学背景知识,使得应用对数据的保护非常薄弱。本文将介绍可能出现在Android应用中的一些脆弱的加密方式,以及对应的攻击方法。

造成脆弱加密的主要原因

  Android应用中造成弱加密的原因多种多样,OWASP Mobile Top 10 给出了几个原因:  

使用了脆弱的加密算法

使用了强健的加密算法,但加密的实现存在漏洞。

使用弱密码算法实现加解密

我们先来看看如果如果一个应用使用弱加密算法会遭受怎样的攻击。

例如使用MD5作为Hash算法,MD5已经认为不安全了。如果应用使用了MD5这样的脆弱算法,而攻击者又能读取到Hash,攻击者就有相当大的机会能破解加密。假设应用使用MD5生成了这样一段Hash:

8f6b983ad06881847a180f1398910891

攻击者可以使用john之类的工具或在线的彩虹表破解服务:

如上图,hash被成功破解。

除此之外,有的开发者也会使用编码来保护敏感信息。编码不是加密,可以很容易就解码还原出明文。例如我们在反编译了一个应用之后发现了如下的一段Base64编码字符:

SGVsbG8gV29ybGQu

找一个提供在线base64解码的网站就能还原出明文:

强密码算法的不安全实现

另一种情况是使用了较强的加密,但使用方法不够安全,例如使用了AES这样的对称加密算法,尽管该算法足够强壮,但当其实现不当的时候也一样容易受到攻击。

1.AES加密使用javax.crypto.Cipher初始化时如果使用了ECB模式,将会使相同的明文在不同时候会产生相同的密文,容易遭到字典攻击,安全性不够高。

public void initAES()
{
try {
this.cipher = javax.crypto.Cipher.getInstance("AES/ECB/PKCS5Padding");
Exception v0_3 = new javax.crypto.spec.SecretKeySpec(this.keyBytes, "AES");
this.cipher.init(1, v0_3);
this.decipher = javax.crypto.Cipher.getInstance("AES/ECB/PKCS5Padding");
this.decipher.init(2, v0_3);
com.easemob.util.EMLog.d("encrypt", "initital for AES");
} catch (Exception v0_5) {
v0_5.printStackTrace();
}
return;
}

 2.使用SecureRandom时使用方法setSeed设置种子将会造成生成的随机数不随机。

通常我们都能意识到应该使用SecureRandom类来产生密钥,用来对本地的敏感信息进行加密,实际上这种做法是欠妥的。

在这种方法中,不将密钥作为一个字符串直接存储在APK文件中,而是通过另外一个字符串来生成密钥–有点类似于通过用户口令生成加密密钥。这种必要的混淆手段可以使攻击者不容易破解加密信息,但是对于一个有经验的攻击者而言,这种策略很容易被绕过,因此我们不推荐这种方法。

事实上,Android现有的安全机制中已经为这种数据提供了很好的保护,敏感数据应该标记上 MODE_PRIVATE,然后存储在内部存储中,请注意,千万不能存储在SD卡中,因为访问控制没法强制在外部存储上起作用。

结合设备加密措施,这种方法可以杜绝绝大部分攻击。

除此之外,像我们上面描述的那样使用SecureRandom类还存在另外一个问题。从Android4.2开始,SecureRandom的默认实现是OpenSSL,开发者无法覆盖SecureRandom的内部状态信息,例如下面这段代码:

SecureRandom secureRandom = new SecureRandom();
byte[] b = new byte[]{(byte)1};
secureRandom.setSeed(b);
//在Android4.2上,下面这行代码总是返回同一个数字。
System.out.println(secureRandom.nextInt());

 (【译者注】这段代码可以看到通过程序覆盖了random对象中的种子,造成每次生成的随机数序列都是一样的)

在以前的Android版本中,SecureRandom是基于Bouncy Castle实现的,它允许像上面代码这样的操作,每个SecureRandom类的实例产生伪随机数时使用的种子是从/dev/urandom获取的。(【译者注】/dev/urandom是类Unix系统中根据当前计算机混乱状态,如内存使用,CPU占用率等信息计算出来的随机数,读者可以在Linux下试试cat /dev/urandom,它会不停地输出乱码,一般用“熵”这个专业术语形容计算机的混乱状态)。那些试图使用产生随机数的开发者通常是通过替换现有的种子来产生随机数序列的(参考 相关实现文档),如果种子固定,那么产生的随机数列就是可预测的,这一点是不安全的。现在通过OpenSSL实现,使得这种错误的行为不再可能出现。

不幸的是,那些依赖老的SecureRandom类的应用程序会发现每次程序启动时产生的随机数都不一样了(事实上,这就应该是随机数发生器的期望行为)。想要通过这种方法对加密密钥混淆已经不可行了。

(【译者注】原作者的意思是有些应用对敏感信息做加密,加密的话需要密钥,但是密钥如果直接存起来觉得很不放心,于是通过产生随机数的方式来对密钥混淆一下,那么每次程序启动时都要用相同的密钥去解密数据,于是通过一个固定的信息,比如一个密码,或者记住某个随机数字,通常很多人用当前时间,然后通过这个固定的信息作为种子产生随机数,用这个随机数做密钥,相当于对这个固定信息做了一次混淆操作。实际上这种方法还是不安全,安全性就变成了如何保证这个种子的安全性,治标不治本。下面的部分作者的意思是应该直接将密钥打上MODE_PRIVATE的标记存起来,通过系统的访问控制机制保证密钥的安全性。)

 正确的方法

一种更加合理的解决方案很简单,就是当应用程序第一次启动时产生一个随机的AES算法的密钥:

public static SecretKey generateKey() throws NoSuchAlgorithmException {
// 生成一个256位密钥
final int outputKeyLength = 256;

SecureRandom secureRandom = new SecureRandom();
// Do *not* seed secureRandom! Automatically seeded from system entropy.
//不要给secureRandom一个固定的种子!通过系统熵值产生随机的种子
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(outputKeyLength, secureRandom);
SecretKey key = keyGenerator.generateKey();
return key;

注意这种方法的安全性依赖于如何保证密钥的安全性,这可以依赖于Android系统的内部存储的安全性。将密钥直接存放在文件中,标记为MODE_PRIVATE存在内部存储器。(【译者注】我们很多人的Android手机都被Root过的,好多应用也会取得Root权限,Root权限用户是可以做任何事情的。。。这怎么办呢?)

更加安全的方法

如果你的应用还需要额外的加密操作,那么一个推荐的方法是每次进入你的应用时需要输入一个口令或者PIN码。然后将这个口令传给 PBKDF2(PBKDF2,基于口令的密钥导出函数版本2,是RSA安全公司提出的密钥导出算法,通常用来根据口令取得密钥,通过一种叫做密钥拉伸的专业技术),Android在SecretKeyFactory类中提供了一个叫做PBKDF2WithHmacSHA1的实现:

public static SecretKey generateKey(char[] passphraseOrPin, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException {
//PBKDF2算法执行轮数,这个数字越大,计算时间越长,你应该让这个数字
//足够大,以至于这个算法执行时间超过100毫秒以保证安全性
final int iterations = 1000;

// 产生一个256位的密钥
final int outputKeyLength = 256;

SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec keySpec = new PBEKeySpec(passphraseOrPin, salt, iterations, outputKeyLength);
SecretKey secretKey = secretKeyFactory.generateSecret(keySpec);
return secretKey;
}

 加密盐应该是一个通过SecureRandom产生的随机字符串,和加密密文一起存放在内部存储器中。使用加密盐很重要,它可以有效防止字典攻击。

(【译者注】看PBKDF2WithHmacSHA1这个名字也可以知道该算法是基于SHA1算法的,经常攻击这种单向函数方法就是字典攻击,预先计算好大量的明文对应的密文,就像是明文对应密文的字典,然后再进行逐一对比,如果明文字符串在加密前和一个随机字符串做个连接操作,那么那些预先计算的字典就没用了。)

检查你的应用是不是正确的使用SecureRandom

如本文以及 Jelly Bean的新安全特性所述,Android4.2的SecureRandom默认实现发生了变化,用它产生固定密钥已经行不通了。

如果你也用了这种错误方法的话,我们建议现在就更新你的应用,防止当用户升级到Android4.2或以上版本后发生一些莫名其妙的错误。

 

参考链接:

http://bobao.360.cn/learning/detail/174.html

http://www.cnblogs.com/maverick-fu/p/4341808.html

http://www.importnew.com/3456.html


本文链接: Android应用安全之脆弱的加密,转载请注明。

相关 [android 应用 安全] 推荐:

ANDROID应用安全防御

- - 移动开发 - ITeye博客
Android应用的安全隐患包括三个方面:代码安全、数据安全和组件安全.   代码安全主要是指Android apk有被篡改、盗版等风险,产生代码安全的主要原因是apk很容易被反编译、重打包. 我们可以采用以下方法对apk进行保护:.   代码混淆可以在一定程度上增加apk逆向分析的难度. Android SDK从2.3开始就加入了ProGuard代码混淆功能,开发者只需进行简单的配置就可以实现对代码的混淆.

Android 应用安全风险与防范

- - DiyCode - 致力于构建开发工程师高端交流分享社区社区
Hello,大家好,我是Clock. 最近一段时间在做Android应用安全方面的功课,本文进行简单梳理方便以后Review,有错误和遗漏之处还请大家指出. Android开发除了部分功能采用C/C++编码外,其余主要都是采用Java进行编码开发功能. Java应用非常容易被反编译,Android自然也不例外.

Android应用安全之脆弱的加密 - bamb00

- - 博客园_首页
程序员希望通过加密来提升程序的安全性性,但却缺乏专业的密码学背景知识,使得应用对数据的保护非常薄弱. 本文将介绍可能出现在Android应用中的一些脆弱的加密方式,以及对应的攻击方法.   Android应用中造成弱加密的原因多种多样,OWASP Mobile Top 10 给出了几个原因:  . 使用了强健的加密算法,但加密的实现存在漏洞.

两款免费的Android应用代码安全检测工具

- - FreeBuf.COM | 关注黑客与极客
‍‍FreeBuf前不久刚刚 报道过,美‍‍图秀秀、gReader、福昕PDF阅读器等14款Android应用易遭中间人攻击. 今天,央视《 新闻直播间》也用“黄金三分钟”介绍了安卓手机上存在的名为“寄生兽”的通用型安全漏洞,影响规模达到数以千万级的用户,市面上安卓90%APP都中招. 今年6月Android智能手机在美国的市场份额上升2.8%,达到64.9%.

Android应用安全开发之浅谈网页打开APP

- - WooYun知识库
Author:伊樵,呆狐,舟海@阿里移动安全. 0x00 网页打开APP简介. Android有一个特性,可以通过点击网页内的某个链接打开APP,或者在其他APP中通过点击某个链接打开另外一个APP(AppLink),一些用户量比较大的APP,已经通过发布其AppLink SDK,开发者需要申请相应的资格,配置相关内容才能使用.

从零开始学Android应用安全测试(Part1)

- - FreeBuf.COM | 关注黑客与极客
在本系列文章中,利用InsecureBankv2这款含有漏洞的安卓应用,我们可以了解到有关安卓应用安全的种种概念. 我们将从一个新手的角度看待每一个问题. 所以,我建议新手朋友可以关注下本系列文章. 由于教程是从零开始,前面的东西不免会比较基础,老鸟请先飞过吧. 在对安卓应用测试之前,我们需要搭建一个合适的移动渗透平台.

腾讯应用中心Android客户端上线 设安全认证

- Tony - cnBeta.COM
Android腾讯应用中心客户端昨日全新上线,其前身是“QQ手机软件管理”. 腾讯应用中心Android客户端全新的UI和架构,显示出腾讯应用中心的社区化和开放平台理念,同时腾讯应用中心每款应用都经专业的QQ手机管家认证,用户下载更安心.

92%的主流Android应用都存在安全或隐私风险

- - IT经理网
云移动风险管理公司 MetaIntell近日对包括亚马逊、CNET以及谷歌官方应用商店Google Play中,人们最常下载的前500名应用进行测试后发现,92%的Android应用都采用了不安全的通讯协议,60%的应用与黑名单列表中的网站通讯,20%的应用在用户不知情或未经用户授权的情况下加载远程或者本地应用.

GetEd2k (Android应用)

- 某牢 - eMule Fans 电骡爱好者
GetEd2k是一个Android应用程序,作者是anacletus. 此应用可以帮助你把网页中的电驴(eDonkey) 链接添加到你个人电脑的电驴客户端里,不过前提是你的客户端开启了用于远程控制的Web interface(Web服务器,网页接口,Web界面),当然,eMule(电骡), MLDonkey 和 aMule 都支持该功能,所以这三种主流电驴客户端的用户都可以使用GetEd2k.

Android操作系统安全

- - CSDN博客推荐文章
        Android在迅猛发展的同时,其安全问题一直没有引起足够的重视,但在2010年6月研究人员发布Android平台的KernelRootkit以来,Android平台的安全问题引来了越来越多的关注,而同时,Android平台的恶意软件也开始流行起来.        根据以上的Android系统架构分析,可以发现在三个层面可能存在恶意软件.