189 8069 5689

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

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

创新互联-专业网站定制、快速模板网站建设、高性价比嘉定网站开发、企业建站全套包干低至880元,成熟完善的模板库,直接使用。一站式嘉定网站制作公司更省心,省钱,快速模板网站建设找我们,业务覆盖嘉定地区。费用合理售后完善,十多年实体公司更值得信赖。

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

 
 
  1. android:name=".PrivateActivity" 
  2. android:label="@string/app_name" 
  3. android:exported="false" /> 
  4.  
  5. android:name=".PrivateActivity" 
  6. android:label="@string/app_name" 
  7. 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.  
  3. android:taskAffinity="com.winuxxan.task" 
  4. android:label="@string/app_name"> 
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11.  
  12.  
  13.  
  14.  
  15. android:taskAffinity="com.winuxxan.task" 
  16. android:label="@string/app_name"> 
  17.  
  18.  
  19.  
  20.  
  21.  
  22.  
  23.  
  24.  

 

那此时,恶意软件中的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.  
  5. package="org.jssec.android.activity.privateactivity" 
  6. android:versionCode="1" 
  7. android:versionName="1.0" > 
  8.  
  9. android:icon="@drawable/ic_launcher" 
  10. android:label="@string/app_name" > 
  11.  
  12.  
  13. android:name=".PrivateUserActivity" 
  14. android:label="@string/app_name" 
  15. android:launchMode="singleInstance" > 
  16.  
  17.  
  18.  
  19.  
  20.  
  21.  
  22.  
  23.  
  24. android:name=".PrivateActivity" 
  25. android:label="@string/app_name" 
  26. android:exported="false" /> 
  27.  
  28.  
  29.  
  30.  
  31. package="org.jssec.android.activity.privateactivity" 
  32. android:versionCode="1" 
  33. android:versionName="1.0" > 
  34.  
  35. android:icon="@drawable/ic_launcher" 
  36. android:label="@string/app_name" > 
  37.  
  38.  
  39. android:name=".PrivateUserActivity" 
  40. android:label="@string/app_name" 
  41. android:launchMode="singleInstance" > 
  42.  
  43.  
  44.  
  45.  
  46.  
  47.  
  48.  
  49.  
  50. android:name=".PrivateActivity" 
  51. android:label="@string/app_name" 
  52. android:exported="false" /> 
  53.  
  54.  

 

非公开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.  
  18. public void onReturnResultClick(View view) { 
  19. Intent intent = new Intent(); 
  20. intent.putExtra("RESULT", 机密数据"); 
  21. setResult(RESULT_OK, intent); 
  22. finish(); 
  23. } 
  24. } 
  25.  
  26. package org.jssec.android.activity.privateactivity; 
  27. import android.app.Activity; 
  28. import android.content.Intent; 
  29. import android.os.Bundle; 
  30. import android.view.View; 
  31. import android.widget.Toast; 
  32. public class PrivateActivity extends Activity { 
  33. @Override 
  34. public void onCreate(Bundle savedInstanceState) { 
  35. super.onCreate(savedInstanceState); 
  36. setContentView(R.layout.private_activity); 
  37. String param = getIntent().getStringExtra("PARAM"); 
  38. Toast.makeText(this, String.format("「%s」取得。", param), 
  39. Toast.LENGTH_LONG).show(); 
  40. } 
  41.  
  42. public void onReturnResultClick(View view) { 
  43. Intent intent = new Intent(); 
  44. intent.putExtra("RESULT", 机密数据"); 
  45. setResult(RESULT_OK, intent); 
  46. finish(); 
  47. } 
  48. } 

 

调用非公开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.  
  17. public void onUseActivityClick(View view) { 
  18. // 用standard模式启动非公开Activity 
  19. Intent intent = new Intent(); 
  20. intent.setClass(this, PrivateActivity.class); 
  21. intent.putExtra("PARAM", "机密数据"); 
  22. startActivityForResult(intent, REQUEST_CODE); 
  23. } 
  24.  
  25. @Override 
  26. public void onActivityResult(int requestCode, int resultCode, 
  27. Intent data) { 
  28. super.onActivityResult(requestCode, resultCode, data); 
  29. if (resultCode != RESULT_OK) 
  30. return; 
  31. switch (requestCode) { 
  32. case REQUEST_CODE: 
  33. String result = data.getStringExtra("RESULT"); 
  34. break; 
  35. } 
  36. } 
  37. } 
  38.  
  39. package org.jssec.android.activity.privateactivity; 
  40. import android.app.Activity; 
  41. import android.content.Intent; 
  42. import android.os.Bundle; 
  43. import android.view.View; 
  44. import android.widget.Toast; 
  45. public class PrivateUserActivity extends Activity { 
  46. private static final int REQUEST_CODE = 1; 
  47.  
  48. @Override 
  49. public void onCreate(Bundle savedInstanceState) { 
  50. super.onCreate(savedInstanceState); 
  51. setContentView(R.layout.user_activity); 
  52. } 
  53.  
  54. public void onUseActivityClick(View view) { 
  55. // 用standard模式启动非公开Activity 
  56. Intent intent = new Intent(); 
  57. intent.setClass(this, PrivateActivity.class); 
  58. intent.putExtra("PARAM", "机密数据"); 
  59. startActivityForResult(intent, REQUEST_CODE); 
  60. } 
  61.  
  62. @Override 
  63. public void onActivityResult(int requestCode, int resultCode, 
  64. Intent data) { 
  65. super.onActivityResult(requestCode, resultCode, data); 
  66. if (resultCode != RESULT_OK) 
  67. return; 
  68. switch (requestCode) { 
  69. case REQUEST_CODE: 
  70. String result = data.getStringExtra("RESULT"); 
  71. break; 
  72. } 
  73. } 
  74. } 

 

 

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

 

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

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

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

 

 

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); 

本文标题:Android开发中的若干安全问题之Activity篇
文章地址:http://ptruijie.cn/article/djposid.html

其他资讯