作为一个自学了三年的个人开发者,一直照着教程和视频来学习,包括一些入门的Android书籍,都从来对Android的安全问题一概忽略。我们应该有这样一种态度,要做极致的东西,就要每一方面都做好,特别是用户数据的安全。这应该是我们开发者应有的对用户的默许的承诺!

android内核实行了特权分离模式,android操作系统要求每一个应用程序在运行时都提供用户标识(UID)和用户群标识(GID)。这种设计的背后是确保没有应用程序可以读、写其他应用程序、设备用户或者操作系统自身的代码或数据。

两个进程分别在各自的沙盒中运行后,两者之间通信的唯一方式是明确请求数据读取权限。

android采取的安全的解决方法和机制即特权分离、权限和应用代码签名。

间接攻击

android 2.2版本发现两个漏洞,(JavaScript)攻击者可以不需要权限,甚至在没有任何提示的情况下,复制SD卡上的文件。如果应用把用户信息保存在SD卡,应用的数据就有被盗的风险。

直接攻击

攻击者会利用应用设计中的弱点来收集用户的敏感信息,或者攻击应用正在通信的服务器。

数据存储

  • 个人信息:如电话号码,邮箱等对自己来说是隐私但可以和其他人分享的信息。
  • 敏感信息:如密码、身份证,其具有较高的价值,在任何时候都应该受到保护。

直接保存在SD卡上的数据是不安全的,需要在保存前进行加密。

Android系统中数据存储机制

存储方式 数据保密性
用户数据共享(SharedPreference) 4种设置方式:MODE_PRIVATEMODE_WORLD_READABLEMODE_WORLD_WRITABLEMODE_MULTI_PROCESS,默认是MODE_PRIVATE
内部存储 3中设置方式:MODE_PRIVATEMODE_WORLD_READABLEMODE_WORLD_WRITABLE,默认是MODE_PRIVATE
外部存储 默认全局可读
SQLite数据库 对程序内所有的类是可以访问的,对于外部应用程序不可访问
网络连接 依赖于Web Services设置

尽管Android有多种数据存储机制,我们仍需要对重要的信息进行加密,比如对存储在SQLite里的数据采用AES加密,即使使用固定的密钥或把密钥保存在手机上也可免受直接攻击。

AES加密标准

公钥加密通过两种不同类型的密钥对数据进行加密或者混淆。每个用户有两类密钥:公钥和私钥。私钥只能用来解密被公钥加密的数据。为非对称加密。

加密和解密数据的为同一个密钥的为对称加密。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public static byte[] encrypt(byte[] key,byte[] data){
SecretKeySpec keySpec = new SecretKeySpec(key,"AES");
Cipher cipher;
byte[] cipherText = null;
try {
cipher = Cipher.getInstance("AES");
//使用生成的密钥加密
cipher.init(Cipher.ENCRYPT_MODE,keySpec);
cipherText = cipher.doFinal(data);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
}
return cipherText;
}
//密钥生成器
public static byte[] generateKey(byte[] randomNumSeed){
SecretKey secretKey = null;
try {
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
//使用SHA1编码
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
random.setSeed(randomNumSeed);
keyGen.init(256,random);
secretKey = keyGen.generateKey();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return secretKey.getEncoded();
}

Android安全架构

APP在执行api调用时,权限验证机制会检查应用是否有调用API的权限,没有授权则会抛出SecurityException。

可自定义权限,对于希望使用该应用的应用,需要在Mainifest文件中配置标签。

数据存储和密码学

公钥基础设施(PKI)

PKI是基于一个受信任的第三方而进行的身份认证。术语:

  • 消息发送和接收者:交换敏感信息并遵循PKI规范
  • 攻击者
  • 铭感数据
  • 加密后的信息
  • 公钥:锁
  • 私钥:钥匙
  • 认证授权机构(CA):可信的第三方
  • 认证授权域:作为活动可信的第三方,保证所有的交易都在同一个上下文中发生
  • 注册授权机构(RA):核实身份,注册成功后获取自己的公钥和私钥

密码学术语

  • 明文
  • 加密
  • 密文
  • 解密
  • 加密算法
  • 密钥
  • 对称密钥:可加密也可解密
  • 非对称密钥:公钥加密,私钥解密
  • 密码分析:破解密文的研究活动

android中的密码学

手机中引入PKI大材小用(也有对于移动领域的轻量级PKI – LPKI),需要根据情况引入合适的密码技术。

对称加密算法

AES就属于一种对称加密算法或说是分组密码。一次处理若干数据位,叫做分组密码;一次只处理一个数据位,叫做流密码。一些分组密码:

分组密码 | 分组长度 | 密钥长度
| —– | —— | —–|
AES | 128bit | 0~256
Camelia | 128bit | 128,192,256
Blowfish| 64bit | 0~448
Twofish | 128bit | 128,192,256

数据填充

若数据长度小于算法要求的数据长度时,就需要对数据进行填充。

如PKCS5/7填充就是取需要填充的位数作为填充的内容,Android默认使用PKCS5填充方式。

分组密码的几种模式

分组密码有不同的加密和解密机制。最简单的为电子密码本(ECB)模式 ,其为将一个明文数据块加密成一个密文数据库,下一个明文数据块加密成下一个密文数据块,… 但ECB模式不能为模式识别的密码分析提供保护。一旦模式确定了,就很容易推断出使用了ECB加密,攻击者只需瞄准解决特定的密文数据块即可,而不必解密整个密文。

  • 密码分组链接(CBC):使用初始化向量IV和第一组明文进行异或操作,然后加密,加密后的密文与下一组明文进行异或操作,…保证了每一组密文依赖于它前面所有的明文。
  • 填充密码分组链接(PCBC):它不仅有初始化向量IV,还包含初始化向量与第一组密文进行异或操作,以及这个结果与下一组进行异或操作。密文中任何一个小的修改都会导致加密和解密流程发生很大的改变。
  • 密码反馈(CFB):首先对初始化向量加密,再由加密后的初始化向量与明文进行异或操作生成密文,接着再对密文进行加密,然后与下一组明文进行异或操作。
  • 输出反馈(OFB):加密后的初始化向量没有与明文进行异或操作。初始化向量加密后作为第二组明文的输入再与第一组明文进行异或操作。后续的加密操作都发生在异或之前。

Android默认使用电子密码本模式进行加密和解密操作。

Android Web安全

  • html:静态页面
  • web应用:用户可通过网络访问的软件,可动态生成html
  • web服务:使用某种特定的xml格式来交换数据
    • SOAP:由各种mxl载荷而成
    • RESTFul API:REST(Representational State Transfer)是一种使用无状态的客户端-服务器协议来表述终端web服务的架构,其核心是使用http协议组成URI来描述每一个资源,而不是用那些复杂的协议。

典型的Web应用有3层,表现层、逻辑层和数据层。多层结构的优点即系统管理员可以替换、扩充硬件或服务器端配置而不影响其它的层。

OWASP与Web攻击

OWASP(Open Web Application Security Project)是一个提供安全开发和安全测试指导性原则的非盈利性组织。其有一个针对移动端网络安全的项目点击查看,将会看到:

  • 确认并保护设备上的敏感数据
  • 确保密码等身份认证信息的安全
  • 数据传输安全
  • 正确的身份认证、授权与会话管理
  • 保障后端API服务和平台的安全
  • 与第三方应用程序或服务的安全交互
  • 设置用户隐私使用条例
  • 实现对付费资源的授权访问控制
  • 保证移动应用的分布式安全
  • 运行环境中的代码错误检查

认证技术

SSL(Secure Socket Layer)是一种传输协议,它对两台计算机之间传输的数据进行加密。事实上最新的协议是TLS(Transport Layer Secure),SSL和TLS其中的一部分是X.509证书(遵循PKI)的标准,也是其核心。

  1. 浏览器请求数据安全套接字
  2. 服务器响应返回SSL认证
  3. 会话密钥种子通过SSL密钥加密并传给服务器
  4. 服务器要求之后所有的传输都有加密
  5. 服务器和浏览器直接能够发送加密信息

SSL的本质是信任,如果能诱导用户相信某个服务器,你就能进行中间人并且截获他发送/接收的所有数据。因此SSL也不是绝对安全的。如2011年一个DigiNotar的CA导致攻击,攻击者拥有了合法证书,最终破产。

有两种方法阻止攻击者窥探通过SSL传输的个人认证信息:

OAuth认证

OAuth协议允许第三方站点或应用去访问服务提供商的Web应用中的数据。根据用户被赋予访问这些第三方站点的权限,它可以操控相应的数据而不必在现在的站点保存它在第三方站点的用户信息。

OAuth通过request token来工作,一个网站想访问另一个网站的数据,它必须被这个网站授予一个访问token。比如APP上的第三方登录认证过程。

挑战/应答

挑战方(服务提供方)向被挑战方(用户)发出一个挑战,用户使用选定的加密技术加密一个随机字符串,加密用的密钥就是用户的密码,挑战方使用存在数据库里的该用户的密码来加密那条同样的信息,如果这两个密文匹配,则用户被授权。