Kategori OWASP: MASVS-STORAGE: Penyimpanan
Ringkasan
Pengungkapan Info log adalah jenis kerentanan ketika aplikasi mencetak data sensitif ke log perangkat. Jika terekspos ke pelaku kejahatan, informasi sensitif ini mungkin sangat berharga seperti kredensial atau informasi identitas pribadi (PII) pengguna, atau informasi tersebut dapat memungkinkan serangan lebih lanjut.
Masalah ini dapat terjadi dalam salah satu skenario berikut:
- Log yang dibuat aplikasi:
- Log sengaja mengizinkan akses ke pelaku yang tidak sah, tetapi tanpa sengaja berisi data sensitif.
- Log sengaja menyertakan data sensitif, tetapi data tersebut dapat diakses oleh pelaku yang tidak sah secara tidak sengaja.
- Log error umum yang terkadang mencetak data sensitif, bergantung pada pesan error yang dipicu.
- Log yang dibuat secara eksternal:
- Komponen eksternal bertanggung jawab untuk mencetak log yang menyertakan data sensitif.
Pernyataan Log.*
Android menulis ke buffering memori umum logcat
. Mulai Android 4.1 (API level 16), hanya aplikasi sistem dengan hak istimewa yang dapat diberi akses untuk membaca logcat
, dengan mendeklarasikan izin READ_LOGS
. Namun, Android mendukung serangkaian perangkat yang sangat beragam yang aplikasi bawaannya terkadang mendeklarasikan hak istimewa READ_LOGS
. Akibatnya, logging langsung ke logcat
tidak disarankan karena lebih rentan terhadap kebocoran data.
Pastikan semua logging ke logcat
dibersihkan dalam versi non-debug aplikasi Anda. Hapus semua data yang mungkin bersifat sensitif. Sebagai tindakan pencegahan tambahan, gunakan alat seperti R8 untuk menghapus semua level log kecuali peringatan dan error. Jika Anda membutuhkan log yang lebih mendetail, gunakan penyimpanan internal dan kelola log Anda sendiri secara langsung, bukan menggunakan log sistem.
Dampak
Tingkat keparahan class kerentanan Pengungkapan Info Log dapat bervariasi, bergantung pada konteks dan jenis data sensitif. Secara keseluruhan, dampak dari class kerentanan ini adalah hilangnya kerahasiaan informasi yang mungkin penting, seperti PII dan kredensial
Mitigasi
Umum
Sebagai tindakan preemptive umum selama desain dan implementasi, buat batas kepercayaan sesuai dengan prinsip hak istimewa terendah. Idealnya, data sensitif tidak boleh melintasi atau menjangkau orang di luar area kepercayaan mana pun. Hal ini memperkuat pemisahan hak istimewa.
Jangan mencatat log data sensitif. Hanya buat konstanta waktu kompilasi jika memungkinkan. Anda dapat menggunakan alat ErrorProne untuk anotasi konstanta waktu kompilasi.
Hindari log yang mencetak pernyataan yang mungkin berisi informasi tak terduga, termasuk data sensitif, bergantung pada error yang dipicu. Sebisa mungkin, data yang dicetak di log dan log error hanya boleh menyertakan informasi yang dapat diprediksi.
Hindari logging ke logcat
. Karena logging ke logcat
mungkin menjadi masalah privasi jika aplikasi memiliki izin READ_LOGS
. Hal ini juga tidak efektif karena tidak dapat memicu pemberitahuan atau meminta kueri. Sebaiknya aplikasi mengonfigurasi backend logcat
khusus untuk build developer.
Sebagian besar library pengelolaan log mengizinkan penentuan level log, yang memungkinkan logging jumlah informasi yang berbeda antara log debug dan produksi. Ubah level log agar berbeda dengan "debug" segera setelah pengujian produk berakhir.
Hapus sebanyak mungkin level log dari produksi. Jika Anda tidak dapat mencegah penyimpanan log dalam produksi, hapus variabel non-konstanta dari laporan log. Skenario berikut dapat terjadi:
- Anda dapat menghapus semua log dari Produksi.
- Anda harus terus menyimpan log Error dan Peringatan dalam Produksi.
Untuk kedua kasus ini, hapus log secara otomatis menggunakan library seperti R8. Setiap upaya untuk menghapus log secara manual rawan error. Sebagai bagian dari pengoptimalan kode, R8 dapat disetel untuk menghapus secara aman level log yang ingin Anda pertahankan untuk proses debug, tetapi dihapus dalam Produksi.
Jika Anda akan mencatat log di Produksi, siapkan flag yang dapat digunakan untuk menonaktifkan logging secara bersyarat jika terjadi insiden. Flag Respons Insiden harus memprioritaskan: keamanan deployment, kecepatan dan kemudahan deployment, ketelitian penyamaran log, penggunaan memori, dan biaya performa saat memindai setiap pesan log.
Menghapus log ke Logcat dari build Produksi dengan menggunakan R8.
Di Android Studio 3.4 atau plugin Android Gradle 3.4.0 dan yang lebih baru, R8 adalah compiler default untuk pengoptimalan dan penyingkatan kode. Namun, Anda harus mengaktifkan R8.
R8 telah menggantikan ProGuard, tetapi file aturan dalam folder root project masih bernama proguard-rules.pro
. Cuplikan berikut menunjukkan contoh file proguard-rules.pro
yang menghapus semua log dari produksi, kecuali peringatan dan error:
-assumenosideeffects class android.util.Log {
private static final String TAG = "MyTAG";
public static boolean isLoggable(java.lang.String, int);
public static int v(TAG, "My log as verbose");
public static int d(TAG, "My log as debug");
public static int i(TAG, "My log as information");
}
Contoh file proguard-rules.pro
berikut menghapus semua log dari produksi:
-assumenosideeffects class android.util.Log {
private static final String TAG = "MyTAG";
public static boolean isLoggable(java.lang.String, int);
public static int v(TAG, "My log as verbose");
public static int d(TAG, "My log as debug");
public static int i(TAG, "My log as information");
public static int w(TAG, "My log as warning");
public static int e(TAG, "My log as error");
}
Perhatikan bahwa R8 menyediakan kemampuan penyingkatan aplikasi dan fungsi penghapusan log. Jika Anda hanya ingin menggunakan R8 untuk fungsi penghapusan log, tambahkan kode berikut ke file proguard-rules.pro
Anda:
-dontwarn **
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontpreverify
-verbose
-optimizations !code/simplification/arithmetic,!code/allocation/variable
-keep class **
-keepclassmembers class *{*;}
-keepattributes *
Membersihkan log akhir di Produksi yang berisi data sensitif
Untuk menghindari kebocoran data sensitif, pastikan semua logging ke logcat
dibersihkan dalam versi non-debug aplikasi Anda. Hapus semua data yang mungkin bersifat sensitif.
Contoh:
Kotlin
data class Credential<T>(val data: String) {
/** Returns a redacted value to avoid accidental inclusion in logs. */
override fun toString() = "Credential XX"
}
fun checkNoMatches(list: List<Any>) {
if (!list.isEmpty()) {
Log.e(TAG, "Expected empty list, but was %s", list)
}
}
Java
public class Credential<T> {
private T t;
/** Returns a redacted value to avoid accidental inclusion in logs. */
public String toString(){
return "Credential XX";
}
}
private void checkNoMatches(List<E> list) {
if (!list.isEmpty()) {
Log.e(TAG, "Expected empty list, but was %s", list);
}
}
Menyamarkan data sensitif di log
Jika Anda harus menyertakan data sensitif di log, sebaiknya bersihkan log sebelum mencetaknya untuk menghapus atau meng-obfuscate data sensitif. Untuk melakukannya, gunakan salah satu teknik berikut:
- Tokenisasi. Jika data sensitif disimpan di vault, seperti sistem pengelolaan enkripsi dengan secret yang dapat direferensikan melalui token, catat token tersebut ke dalam log, bukan data sensitif.
- Data masking. Data masking adalah proses satu arah yang tidak dapat dibatalkan. Fungsi ini membuat versi data sensitif yang terlihat secara struktural mirip dengan aslinya, tetapi menyembunyikan informasi paling sensitif yang terdapat dalam kolom. Contoh: Mengganti nomor kartu kredit
1234-5678-9012-3456
denganXXXX-XXXX-XXXX-1313
. Sebelum merilis aplikasi ke tahap produksi, sebaiknya selesaikan proses peninjauan keamanan untuk mengamati penggunaan data masking. Peringatan: Jangan gunakan data masking jika dengan merilis sebagian data sensitif saja dapat berdampak signifikan pada keamanan, seperti saat menangani sandi. - Penyamaran. Penyamaran mirip dengan masking, tetapi menyembunyikan semua informasi yang terdapat dalam kolom. Contoh: Mengganti nomor kartu kredit
1234-5678-9012-3456
denganXXXX-XXXX-XXXX-XXXX
. - Pemfilteran. Implementasikan string format dalam library logging pilihan Anda jika string tersebut belum ada, untuk memfasilitasi modifikasi nilai non-konstanta dalam laporan log.
Pencetakan log hanya boleh dilakukan melalui komponen "logs sanitizer" yang memastikan semua log dibersihkan sebelum dicetak, seperti yang ditunjukkan dalam cuplikan kode berikut.
Kotlin
data class ToMask<T>(private val data: T) {
// Prevents accidental logging when an error is encountered.
override fun toString() = "XX"
// Makes it more difficult for developers to invoke sensitive data
// and facilitates sensitive data usage tracking.
fun getDataToMask(): T = data
}
data class Person(
val email: ToMask<String>,
val username: String
)
fun main() {
val person = Person(
ToMask("name@gmail.com"),
"myname"
)
println(person)
println(person.email.getDataToMask())
}
Java
public class ToMask<T> {
// Prevents accidental logging when an error is encountered.
public String toString(){
return "XX";
}
// Makes it more difficult for developers to invoke sensitive data
// and facilitates sensitive data usage tracking.
public T getDataToMask() {
return this;
}
}
public class Person {
private ToMask<String> email;
private String username;
public Person(ToMask<String> email, String username) {
this.email = email;
this.username = username;
}
}
public static void main(String[] args) {
Person person = new Person(
ToMask("name@gmail.com"),
"myname"
);
System.out.println(person);
System.out.println(person.email.getDataToMask());
}