Skip to main content

古早安卓漏洞学习

·874 words·5 mins
ベーコン
Author
ベーコン
ljahum-beacon

本科生课件的一部分

最好有一部顺手的调试机

狠狠抄ref:https://bbs.kanxue.com/thread-273867.htm#msg_header_h2_2

版本2023版 Fastboot boot只做临时修改 Fastboot flash会直接写入,无法修稿

环境 #

1.新建空项目

Alt text

选择使用java编写

Alt text

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;
            }
        });

    }
}

Alt text

把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通手机和电脑?:

  1. Adb shell链接手机shell 查看网段

注意这里的 Mask:255.255.224.0,所以网段并不是172.26.239.x

Alt text

  1. 在cmd 敲下 ipconfig 本机在热点中的ip

Alt text

我们找一个文件夹,放我们写js用的html 用python -m http.server 8080把当前目录发布在默认的http端口

Alt text

然后用手机访问台式机的ip,可以看到目录下的文件,接下来我们用webview加载这个文件

Alt text

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;
            }

        });
    }
}

Alt text

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);
}

Alt text

跨域漏洞 #

现在基本没有这种好事了,但不同域之间的权限管理确实是经典的绕过思路

  • 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");

Alt text

  • 固定不变的 HTML 文件可以放在 assets 或 res 目录下,file:///android_asset 和 file:///android_res 在不开启 API 的情况下也可以访问;
  • 可能会更新的 HTML 文件放在 /data/data/(app) 目录下,避免被第三方替换或修改;
  • 对 file 域请求做白名单限制时,需要对“…/…/”特殊情况进行处理,避免白名单被绕过