安卓开发,关于代码安全的注意点,平常开发中你有没有注意!!!

发扬分享精神,做一个快乐的开发者!

看CSDN有好长时间了,感谢那些善于分享的开发者,感谢你们 ,阅读你们的文章,我感觉有很快的进步,我一直也想写博客,把自己的见解和大家分享,只是苦于不知道写些什么,现在机会来了,我要把我研究的一些关于代码安全的试题给大家分享一下,其中参考了很多的网上资源,也有很多自己的理解,可能会有一些偏差,希望大家能够指正.

1,关于安卓的剪切板风险.
手机里面的几乎所有的程序都能访问剪切板,甚至一些权限不高的APP都可以通过剪贴板功能获取我们复制或者剪切的信息。如果我们复制或者剪切账户密码信息,很容易就被嗅探泄密,原因是Android剪贴板的内容向任何权限的app开放 .如果是明文内容将会有信息泄露的风险,

首先可能有的人不是很熟悉,安卓的剪切板,我在先说一下安卓剪切板的用法.

1,先获取一个Manger的对象,和获取大多管理服务一样,在上下文的环境中调用 getSystemService(CLIPBOARD_SERVICE);获取一个剪切板管理器对象 取名为manager ,强转成ClipboardManager;

2.现在有一个管理器对象了,还有有一个存放剪切的内容的地方就是ClipData,这个对象不是new出来的而是通过静态方法ClipData.newPlainText(CharSequence label, CharSequence text),
ClipData.newIntent(CharSequence label, Intent intent),
ClipData.newUri(ContentResolver resolver, CharSequence label,
Uri uri) 获得的,分别对应存储的三种类型的数据: 文本,Intent,URL.
这里我以复制密码为例 :

// 剪切板数据
        ClipData clip = ClipData.newPlainText("password", "helloworld123456");

3.现在剪切板管理对象有了,数据对象也有了,就把数据通过manager放进剪切板里面.

manager.setPrimaryClip(clip);

现在剪切板就使用完成了,这里我模拟复制了密码,现在剪切板里面的内容可以别任意APP读取,可想而知,这里应该是代码安全的注意点.

现在我们看一下如何读取剪切板的数据
如下代码可以在任意APP中读取剪切板的文字内容:

ClipboardManager cm = (ClipboardManager)getSystemService(CLIPBOARD_SERVICE);
    ClipData cd2 = cm.getPrimaryClip();
    str2 = cd2.getItemAt(0).getText().toString();

修改方法:
使用完clipboard及时清空,并避免使用剪贴板明文存储敏感信息
我找了API但是没有找到清空的方法,这里我们可以这样给他清空

ClipData data = ClipData.newPlainText("password", "");
        manager.setPrimaryClip(data);

一句话 : 使用安卓剪切板的时候注意清空,并避免使用剪贴板明文存储敏感信息!!!!

2. 关于安卓随机数风险

安卓使用SecureRandom代码。

    SecureRandom secureRandom = new SecureRandom();

        byte[] b = new byte[] { (byte) 1 };
        //种子一样 每次生成的随机数是一样的  设置了自己的种子 代替的系统的种子
        secureRandom.setSeed(b);
        // Prior to Android 4.2, the next line would always return the same
        // number!
        for (int i = 0; i < 30; i++) {

            System.out.println(secureRandom.nextInt());
        }

java中还有一个 Random 类 基本类似.

解析:
在Android 4.2以下,SecureRandom是基于老版的Bouncy Castle实现的。如果生成SecureRandom对象后马上调用setSeed方法。SecureRandom会用用户设置的seed代替默认的随机源。使得每次生成随机数时都是会使用相同的seed作为输入。从而导致生成的随机数是相同的。

解决方法:
1.不要使用自定义随机源代替系统默认随机源(推荐)除非有特殊需求.
2.在使用SecureRandom类时,不要调用这个构造函数
SecureRandom(byte[] seed)
3.不要调用这些设置种子的方法:

setSeed(long seed)
setSeed(byte[] seed)

4.可以在在调用setSeed方法前先调用任意nextXXX方法,可以通过nextBytes(byte[] bytes)避免这个问题。具体做法是调用setSeed方法前先调用一次nextBytes(byte[] bytes)方法。

3.安卓BroadCastReceiver安全风险

代码描述 : 安卓manifest.xml中广播注册代码。
代码:

<receiver android:name="com.baroad.demo.MyBroadCastReceiver" >  
     <intent-filter >  
     <action android:name="com.demo.action"/>  
     </intent-filter>  
     </receiver> 

解析:
BroadCastReceiver是Android 四大组件之一,应用非常广泛,也非常简单,但是我们平时在使用的过程中忽略了一个安全问题。别人很容易通过反编译获取到我们应用中的广播,然后频繁的向你的App中发送广播,那么如何避免应用中注册的广播响应其他应用发送的广播呢,对于显示的广播除非是别人故意攻击,一般很少出现响应别人的广播,但是对于隐式的广播就很容易出现上述问题,因为action很容易是一样的,一旦是一样的就出问题了.
修改方法:
1、在自己的应用中,在manifest.xml中注册receiver的时候加入export属性,android:exported=”false”。

ps: android:exported 是Android中的四大组件 Activity,Service,Provider,Receiver 四大组件中都会有的一个属性。来表示是否允许跨进程调用,即该组件能不能被其他应用调用.默认值:如果包含有intent-filter 默认值为true; 没有intent-filter默认值为false。

2、 自定义权限,在manifest.xml中加入自定义权限,然后再响应的BroadCastReceiver中加入这个权限即可,在发送广播时将权限作为参数一同发出,接收方在配置文件里添加相应的权限

 //自定义一个权限
<permission   
android:name="com.sdkj.permission.STARTBROAD"    
android:protectionLevel="normal"/>


<receiver android:name="com.baroad.demo.MyBroadCastReceiver"          android:permission="com.sdkj.permission.STARTBROAD">  
   <intent-filter >  
       <action android:name="com.demo.action"/>  
   </intent-filter>
  </receiver>

千万不要忘记加入权限

<uses-permission android:name="com.sdkj.permission.STARTBROAD"/>

发送广播时 :

    public void button(View view) {
        Intent intent = new Intent();
        intent.setAction("com.demo.action");
        sendBroadcast(intent,"com.sdkj.permission.STARTBROAD");
    }

这样第三方应用只能获得相应的权限后才可以对B发送消息;

谷歌推荐使用第一种
3 安卓应用截屏安全风险

解析:我们开发程序的地方可能有的地方不想让用户截屏,或者不想让其他程序为我们截屏,需要注意的地方

解决:
加入一行代码就可以解决:
this.getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
这样就能防止应用截屏了

4 Database配置模式安全风险

代码描述:安卓数据库创建代码。
代码:

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
try {
database = openOrCreateDatabase("login.db",
    Context.MODE_WORLD_READABLE, null);
database.execSQL(CREATE_TABLE);   
} catch (SQLiteException e) {
 e.printStackTrace();
} 
et_name = (EditText) findViewById(R.id.et_name);
et_password = (EditText) findViewById(R.id.et_password);
btn_login = (Button) findViewById(R.id.btn_login);

解析:
Database配置模式安全风险源于:1)开发者在创建数据库(Database)时没有正确的选取合适的创建模式(MODE_PRIVATE、MODE_WORLD_READABLE以及MODE_WORLD_WRITEABLE)进行权限控制,从而导致数据库(Database)内容被恶意读写,造成账户密码、身份信息、以及其他敏感信息的泄露,甚至攻击者进一步实施恶意攻击。
如果在开发中没有使用正确的创建模式数据库(Database)文件,将会导致敏感信息泄露危害,如个人账户密码、身份信息以及金融账户等重要敏感信息。
**修改方法:
避免使用MODE_WORLD_WRITEABLE和MODE_WORLD_READABLE模式创建数据库(Database),权限不要开方太大,安全建议不要使用全局可读模式和全局可写模式创建数据库;**

* 5 安卓LogCat安全风险

代码描述:LogCat打印敏感调试信息。

解析:
Logcat是我们开发中最常用的了,用它打印信息,看程序是否执行到了这里,和输出一些信息帮助我们开发程序,可是我们在打印的过程中,常常可能会打印一些关键的信息,如用户名,密码,接获取到有价值的隐私敏感信息。.还有可能会让攻击者更加容易了解APP内部结构,方便破解和攻击.

修改方法:
禁止隐私信息的log,设置布尔值来控制打印信息,或者使用ProGuard等工具在APP的发行版本(release)中自动删除Log.d()和Log.v()对应的代码.

6 安卓debuggable安全风险

代码描述:安卓manifest.xml文件功能代码。

 <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" 
        android:debuggable="true">

解析:
android:debuggable=”true”应用存在debug调试风险
debuggable 属性有两个值“true|false”;
只有Android:debuggable=”true”时我们才可以在手机上调试Android程序。
但是当我们没在AndroidManifest.xml中设置其debug属性时:
使用Eclipse运行这种方式打包时其debug属性为true,使用Eclipse导出这种方式打包时其debug属性为法false.
在使用ant打包时,其值就取决于ant的打包参数是release还是debug.

7 SharedPreferences存储数据
解析:
在保存特殊数据时,没有对特殊数据进行加密处理,存在数据信息泄漏风险。开放的权限不要太大.

修改:
1.将Context.MODE_WORLD_READABLE改为Context.MODE_PRIVATE
Context.MODE_WORLD_READABLE:表示当前文件可以被其他应用读取。
Context.MODE_PRIVATE:表示当前文件为默认操作模式,代表该文件是私有数据,只能被应用本身访问。
2.对存储的数据采用MD5方式加密

ps :
MD5算法具有以下特点:
1、压缩性:任意长度的数据,算出的MD5值长度都是固定的。
2、容易计算:从原数据计算出MD5值很容易。
3、抗修改性:对原数据进行任何改动,哪怕只修改1个字节,所得到的MD5值都有很大区别。
4、强抗碰撞:已知原数据和其MD5值,想找到一个具有相同MD5值的数据(即伪造数据)是非常困难的。
5、不可逆性:知道MD5值不会得到原数据.

public static String encrypt(String data, String mode) throws Exception {
MessageDigest md5 = MessageDigest.getInstance(mode);
md5.update(data.getBytes());
byte[] digest = md5.digest();
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i < digest.length; i++) {
int val = ((int) digest[i]) & 0xff;
if (val < 16) {
stringBuffer.append("0");
}
stringBuffer.append(Integer.toHexString(digest[i]& 0xff));
}
return stringBuffer.toString();
}

先写这么多吧,写了一下午昏昏涨涨的,第一次写博客,全是个人理解,如果有不对的地方,欢迎你的指正,如果有不明白的地方,乐于为你解答.如果有侵犯的地方,请联系我,会立即删除.
做一个快乐的善于分享的开发者!

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值