古早安卓漏洞学习
Table of Contents
本科生课件的一部分
最好有一部顺手的调试机
狠狠抄ref:https://bbs.kanxue.com/thread-273867.htm#msg_header_h2_2
版本2023版 Fastboot boot只做临时修改 Fastboot flash会直接写入,无法修稿
环境 #
1.新建空项目
选择使用java编写
1 运行webview #
package com.example.myapplication;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.AndroidException;
import android.util.Log;
import android.webkit.JavascriptInterface;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WebView webView = (WebView) findViewById(R.id.Wind_webview);
// webView.loadUrl("http://www.baidu.com");
//系统默认会通过手机浏览器打开网页,为了能够直接通过WebView显示网页,则必须设置
webView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
});
}
}
把compileSdk = 33改成34
运行后 net:ERR_CLEARTEXT_NOT_PERMITTED报错 android:usesCleartextTraffic=“true” 添加到Manifest文件
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.MyApplication"
android:usesCleartextTraffic="true"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
app可以访问百度搜索
2 在页面上加载JavaScript脚本 #
package com.example.myapplication;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.AndroidException;
import android.util.Log;
import android.webkit.JavascriptInterface;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WebView webView = (WebView) findViewById(R.id.Wind_webview);
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webView.addJavascriptInterface(new AndroidtoJs(),"test");
webView.loadData("","text/html",null);
// webView.loadUrl("http://www.baidu.com");
webView.loadUrl("http://172.26.215.65:8080/attack.html");
//系统默认会通过手机浏览器打开网页,为了能够直接通过WebView显示网页,则必须设置
webView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
//使用WebView加载显示url
view.loadUrl(url);
//返回true
return true;
}
});
}
public class AndroidtoJs {
// 定义JS需要调用的方法,被JS调用的方法必须加入@JavascriptInterface注解
@JavascriptInterface
public void hello(String msg) {
Log.e("WindXaa","Hello," + msg);
}
}
}
本实验中使用手机连接台式机热点,最好保证一个相对真实的环境,实测模拟器不太好用
如何ping通手机和电脑?:
- Adb shell链接手机shell 查看网段
注意这里的 Mask:255.255.224.0,所以网段并不是172.26.239.x
- 在cmd 敲下 ipconfig 本机在热点中的ip
我们找一个文件夹,放我们写js用的html 用python -m http.server 8080把当前目录发布在默认的http端口
然后用手机访问台式机的ip,可以看到目录下的文件,接下来我们用webview加载这个文件
package com.example.myapplication;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.AndroidException;
import android.util.Log;
import android.webkit.JavascriptInterface;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WebView webView = (WebView) findViewById(R.id.Wind_webview);
// 设置可以使用JavaScript
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
//设置
webView.addJavascriptInterface(new AndroidtoJs(),"test");
webView.loadData("","text/html",null);
// webView.loadUrl("http://www.baidu.com");
webView.loadUrl("http://172.26.215.65:8080/attack.html");
//系统默认会通过手机浏览器打开网页,为了能够直接通过WebView显示网页,则必须设置
webView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
//使用WebView加载显示url
view.loadUrl(url);
//返回true
return true;
}
});
}
public class AndroidtoJs {
// 定义JS需要调用的方法,被JS调用的方法必须加入@JavascriptInterface注解
@JavascriptInterface
public void hello(String msg) {
Log.e("feed back","Hello," + msg);
}
}
}
Android or JavaScript? #
Android调用JS #
方法1 使用urlload
方法2 WebView.evaluateJavascript()不会刷新页面load会刷新页面
package com.example.myapplication;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import android.content.DialogInterface;
import android.os.Bundle;
import android.util.AndroidException;
import android.util.Log;
import android.view.View;
import android.webkit.JavascriptInterface;
import android.webkit.*;
//import android.webkit.WebChromeClient;
//import android.webkit.WebSettings;
//import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WebView webView = (WebView) findViewById(R.id.Wind_webview);
//初始化setting
WebSettings webSettings = webView.getSettings();
// 设置与Js交互的权限
// 设置允许JS弹窗
webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
webSettings.setJavaScriptEnabled(true);
//方法1 使用load去加载
webView.loadUrl("file:///android_asset/AndroJs.html");
//设置layour中的Button背按下后的反应
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 通过Handler发送消息
webView.post(new Runnable() {
@Override
public void run() {
// 注意调用的JS方法名要对应上
// 调用javascript的callJS()方法
// webView.loadUrl("javascript:callJS()");// 方法1
webView.evaluateJavascript("javascript:callJS()", new ValueCallback<String>() { // 方法二
@Override
public void onReceiveValue(String value) {
Log.i("js", "调用成功了?"+value);
//此处为 js 返回的结果
}
});
}
});
}
});
// 由于设置了弹窗检验调用结果,所以需要支持js对话框
// webview只是载体,内容的渲染需要使用webviewChromClient类去实现
// 通过设置WebChromeClient对象处理JavaScript的对话框
//设置响应js 的Alert()函数
webView.setWebChromeClient(new WebChromeClient() {
@Override
public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
AlertDialog.Builder b = new AlertDialog.Builder(MainActivity.this);
// 设置标题和内容
b.setTitle("Alert");
b.setMessage(message);
// 设置确定按钮及其点击事件:
b.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// 点击该按钮时调用result.confirm(),通知JavaScript代码继续执行。
result.confirm();
}
});
// 确保用户必须点击确定按钮才能关闭对话框,防止用户意外关闭对话框导致JavaScript代码中断
// 没有这个的话 按返回上级或者返回桌面 会导致js代码被中断
b.setCancelable(false);
b.create().show();
return true;
}
});
}
}
layout文件 Activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<WebView
android:id="@+id/Wind_webview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/button" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Call JS"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
tools:ignore="MissingConstraints" />
<!-- <TextView-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:text="Hello World!"-->
<!-- app:layout_constraintBottom_toBottomOf="parent"-->
<!-- app:layout_constraintEnd_toEndOf="parent"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toTopOf="parent" />-->
</androidx.constraintlayout.widget.ConstraintLayout>
Load的html文件 AndroJs.html
<html>
<head>
<meta charset="utf-8">
<title>测试</title>
<script>
function callJS(){
alert("Android调用了JS的callJS方法");
}
</script>
</head>
<body>
<h1>Android调用JS方法测试</h1>
</body>
</html>
js调用Android #
方法:那Android中的对象映射到JavaScript
Html文件
//JS调用Android
<html>
<head>
<meta charset="utf-8">
<title>Carson</title>
<script>
function callAndroid(){
//由于对象映射,所以调用test对象等于调用Android映射的对象
test.hello("WindXaa js调用了android中的hello方法");
}
</script>
</head>
<body>
<!--点击按钮则调用callAndroid函数-->
<button type="button" id="button1" onclick="callAndroid()">Click Attack</button>
</body>
</html>
main_activity
package com.example.myapplication;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import android.content.DialogInterface;
import android.os.Bundle;
import android.util.AndroidException;
import android.util.Log;
import android.view.View;
import android.webkit.JavascriptInterface;
import android.webkit.*;
//import android.webkit.WebChromeClient;
//import android.webkit.WebSettings;
//import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//activity_js_to_andro可以直接把之前layout里面的button删掉
//是一样的
setContentView(R.layout.activity_js_to_andro);
WebView webView = (WebView) findViewById(R.id.Wind_webview1);
//初始化setting
WebSettings webSettings = webView.getSettings();
// 设置与Js交互的权限
// 设置允许JS弹窗
webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
webSettings.setJavaScriptEnabled(true);
//2.将方法映射到test对象
webView.addJavascriptInterface(new AndroidtoJs(), "test");
//3. 加载js文件
webView.loadUrl("file:///android_asset/javascript.html");
}
//1.编写给js用的class
public class AndroidtoJs {
// 定义JS需要调用的方法,被JS调用的方法必须加入@JavascriptInterface注解
@JavascriptInterface
public void hello(String msg) {
Log.e("WindXaa","Hello," + msg);
}
}
}
显示js直接调用 js向Android传参,参数由Android重写相关方法来截断 #
// 复写WebViewClient类的shouldOverrideUrlLoading方法
mWebView.setWebChromeClient(new WebChromeClient() {
// Android通过 WebChromeClient 的onJsAlert()、onJsConfirm()、onJsPrompt()方法回调分别拦截JS对话框
@Override
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
// 根据协议的参数,判断是否是所需要的url(原理同方式2)
// 一般根据scheme(协议格式) & authority(协议名)判断(前两个参数)
Uri uri = Uri.parse(message);
// 如果url的协议 = 预先约定的 js 协议
// 就解析往下解析参数
if (uri.getScheme().equals("js")) {
//js://webview?arg1=WindXaa&arg2=attack
// 如果 authority = 预先约定协议里的 webview,即代表都符合约定的协议
// 所以拦截url,下面JS开始调用Android需要的方法
if (uri.getAuthority().equals("webview")) {
// 执行JS所需要调用的逻辑
System.out.println("js调用了Android的方法");
// 可以在协议上带有参数并传递到Android上
HashMap<String, String> params = new HashMap<>();
Set<String> collection = uri.getQueryParameterNames();
//参数result:代表消息框的返回值(输入值)
result.confirm("js调用了Android的方法成功啦");
}
return true;
}
return super.onJsPrompt(view, url, message, defaultValue, result);
}
}
);
function clickprompt(){
// 调用prompt()
var result=prompt("js://webview?arg1=WindXaa&arg2=attack");
alert("demo " + result);
}
跨域漏洞 #
现在基本没有这种好事了,但不同域之间的权限管理确实是经典的绕过思路
- setAllowUniversalAccessFromFileURLs 允许从文件 URL 访问其他文件 URL。
- setAllowFileAccessFromFileURLs 允许从文件 URL 访问文件系统。
任意文件,页面读 跨域漏洞去访问本地的私有目录 setAllowFileAccess(true) + setAllowFileAccessFromFileURLs(true) Html
<script>
function loadXMLDoc()
{
var arm = "file:///etc/hosts";
var xmlhttp;
if (window.XMLHttpRequest)
{
xmlhttp=new XMLHttpRequest();
}
xmlhttp.onreadystatechange=function()
{
//alert("status is"+xmlhttp.status);
if (xmlhttp.readyState==4)
{
console.log(xmlhttp.responseText);
}
}
xmlhttp.open("GET",arm);
xmlhttp.send(null);
}
loadXMLDoc();
</script>
Java
用
WebView mWebView = (WebView) findViewById(R.id.Wind_webview1);
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setAllowFileAccess(true);
// 换成setAllowFileAccessFromFileURLs可以访问http网页
webSettings.setAllowFileAccessFromFileURLs(true);
mWebView.loadUrl("file:///data/local/tmp/fileAttack.html");
- 固定不变的 HTML 文件可以放在 assets 或 res 目录下,file:///android_asset 和 file:///android_res 在不开启 API 的情况下也可以访问;
- 可能会更新的 HTML 文件放在 /data/data/(app) 目录下,避免被第三方替换或修改;
- 对 file 域请求做白名单限制时,需要对“…/…/”特殊情况进行处理,避免白名单被绕过