Android Logcat Security
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
/tips/?id=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的資訊如下:
- 目標包名
- 目標類名
- intent.setData(URL)的URL
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: 杭州銀行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
相關文章
- Android Activtity Security2020-08-19Android
- Android Service Security2020-08-19Android
- Android Broadcast Security2020-08-19AndroidAST
- Logcat filter2024-09-26GCFilter
- Android Content Provider Security2020-08-19AndroidIDE
- 用adb logcat抓取log2018-07-24GC
- 如何優雅的結束 adb logcat??2020-11-12GC
- 安卓應用安全指南4.8輸出到LogCat2018-03-24安卓GC
- logcat 引數的一些疑惑,求大佬指教2020-06-24GC
- Spring Security2022-05-01Spring
- Spring Security原始碼分析八:Spring Security 退出2019-03-02Spring原始碼
- 解決 AS 3.1.0 版本 Logcat 合併多條日誌的問題2019-03-03GC
- Spring Security原始碼分析九:Spring Security Session管理2019-03-04Spring原始碼Session
- Security, Privacy and Ethics2024-11-29
- Spring Security(8)2022-12-01Spring
- Spring Security(6)2022-11-27Spring
- Spring Security(7)2022-11-29Spring
- Spring Security + JWT2022-12-21SpringJWT
- 1.1.2 Security Officers2020-02-20
- Content Security Policy2020-09-03
- Rails Security (上)2020-08-19AI
- spring security(一)2020-12-13Spring
- 初探Spring Security2021-08-29Spring
- Spring Security 上2021-05-06Spring
- Spring Security(二)2019-01-11Spring
- Spring Boot Security2018-06-08Spring Boot
- [Information Security] What is WEP2022-11-24ORM
- Spring Boot —— Spring Security2024-05-22Spring Boot
- Web-Security-Learning2020-05-24Web
- 41. The Security Namespace2020-08-16namespace
- A Security Analysis Of Browser Extensions2020-08-19
- SpringBoot整合Spring Security2020-09-19Spring Boot
- [譯]Spring Security Architecture2019-04-21Spring
- Spring Security進階2021-09-05Spring
- Spring Security OAuth 2.02021-08-28SpringOAuth
- Spring Security詳解2021-04-27Spring
- Shrio(Simple,Java,Security)2018-08-14Java
- 如何從Spring Security 5遷移到Spring Security 6/Spring Boot 32024-03-12Spring Boot