<pre id="vvttv"><mark id="vvttv"><progress id="vvttv"></progress></mark></pre>
    <pre id="vvttv"></pre>

      <p id="vvttv"></p>

          <p id="vvttv"></p>

                <p id="vvttv"></p>

                <pre id="vvttv"><cite id="vvttv"><progress id="vvttv"></progress></cite></pre>

                  <output id="vvttv"><dfn id="vvttv"><th id="vvttv"></th></dfn></output>

                    <p id="vvttv"></p>

                    原文地址:http://drops.wooyun.org/tips/3812

                    0x00 科普


                    development version :開發版,正在開發內測的版本,會有許多調試日志。

                    release version : 發行版,簽名后開發給用戶的正式版本,日志量較少。

                    android.util.Log:提供了五種輸出日志的方法

                    Log.e(), Log.w(), Log.i(), Log.d(), Log.v()

                    ERROR, WARN, INFO, DEBUG, VERBOSE

                    android.permission.READ_LOGS:app讀取日志權限,android 4.1之前版本通過申請READ_LOGS權限就可以讀取其他應用的log了。但是谷歌發現這樣存在安全風險,于是android 4.1以及之后版本,即使申請了READ_LOGS權限也無法讀取其他應用的日志信息了。4.1版本中 Logcat的簽名變為“signature|system|development”了,這意味著只有系統簽名的app或者root權限的app才能使用該權限。普通用戶可以通過ADB查看所有日志。

                    0x01 測試


                    測試方法是非常簡單的,可以使用sdk中的小工具monitor或者ADT中集成的logcat來查看日志,將工具目錄加入環境變量用起來比較方便。當然如果你想更有bigger也可以使用adb logcat。android整體日志信息量是非常大的,想要高效一些就必須使用filter來過濾一些無關信息,filter是支持正則的,可以做一些關鍵字匹配比如password、token、email等。本來準備想做個小工具自動化收集,但是覺得這東西略雞肋沒太大必要,故本文的重點也是在如何安全的使用logcat方面。

                    當然也可以自己寫個app在直接在手機上抓取logcat,不過前面提到因為android系統原因如果手機是android4.1或者之后版本即使在manifest.xml中加入了如下申請也是無法讀取到其他應用的log的。

                    <uses-permission android:name="android.permission.READ_LOGS"/>
                    

                    root權限可以隨便看logcat,所以“logcat信息泄露”漏洞因谷歌在4.1上的動作變得很雞肋了。

                    0x02 smali注入logcat


                    http://drops.wooyun.org/tips/2986 一文中提到將敏感數據在加密前打印出來就是利用靜態smali注入插入了logcat方法。 使用APK改之理smali注入非常方便,但要注意隨意添加寄存器可能破壞本身邏輯,新手建議不添加寄存器直接使用已有的寄存器。

                    invoke-static {v0, v0}, Landroid/util/Log;->e(Ljava/lang/String;Ljava/lang/String;)I
                    

                    0x03 建議


                    有些人認為任何log都不應該在發行版本打印。但是為了app的錯誤采集,異常反饋,必要的日志還是要被輸出的,只要遵循安全編碼規范就可以將風險控制在最小范圍。

                    Log.e()/w()/i():建議打印操作日志

                    Log.d()/v():建議打印開發日志

                    1、敏感信息不應用Log.e()/w()/i(), System.out/err 打印。

                    2、如果需要打印一些敏感信息建議使用 Log.d()/v()。(前提:release版本將被自動去除)

                    @Override
                    public void onCreate(Bundle savedInstanceState) {
                    super.onCreate(savedInstanceState);
                    setContentView(R.layout.activity_proguard);
                    // *** POINT 1 *** Sensitive information must not be output by Log.e()/w()/i(), System.out/err.
                    Log.e(LOG_TAG, "Not sensitive information (ERROR)");
                    Log.w(LOG_TAG, "Not sensitive information (WARN)");
                    Log.i(LOG_TAG, "Not sensitive information (INFO)");
                    // *** POINT 2 *** Sensitive information should be output by Log.d()/v() in case of need.
                    // *** POINT 3 *** The return value of Log.d()/v()should not be used (with the purpose of substitution or comparison).
                    Log.d(LOG_TAG, "sensitive information (DEBUG)");
                    Log.v(LOG_TAG, "sensitive information (VERBOSE)");
                    }
                    

                    3、Log.d()/v()的返回值不應被使用。(僅做開發調試觀測)

                    Examination code which Log.v() that is specifeied to be deleted is not deketed

                    int i = android.util.Log.v("tag", "message");
                    System.out.println(String.format("Log.v() returned %d. ", i)); //Use the returned value of Log.v() for examination
                    

                    4、release版apk實現自動刪除Log.d()/v()等代碼。

                    eclipse中配置ProGuard

                    開發版所有log都打印出來了。

                    發行版ProGuard移除了d/v的log

                    反編譯后查看確實被remove了

                    5、公開的APK文件應該是release版而不是development版。

                    0x04 native code


                    android.util.Log的構造函數是私有的,并不會被實例化,只是提供了靜態的屬性和方法。 而android.util.Log的各種Log記錄方法的實現都依賴于native的實現println_native(),Log.v()/Log.d()/Log.i()/Log.w()/Log.e()最終都是調用了println_native()。

                    Log.e(String tag, String msg)

                    public static int v(String tag, String msg) {
                        return println_native(LOG_ID_MAIN, VERBOSE, tag, msg);
                    }
                    

                    println_native(LOG_ID_MAIN, VERBOSE, tag, msg)

                    /*
                     * In class android.util.Log:
                     *  public static native int println_native(int buffer, int priority, String tag, String msg)
                     */
                    static jint android_util_Log_println_native(JNIEnv* env, jobject clazz,
                        jint bufID, jint priority, jstring tagObj, jstring msgObj)
                    {
                    const char* tag = NULL;
                    const char* msg = NULL;
                    
                    if (msgObj == NULL) {
                        jniThrowNullPointerException(env, "println needs a message");
                        return -1;
                    }
                    
                    if (bufID < 0 || bufID >= LOG_ID_MAX) {
                        jniThrowNullPointerException(env, "bad bufID");
                        return -1;
                    }
                    
                    if (tagObj != NULL)
                        tag = env->GetStringUTFChars(tagObj, NULL);
                    msg = env->GetStringUTFChars(msgObj, NULL);
                    
                    int res = __android_log_buf_write(bufID, (android_LogPriority)priority, tag, msg);
                    
                    if (tag != NULL)
                        env->ReleaseStringUTFChars(tagObj, tag);
                    env->ReleaseStringUTFChars(msgObj, msg);
                    
                    return res;
                    }
                    

                    其中__android_log_buf_write()又調用了write_to_log函數指針。

                    static int __write_to_log_init(log_id_t log_id, struct iovec *vec, size_t nr)
                    {
                    #ifdef HAVE_PTHREADS
                        pthread_mutex_lock(&log_init_lock);
                    #endif
                    
                        if (write_to_log == __write_to_log_init) {
                            log_fds[LOG_ID_MAIN] = log_open("/dev/"LOGGER_LOG_MAIN, O_WRONLY);
                            log_fds[LOG_ID_RADIO] = log_open("/dev/"LOGGER_LOG_RADIO, O_WRONLY);
                            log_fds[LOG_ID_EVENTS] = log_open("/dev/"LOGGER_LOG_EVENTS, O_WRONLY);
                            log_fds[LOG_ID_SYSTEM] = log_open("/dev/"LOGGER_LOG_SYSTEM, O_WRONLY);
                    
                            write_to_log = __write_to_log_kernel;
                    
                            if (log_fds[LOG_ID_MAIN] < 0 || log_fds[LOG_ID_RADIO] < 0 ||
                                log_fds[LOG_ID_EVENTS] < 0) {
                                log_close(log_fds[LOG_ID_MAIN]);
                                log_close(log_fds[LOG_ID_RADIO]);
                                log_close(log_fds[LOG_ID_EVENTS]);
                                log_fds[LOG_ID_MAIN] = -1;
                                log_fds[LOG_ID_RADIO] = -1;
                                log_fds[LOG_ID_EVENTS] = -1;
                                write_to_log = __write_to_log_null;
                            }
                    
                            if (log_fds[LOG_ID_SYSTEM] < 0) {
                                log_fds[LOG_ID_SYSTEM] = log_fds[LOG_ID_MAIN];
                            }
                        }
                    
                    #ifdef HAVE_PTHREADS
                        pthread_mutex_unlock(&log_init_lock);
                    #endif
                    
                        return write_to_log(log_id, vec, nr);
                    }
                    

                    總的來說println_native()的操作就是打開設備文件然后寫入數據。

                    0x05 其他注意



                    1、使用Log.d()/v()打印異常對象。(如SQLiteException可能導致sql注入的問題)

                    2、使用android.util.Log類的方法輸出日志,不推薦使用System.out/err

                    3、使用BuildConfig.DEBUG ADT的版本不低于21

                    public final static boolean DEBUG = true;
                    

                    在release版本中會被自動設置為false

                    if (BuildConfig.DEBUG) android.util.Log.d(TAG, "Log output information");
                    

                    4、啟動Activity的時候,ActivityManager會輸出intent的信息如下:

                    5、即使不用System.out/err程序也有可能輸出相關信息,如使用 Exception.printStackTrace()

                    6、ProGuard不能移除如下log:("result:" + value).

                    Log.d(TAG, "result:" + value);
                    

                    當遇到此類情況應該使用BulidConfig(注意ADT版本)

                    if (BuildConfig.DEBUG) Log.d(TAG, "result:" + value);
                    

                    7、不應將日志輸出到sdscard中,這樣會讓日志變得全局可讀

                    0x06 烏云案例


                    WooYun: 途牛網app logcat信息泄露用戶的同團聊的聊天內容

                    WooYun: 沖浪瀏覽器locat出用戶短信

                    WooYun: 杭州銀行Android客戶端登錄賬號密碼信息本地泄露

                    0x07 日志工具類

                    #!java
                    import android.util.Log;  
                    
                    /** 
                     * Log統一管理類 
                     *  
                     *  
                     *  
                     */ 
                    public class L  
                    {  
                    
                        private L()  
                        {  
                            /* cannot be instantiated */ 
                            throw new UnsupportedOperationException("cannot be instantiated");  
                        }  
                    
                        public static boolean isDebug = true;// 是否需要打印bug,可以在application的onCreate函數里面初始化  
                        private static final String TAG = "way";  
                      // 下面四個是默認tag的函數  
                        public static void i(String msg)  
                        {  
                            if (isDebug)  
                                Log.i(TAG, msg);  
                        }  
                    
                        public static void d(String msg)  
                        {  
                            if (isDebug)  
                                Log.d(TAG, msg);  
                        }  
                    
                        public static void e(String msg)  
                        {  
                            if (isDebug)  
                                Log.e(TAG, msg);  
                        }  
                    
                        public static void v(String msg)  
                        {  
                            if (isDebug)  
                                Log.v(TAG, msg);  
                        }  
                     // 下面是傳入自定義tag的函數  
                        public static void i(String tag, String msg)  
                        {  
                            if (isDebug)  
                                Log.i(tag, msg);  
                        }  
                    
                        public static void d(String tag, String msg)  
                        {  
                            if (isDebug)  
                                Log.i(tag, msg);  
                        }  
                    
                        public static void e(String tag, String msg)  
                        {  
                            if (isDebug)  
                                Log.i(tag, msg);  
                        }  
                    
                        public static void v(String tag, String msg)  
                        {  
                            if (isDebug)  
                                Log.i(tag, msg);  
                        }  
                    }
                    

                    0x08 參考


                    http://www.jssec.org/dl/android_securecoding_en.pdf

                    http://source.android.com/source/code-style.html#log-sparingly

                    http://developer.android.com/intl/zh-cn/reference/android/util/Log.html

                    http://developer.android.com/intl/zh-cn/tools/debugging/debugging-log.html

                    http://developer.android.com/intl/zh-cn/tools/help/proguard.html

                    https://www.securecoding.cert.org/confluence/display/java/DRD04-J.+Do+not+log+sensitive+information

                    https://android.googlesource.com/platform/frameworks/base.git/+/android-4.2.2_r1/core/jni/android_util_Log.cpp

                      <pre id="vvttv"><mark id="vvttv"><progress id="vvttv"></progress></mark></pre>
                      <pre id="vvttv"></pre>

                        <p id="vvttv"></p>

                            <p id="vvttv"></p>

                                  <p id="vvttv"></p>

                                  <pre id="vvttv"><cite id="vvttv"><progress id="vvttv"></progress></cite></pre>

                                    <output id="vvttv"><dfn id="vvttv"><th id="vvttv"></th></dfn></output>

                                      <p id="vvttv"></p>

                                      这里只有精品视频