Android 开发中的若干安全问题 之 Activity篇

移动开发 Android
因为,如果假设在同一机器上,有另外一个app有同样的intent-filter的话, 调用该Activity的intent会唤醒android的选择画面, 让你选择使用那个app接受该intent。这样就会事实上绕过了非公开的设置。

1. 本app内部使用的activity一定要设置为非公开

 

不准备对外公开的activity一定要设置为非公开,以防止被人非法调用

 

 

 

  1. <activity 
  2. android:name=".PrivateActivity" 
  3. android:label="@string/app_name" 
  4. android:exported="false" /> 
  5.  
  6. <activity 
  7. android:name=".PrivateActivity" 
  8. android:label="@string/app_name" 
  9. android:exported="false" /> 

 

 

 

 

 

同时,一定要注意的是, 非公开的Activity不能设置intent-filter

 

 

因为,如果假设在同一机器上,有另外一个app有同样的intent-filter的话, 调用该Activity的intent会唤醒android的选择画面, 让你选择使用那个app接受该intent。这样就会事实上绕过了非公开的设置。

 

 

2. 不要指定taskAffinity

 

Android中的activity全都归属于task管理 , 简单说来task是一种stack的数据结构, 先入后出。

 

 

一般来说, 如果不指明归属于什么task, 同一个app内部的所有Activity都会存续在一个task中,task的名字就是app的packageName。

 

 

因为在同一个andorid设备中,不会有两个同packageName的app存在,所以能保证Activity不被攻击。

 

 

但是如果你指明taskAffinity,比如如下

 

 

 

  1. [html] 
  2. <application android:icon="@drawable/icon" android:label="@string/app_name"
  3. <activity android:name=".Activity1" 
  4. android:taskAffinity="com.winuxxan.task" 
  5. android:label="@string/app_name"
  6. </activity> 
  7. <activity android:name=".Activity2"
  8. <intent-filter> 
  9. <action android:name="android.intent.action.MAIN" /> 
  10. <category android:name="android.intent.category.LAUNCHER" /> 
  11. </intent-filter> 
  12. </activity> 
  13. </application> 
  14.  
  15. <application android:icon="@drawable/icon" android:label="@string/app_name"
  16. <activity android:name=".Activity1" 
  17. android:taskAffinity="com.winuxxan.task" 
  18. android:label="@string/app_name"
  19. </activity> 
  20. <activity android:name=".Activity2"
  21. <intent-filter> 
  22. <action android:name="android.intent.action.MAIN" /> 
  23. <category android:name="android.intent.category.LAUNCHER" /> 
  24. </intent-filter> 
  25. </activity> 
  26. </application> 

 

 

 

 

那此时,恶意软件中的Activity如果也声明为同样的taskAffinity,那他的Activity就会启动到你的task中,就会有机会拿到你的intent

 

 

3. 不要指定LaunchMode(默认standard模式)

 

Android中Activity的LaunchMode分成 以下四种

 

Standard: 这种方式打开的Activity不会被当作rootActivity,会生成一个新的Activity的instance,会和打开者在同一个task内

 

 

singleTop: 和standard基本一样,唯一的区别在于如果当前task第一个Activity就是该Activity的话,就不会生成新的instance

 

 

singleTask:系统会创建一个新task(如果没有启动应用)和一个activity新实例在新task根部,然后,如果activity实例已经存在单独的task中,系统会调用已经存在activity的 onNewIntent()方法,而不是存在新实例,仅有一个activity实例同时存在。

 

 

singleInstance: 和singleTask相似,除了系统不会让其他的activities运行在所有持有的task实例中,这个activity是独立的,并且task中的成员只有它,任何其他activities运行这个activity都将打开一个独立的task。

 

 

所有发送给root Activity(根Activiy)的intent都会在android中留下履历。所以一般来说严禁用singleTask或者singleInstance来启动画面。

 

 

然而,即使用了standard来打开画面,也可能会出问题,比如如果调用者的Activity是用singleInstance模式打开,即使用standard模式打开被调用Activity,因为调用者的Activitytask是不能有其他task的, 所以android会被迫生成一个新的task,并且把被调用者塞进去,最后被调用者就成了rootActivity。

 

 

程序如下:

 

 

  1. AndroidManifest.xml 
  2.  
  3. [html] 
  4. <?xml version="1.0" encoding="utf-8"?> 
  5. <manifest xmlns:android="http://schemas.android.com/apk/res/android" 
  6. package="org.jssec.android.activity.privateactivity" 
  7. android:versionCode="1" 
  8. android:versionName="1.0" > 
  9. <uses-sdk android:minSdkVersion="8" /> 
  10. <application 
  11. android:icon="@drawable/ic_launcher" 
  12. android:label="@string/app_name" > 
  13. <!—root Activity以”singleInstance”模式启动 --> 
  14. <!—不设置taskAffinity--> 
  15. <activity 
  16. android:name=".PrivateUserActivity" 
  17. android:label="@string/app_name" 
  18. android:launchMode="singleInstance" > 
  19. <intent-filter> 
  20. <action android:name="android.intent.action.MAIN" /> 
  21. <category android:name="android.intent.category.LAUNCHER" /> 
  22. </intent-filter> 
  23. </activity> 
  24. <!-- 非公開Activity --> 
  25. <!—启动模式为”standard” --> 
  26. <!—不设置taskAffinity--> 
  27. <activity 
  28. android:name=".PrivateActivity" 
  29. android:label="@string/app_name" 
  30. android:exported="false" /> 
  31. </application> 
  32. </manifest> 
  33.  
  34. <?xml version="1.0" encoding="utf-8"?> 
  35. <manifest xmlns:android="http://schemas.android.com/apk/res/android" 
  36. package="org.jssec.android.activity.privateactivity" 
  37. android:versionCode="1" 
  38. android:versionName="1.0" > 
  39. <uses-sdk android:minSdkVersion="8" /> 
  40. <application 
  41. android:icon="@drawable/ic_launcher" 
  42. android:label="@string/app_name" > 
  43. <!—root Activity以”singleInstance”模式启动 --> 
  44. <!—不设置taskAffinity--> 
  45. <activity 
  46. android:name=".PrivateUserActivity" 
  47. android:label="@string/app_name" 
  48. android:launchMode="singleInstance" > 
  49. <intent-filter> 
  50. <action android:name="android.intent.action.MAIN" /> 
  51. <category android:name="android.intent.category.LAUNCHER" /> 
  52. </intent-filter> 
  53. </activity> 
  54. <!-- 非公開Activity --> 
  55. <!—启动模式为”standard” --> 
  56. <!—不设置taskAffinity--> 
  57. <activity 
  58. android:name=".PrivateActivity" 
  59. android:label="@string/app_name" 
  60. android:exported="false" /> 
  61. </application> 
  62. </manifest> 

 

 

非公开Activity的代码如下:

 

 

 

  1. [java] 
  2. package org.jssec.android.activity.privateactivity; 
  3. import android.app.Activity; 
  4. import android.content.Intent; 
  5. import android.os.Bundle; 
  6. import android.view.View; 
  7. import android.widget.Toast; 
  8. public class PrivateActivity extends Activity { 
  9. @Override 
  10. public void onCreate(Bundle savedInstanceState) { 
  11. super.onCreate(savedInstanceState); 
  12. setContentView(R.layout.private_activity); 
  13. String param = getIntent().getStringExtra("PARAM"); 
  14. Toast.makeText(this, String.format("「%s」取得。", param), 
  15. Toast.LENGTH_LONG).show(); 
  16.  
  17. public void onReturnResultClick(View view) { 
  18. Intent intent = new Intent(); 
  19. intent.putExtra("RESULT", 机密数据"); 
  20. setResult(RESULT_OK, intent); 
  21. finish(); 
  22.  
  23. package org.jssec.android.activity.privateactivity; 
  24. import android.app.Activity; 
  25. import android.content.Intent; 
  26. import android.os.Bundle; 
  27. import android.view.View; 
  28. import android.widget.Toast; 
  29. public class PrivateActivity extends Activity { 
  30. @Override 
  31. public void onCreate(Bundle savedInstanceState) { 
  32. super.onCreate(savedInstanceState); 
  33. setContentView(R.layout.private_activity); 
  34. String param = getIntent().getStringExtra("PARAM"); 
  35. Toast.makeText(this, String.format("「%s」取得。", param), 
  36. Toast.LENGTH_LONG).show(); 
  37.  
  38. public void onReturnResultClick(View view) { 
  39. Intent intent = new Intent(); 
  40. intent.putExtra("RESULT", 机密数据"); 
  41. setResult(RESULT_OK, intent); 
  42. finish(); 

 

 

调用非公开Activity者,以standard模式打开

 

 

 

  1. [java] 
  2. package org.jssec.android.activity.privateactivity; 
  3. import android.app.Activity; 
  4. import android.content.Intent; 
  5. import android.os.Bundle; 
  6. import android.view.View; 
  7. import android.widget.Toast; 
  8. public class PrivateUserActivity extends Activity { 
  9. private static final int REQUEST_CODE = 1
  10.  
  11. @Override 
  12. public void onCreate(Bundle savedInstanceState) { 
  13. super.onCreate(savedInstanceState); 
  14. setContentView(R.layout.user_activity); 
  15.  
  16. public void onUseActivityClick(View view) { 
  17. // 用standard模式启动非公开Activity 
  18. Intent intent = new Intent(); 
  19. intent.setClass(this, PrivateActivity.class); 
  20. intent.putExtra("PARAM""机密数据"); 
  21. startActivityForResult(intent, REQUEST_CODE); 
  22.  
  23. @Override 
  24. public void onActivityResult(int requestCode, int resultCode, 
  25. Intent data) { 
  26. super.onActivityResult(requestCode, resultCode, data); 
  27. if (resultCode != RESULT_OK) 
  28. return
  29. switch (requestCode) { 
  30. case REQUEST_CODE: 
  31. String result = data.getStringExtra("RESULT"); 
  32. break
  33.  
  34. package org.jssec.android.activity.privateactivity; 
  35. import android.app.Activity; 
  36. import android.content.Intent; 
  37. import android.os.Bundle; 
  38. import android.view.View; 
  39. import android.widget.Toast; 
  40. public class PrivateUserActivity extends Activity { 
  41. private static final int REQUEST_CODE = 1
  42.  
  43. @Override 
  44. public void onCreate(Bundle savedInstanceState) { 
  45. super.onCreate(savedInstanceState); 
  46. setContentView(R.layout.user_activity); 
  47.  
  48. public void onUseActivityClick(View view) { 
  49. // 用standard模式启动非公开Activity 
  50. Intent intent = new Intent(); 
  51. intent.setClass(this, PrivateActivity.class); 
  52. intent.putExtra("PARAM""机密数据"); 
  53. startActivityForResult(intent, REQUEST_CODE); 
  54.  
  55. @Override 
  56. public void onActivityResult(int requestCode, int resultCode, 
  57. Intent data) { 
  58. super.onActivityResult(requestCode, resultCode, data); 
  59. if (resultCode != RESULT_OK) 
  60. return
  61. switch (requestCode) { 
  62. case REQUEST_CODE: 
  63. String result = data.getStringExtra("RESULT"); 
  64. break

 

 

 

4. 发给Activity的intent不要设定为FLAG_ACTIVITY_NEW_TASK

 

就算上面的Activity的lauchMode设置完善了, 在打开intent的时候还是能指定打开模式。

 

 

比如在intent中指明用FLAG_ACTIVITY_NEW_TASK模式的话,发现该activity不存在的话,就会强制新建一个task。如果同时设置了FLAG_ACTIVITY_MULTIPLE_TASK+ FLAG_ACTIVITY_NEW_TASK,就无论如何都会生成新的task,该Activity就会变成rootActiviy,并且intent会被留成履历

 

 

5. Intent中数据的加密

 

Activity中数据的传递都依靠intent, 很容易被攻击, 所以 就算同一个app内部传递数据, 最好还是要加密, 加密算法很多

 

 

6. 明确ActivityName发送Intent

 

明确Activity发送Intent,能够避免被恶意软件截取。

 

 

同一app内部的发送

 

 

 

 

  1. [java] 
  2. Intent intent = new Intent(this, PictureActivity.class); 
  3. intent.putExtra("BARCODE", barcode); 
  4. startActivity(intent); 
  5.  
  6. Intent intent = new Intent(this, PictureActivity.class); 
  7. intent.putExtra("BARCODE", barcode); 
  8. startActivity(intent); 
  9.  
  10.  
  11. 不同app内部的发送 
  12.  
  13. [java] 
  14. Intent intent = new Intent(); 
  15. intent.setClassName( 
  16. "org.jssec.android.activity.publicactivity"
  17. "org.jssec.android.activity.publicactivity.PublicActivity"); 
  18. startActivity(intent); 
  19.  
  20. Intent intent = new Intent(); 
  21. intent.setClassName( 
  22. "org.jssec.android.activity.publicactivity"
  23. "org.jssec.android.activity.publicactivity.PublicActivity"); 
  24. startActivity(intent); 

 

 

但是,要注意的是!

 

 

 

不是指明了packageName和ActivityName就能避免所有的问题,

 

 

 

如果有一个恶意软件故意做成和你发送目标同packageName, 同ActivityName, 此时的intent就会被截取

 

 

7. 跨app接受Intent时,要明确对方的身份

 

接受到别的app发来的intent时,要能确定对方的身份。

 

 

一个好方法是比对对方的app的hashcode。

 

 

当前,前提是调用者要用startActivityForResult(),因为只有这个方法,被调用者才能得到调用者的packageName

 

 

代码如下:

 

 

被调用的Activity

 

 

 

  1. [java] 
  2. package org.jssec.android.activity.exclusiveactivity; 
  3. import org.jssec.android.shared.PkgCertWhitelists; 
  4. import org.jssec.android.shared.Utils; 
  5. import android.app.Activity; 
  6. import android.content.Context; 
  7. import android.content.Intent; 
  8. import android.os.Bundle; 
  9. import android.view.View; 
  10. import android.widget.Toast; 
  11. public class ExclusiveActivity extends Activity { 
  12. // hashcode的白名单 
  13. private static PkgCertWhitelists sWhitelists = null
  14.  
  15. private static void buildWhitelists(Context context) { 
  16. boolean isdebug = Utils.isDebuggable(context); 
  17. sWhitelists = new PkgCertWhitelists(); 
  18. sWhitelists 
  19. .add("org.jssec.android.activity.exclusiveuser", isdebug ? 
  20. "0EFB7236 328348A9 89718BAD DF57F544 D5CCB4AE B9DB34BC 1E29DD26 F77C8255" 
  21. "1F039BB5 7861C27A 3916C778 8E78CE00 690B3974 3EB8259F E2627B8D 4C0EC35A"); 
  22.  
  23. private static boolean checkPartner(Context context, String pkgname) { 
  24. if (sWhitelists == null
  25. buildWhitelists(context); 
  26. return sWhitelists.test(context, pkgname); 
  27.  
  28. @Override 
  29. public void onCreate(Bundle savedInstanceState) { 
  30. super.onCreate(savedInstanceState); 
  31. setContentView(R.layout.main); 
  32. // check白名单 
  33. if (!checkPartner(this, getCallingPackage())) { 
  34. Toast.makeText(this"不是白名单内部的。", Toast.LENGTH_LONG).show(); 
  35. finish(); 
  36. return
  37.  
  38. public void onReturnResultClick(View view) { 
  39. Intent intent = new Intent(); 
  40. intent.putExtra("RESULT""机密数据"); 
  41. setResult(RESULT_OK, intent); 
  42. finish(); 
  43.  
  44. package org.jssec.android.activity.exclusiveactivity; 
  45. import org.jssec.android.shared.PkgCertWhitelists; 
  46. import org.jssec.android.shared.Utils; 
  47. import android.app.Activity; 
  48. import android.content.Context; 
  49. import android.content.Intent; 
  50. import android.os.Bundle; 
  51. import android.view.View; 
  52. import android.widget.Toast; 
  53. public class ExclusiveActivity extends Activity { 
  54. // hashcode的白名单 
  55. private static PkgCertWhitelists sWhitelists = null
  56.  
  57. private static void buildWhitelists(Context context) { 
  58. boolean isdebug = Utils.isDebuggable(context); 
  59. sWhitelists = new PkgCertWhitelists(); 
  60. sWhitelists 
  61. .add("org.jssec.android.activity.exclusiveuser", isdebug ? 
  62. "0EFB7236 328348A9 89718BAD DF57F544 D5CCB4AE B9DB34BC 1E29DD26 F77C8255" 
  63. "1F039BB5 7861C27A 3916C778 8E78CE00 690B3974 3EB8259F E2627B8D 4C0EC35A"); 
  64.  
  65. private static boolean checkPartner(Context context, String pkgname) { 
  66. if (sWhitelists == null
  67. buildWhitelists(context); 
  68. return sWhitelists.test(context, pkgname); 
  69.  
  70. @Override 
  71. public void onCreate(Bundle savedInstanceState) { 
  72. super.onCreate(savedInstanceState); 
  73. setContentView(R.layout.main); 
  74. // check白名单 
  75. if (!checkPartner(this, getCallingPackage())) { 
  76. Toast.makeText(this"不是白名单内部的。", Toast.LENGTH_LONG).show(); 
  77. finish(); 
  78. return
  79.  
  80. public void onReturnResultClick(View view) { 
  81. Intent intent = new Intent(); 
  82. intent.putExtra("RESULT""机密数据"); 
  83. setResult(RESULT_OK, intent); 
  84. finish(); 
  85. } [java] 
  86.  
  87.  
  88. PkgCertWhitelists.java 
  89. [java] 
  90. package org.jssec.android.shared; 
  91. import java.util.HashMap; 
  92. import java.util.Map; 
  93. import android.content.Context; 
  94. public class PkgCertWhitelists { 
  95. private Map<String, String> mWhitelists = new HashMap<String, String>(); 
  96.  
  97. public boolean add(String pkgname, String sha256) { 
  98. if (pkgname == null
  99. return false
  100. if (sha256 == null
  101. return false
  102. sha256 = sha256.replaceAll(" """); 
  103. if (sha256.length() != 64
  104. return false
  105. sha256 = sha256.toUpperCase(); 
  106. if (sha256.replaceAll("[0-9A-F]+""").length() != 0
  107. return false
  108. mWhitelists.put(pkgname, sha256); 
  109. return true
  110.  
  111. public boolean test(Context ctx, String pkgname) { 
  112. String correctHash = mWhitelists.get(pkgname); 
  113. return PkgCert.test(ctx, pkgname, correctHash); 
  114.  
  115. package org.jssec.android.shared; 
  116. import java.util.HashMap; 
  117. import java.util.Map; 
  118. import android.content.Context; 
  119. public class PkgCertWhitelists { 
  120. private Map<String, String> mWhitelists = new HashMap<String, String>(); 
  121.  
  122. public boolean add(String pkgname, String sha256) { 
  123. if (pkgname == null
  124. return false
  125. if (sha256 == null
  126. return false
  127. sha256 = sha256.replaceAll(" """); 
  128. if (sha256.length() != 64
  129. return false
  130. sha256 = sha256.toUpperCase(); 
  131. if (sha256.replaceAll("[0-9A-F]+""").length() != 0
  132. return false
  133. mWhitelists.put(pkgname, sha256); 
  134. return true
  135.  
  136. public boolean test(Context ctx, String pkgname) { 
  137. String correctHash = mWhitelists.get(pkgname); 
  138. return PkgCert.test(ctx, pkgname, correctHash); 
  139. PkgCert.java 
  140. [java] 
  141.  
  142. package org.jssec.android.shared; 
  143. import java.security.MessageDigest; 
  144. import java.security.NoSuchAlgorithmException; 
  145. import android.content.Context; 
  146. import android.content.pm.PackageInfo; 
  147. import android.content.pm.PackageManager; 
  148. import android.content.pm.PackageManager.NameNotFoundException; 
  149. import android.content.pm.Signature; 
  150. public class PkgCert { 
  151. public static boolean test(Context ctx, String pkgname, 
  152. String correctHash) { 
  153. if (correctHash == null
  154. return false
  155. correctHash = correctHash.replaceAll(" """); 
  156. return correctHash.equals(hash(ctx, pkgname)); 
  157.  
  158. public static String hash(Context ctx, String pkgname) { 
  159. if (pkgname == null
  160. return null
  161. try { 
  162. PackageManager pm = ctx.getPackageManager(); 
  163. PackageInfo pkginfo = pm.getPackageInfo(pkgname, 
  164. PackageManager.GET_SIGNATURES); 
  165. if (pkginfo.signatures.length != 1
  166. return null
  167. Signature sig = pkginfo.signatures[0]; 
  168. byte[] cert = sig.toByteArray(); 
  169. byte[] sha256 = computeSha256(cert); 
  170. return byte2hex(sha256); 
  171. catch (NameNotFoundException e) { 
  172. return null
  173.  
  174. private static byte[] computeSha256(byte[] data) { 
  175. try { 
  176. return MessageDigest.getInstance("SHA-256").digest(data); 
  177. catch (NoSuchAlgorithmException e) { 
  178. return null
  179.  
  180. private static String byte2hex(byte[] data) { 
  181. if (data == null
  182. return null
  183. final StringBuilder hexadecimal = new StringBuilder(); 
  184. for (final byte b : data) { 
  185. hexadecimal.append(String.format("%02X", b)); 
  186. return hexadecimal.toString(); 
  187.  
  188.  
  189. package org.jssec.android.shared; 
  190. import java.security.MessageDigest; 
  191. import java.security.NoSuchAlgorithmException; 
  192. import android.content.Context; 
  193. import android.content.pm.PackageInfo; 
  194. import android.content.pm.PackageManager; 
  195. import android.content.pm.PackageManager.NameNotFoundException; 
  196. import android.content.pm.Signature; 
  197. public class PkgCert { 
  198. public static boolean test(Context ctx, String pkgname, 
  199. String correctHash) { 
  200. if (correctHash == null
  201. return false
  202. correctHash = correctHash.replaceAll(" """); 
  203. return correctHash.equals(hash(ctx, pkgname)); 
  204.  
  205. public static String hash(Context ctx, String pkgname) { 
  206. if (pkgname == null
  207. return null
  208. try { 
  209. PackageManager pm = ctx.getPackageManager(); 
  210. PackageInfo pkginfo = pm.getPackageInfo(pkgname, 
  211. PackageManager.GET_SIGNATURES); 
  212. if (pkginfo.signatures.length != 1
  213. return null
  214. Signature sig = pkginfo.signatures[0]; 
  215. byte[] cert = sig.toByteArray(); 
  216. byte[] sha256 = computeSha256(cert); 
  217. return byte2hex(sha256); 
  218. catch (NameNotFoundException e) { 
  219. return null
  220.  
  221. private static byte[] computeSha256(byte[] data) { 
  222. try { 
  223. return MessageDigest.getInstance("SHA-256").digest(data); 
  224. catch (NoSuchAlgorithmException e) { 
  225. return null
  226.  
  227. private static String byte2hex(byte[] data) { 
  228. if (data == null
  229. return null
  230. final StringBuilder hexadecimal = new StringBuilder(); 
  231. for (final byte b : data) { 
  232. hexadecimal.append(String.format("%02X", b)); 
  233. return hexadecimal.toString(); 

 

 

 

8. 所有根Activity中的intent都能被所有app共享

 

 

 

所有的app,只要按照如下样子,就能取出这台手机上所有task上所有根Activity接受到的intent

 

 

 

  1. AndroidManifest.xml 
  2.  
  3. [html] 
  4. <manifest xmlns:android="http://schemas.android.com/apk/res/android" 
  5. package="org.jssec.android.intent.maliciousactivity" 
  6. android:versionCode="1" 
  7. android:versionName="1.0" > 
  8.  
  9. <uses-sdk 
  10. android:minSdkVersion="8" 
  11. android:targetSdkVersion="15" /> 
  12.  
  13. <application 
  14. android:icon="@drawable/ic_launcher" 
  15. android:label="@string/app_name" 
  16. android:theme="@style/AppTheme" > 
  17. <activity 
  18. android:name=".MaliciousActivity" 
  19. android:label="@string/title_activity_main" > 
  20. <intent-filter> 
  21. <action android:name="android.intent.action.MAIN" /> 
  22.  
  23. <category android:name="android.intent.category.LAUNCHER" /> 
  24. </intent-filter> 
  25. </activity> 
  26. </application> 
  27.  
  28. <uses-permission android:name="android.permission.GET_TASKS" /> 
  29.  
  30. </manifest> 
  31.  
  32. <manifest xmlns:android="http://schemas.android.com/apk/res/android" 
  33. package="org.jssec.android.intent.maliciousactivity" 
  34. android:versionCode="1" 
  35. android:versionName="1.0" > 
  36.  
  37. <uses-sdk 
  38. android:minSdkVersion="8" 
  39. android:targetSdkVersion="15" /> 
  40.  
  41. <application 
  42. android:icon="@drawable/ic_launcher" 
  43. android:label="@string/app_name" 
  44. android:theme="@style/AppTheme" > 
  45. <activity 
  46. android:name=".MaliciousActivity" 
  47. android:label="@string/title_activity_main" > 
  48. <intent-filter> 
  49. <action android:name="android.intent.action.MAIN" /> 
  50.  
  51. <category android:name="android.intent.category.LAUNCHER" /> 
  52. </intent-filter> 
  53. </activity> 
  54. </application> 
  55.  
  56. <uses-permission android:name="android.permission.GET_TASKS" /> 
  57.  
  58. </manifest> 
  59. MaliciousActivity.java 
  60.  
  61. [java] 
  62. package org.jssec.android.intent.maliciousactivity; 
  63. import java.util.List; 
  64. import android.app.Activity; 
  65. import android.app.ActivityManager; 
  66. import android.content.Intent; 
  67. import android.os.Bundle; 
  68. import android.util.Log; 
  69. public class MaliciousActivity extends Activity { 
  70. @Override 
  71. public void onCreate(Bundle savedInstanceState) { 
  72. super.onCreate(savedInstanceState); 
  73. setContentView(R.layout.malicious_activity); 
  74. ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE); 
  75. List<ActivityManager.RecentTaskInfo> list = activityManager 
  76. .getRecentTasks(100, ActivityManager.RECENT_WITH_EXCLUDED); 
  77. for (ActivityManager.RecentTaskInfo r : list) { 
  78. Intent intent = r.baseIntent; 
  79. Log.v("baseIntent", intent.toString()); 
  80.  
  81. package org.jssec.android.intent.maliciousactivity; 
  82. import java.util.List; 
  83. import android.app.Activity; 
  84. import android.app.ActivityManager; 
  85. import android.content.Intent; 
  86. import android.os.Bundle; 
  87. import android.util.Log; 
  88. public class MaliciousActivity extends Activity { 
  89. @Override 
  90. public void onCreate(Bundle savedInstanceState) { 
  91. super.onCreate(savedInstanceState); 
  92. setContentView(R.layout.malicious_activity); 
  93. ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE); 
  94. List<ActivityManager.RecentTaskInfo> list = activityManager 
  95. .getRecentTasks(100, ActivityManager.RECENT_WITH_EXCLUDED); 
  96. for (ActivityManager.RecentTaskInfo r : list) { 
  97. Intent intent = r.baseIntent; 
  98. Log.v("baseIntent", intent.toString()); 

 

 

 

9. Intent数据遗漏到LogCat的可能性

 

如果像如下代码,那Intent中发送的数据就会被自动写入LogCat

 

 

  1. [java] 
  2. Uri uri = Uri.parse("mailto:test@gmail.com"); 
  3. Intent intent = new Intent(Intent.ACTION_SENDTO, uri); 
  4. startActivity(intent); 
  5.  
  6. Uri uri = Uri.parse("mailto:test@gmail.com"); 
  7. Intent intent = new Intent(Intent.ACTION_SENDTO, uri); 
  8. startActivity(intent); 
  9.  
  10.  
  11. 如果像如下,就能避免 
  12.  
  13. [java] 
  14. Uri uri = Uri.parse("mailto:"); 
  15. Intent intent = new Intent(Intent.ACTION_SENDTO, uri); 
  16. intent.putExtra(Intent.EXTRA_EMAIL, new String[] {"test@gmail.com"}); 
  17. startActivity(intent); 
  18.  
  19. Uri uri = Uri.parse("mailto:"); 
  20. Intent intent = new Intent(Intent.ACTION_SENDTO, uri); 
  21. intent.putExtra(Intent.EXTRA_EMAIL, new String[] {"test@gmail.com"}); 
  22. startActivity(intent); 

 

责任编辑:chenqingxiang
相关推荐

2022-07-07 09:00:00

区块链加密货币安全

2010-05-04 17:43:50

Unix系统

2015-07-06 09:52:40

2012-11-20 10:47:16

2011-05-26 15:22:57

Android Activity

2013-09-30 09:18:39

2019-04-04 11:55:59

2023-03-09 12:30:55

2022-08-30 18:46:24

安全软件开发测试软件

2016-10-24 14:04:24

2020-10-06 18:28:52

gosecGo代码安全

2020-10-30 08:50:25

2012-10-09 16:47:19

2016-03-01 11:44:57

2009-07-07 13:29:33

Servlet和JSP

2010-04-02 13:53:47

2013-03-12 09:22:32

2013-01-07 10:34:23

2009-05-30 09:36:18

2013-02-27 15:49:22

点赞
收藏

51CTO技术栈公众号