লগ ইনফো ডিসক্লোজার

OWASP বিভাগ: MASVS-স্টোরেজ: স্টোরেজ

ওভারভিউ

লগ ইনফো ডিসক্লোজার হল এক ধরনের দুর্বলতা যেখানে অ্যাপগুলি ডিভাইস লগে সংবেদনশীল ডেটা প্রিন্ট করে। দূষিত অভিনেতাদের সংস্পর্শে এলে, এই সংবেদনশীল তথ্য সরাসরি মূল্যবান হতে পারে - যেমন ব্যবহারকারীর শংসাপত্র বা ব্যক্তিগতভাবে শনাক্তকরণযোগ্য তথ্য (PII) - অথবা এটি আরও আক্রমণ সক্ষম করতে পারে৷

এই সমস্যা নিম্নলিখিত পরিস্থিতিতে ঘটতে পারে:

  • অ্যাপ-উত্পন্ন লগ:
    • লগগুলি ইচ্ছাকৃতভাবে অননুমোদিত অভিনেতাদের অ্যাক্সেসের অনুমতি দেয়, তবুও তারা দুর্ঘটনাক্রমে সংবেদনশীল ডেটা ধারণ করে৷
    • লগগুলি ইচ্ছাকৃতভাবে সংবেদনশীল ডেটা অন্তর্ভুক্ত করে, তবে সেগুলি দুর্ঘটনাক্রমে অননুমোদিত অভিনেতাদের কাছে অ্যাক্সেসযোগ্য৷
    • ট্রিগার করা ত্রুটির বার্তার উপর নির্ভর করে জেনেরিক ত্রুটির লগ যা মাঝে মাঝে সংবেদনশীল ডেটা প্রিন্ট করতে পারে।
  • বাহ্যিকভাবে তৈরি লগ:
    • বাহ্যিক উপাদানগুলি সংবেদনশীল ডেটা অন্তর্ভুক্ত করে লগ মুদ্রণের জন্য দায়ী৷

অ্যান্ড্রয়েড Log.* বিবৃতিগুলি সাধারণ মেমরি বাফার logcat লেখা হয়। যেহেতু Android 4.1 (API স্তর 16), শুধুমাত্র সুবিধাপ্রাপ্ত সিস্টেম অ্যাপগুলিকে READ_LOGS অনুমতি ঘোষণা করে logcat পড়ার অ্যাক্সেস দেওয়া যেতে পারে৷ যাইহোক, অ্যান্ড্রয়েড একটি অবিশ্বাস্যভাবে বৈচিত্র্যময় ডিভাইসের সেটকে সমর্থন করে যার প্রি-লোড করা অ্যাপ্লিকেশনগুলি কখনও কখনও READ_LOGS বিশেষাধিকার ঘোষণা করে৷ ফলস্বরূপ, logcat সরাসরি লগিং করা নিরুৎসাহিত করা হয় কারণ এটি ডেটা ফাঁসের প্রবণতা বেশি।

আপনার অ্যাপ্লিকেশনের নন-ডিবাগ সংস্করণগুলিতে logcat সমস্ত লগিং স্যানিটাইজ করা হয়েছে তা নিশ্চিত করুন। সংবেদনশীল হতে পারে এমন যেকোন ডেটা সরিয়ে দিন। একটি অতিরিক্ত সতর্কতা হিসাবে, সতর্কতা এবং ত্রুটি ব্যতীত সমস্ত লগ স্তরগুলি সরাতে R8 এর মতো সরঞ্জামগুলি ব্যবহার করুন৷ আপনার যদি আরও বিস্তারিত লগের প্রয়োজন হয়, অভ্যন্তরীণ সঞ্চয়স্থান ব্যবহার করুন এবং সিস্টেম লগ ব্যবহার না করে সরাসরি আপনার নিজের লগগুলি পরিচালনা করুন৷

প্রভাব

লগ ইনফো ডিসক্লোজার দুর্বলতা শ্রেণীর তীব্রতা প্রেক্ষাপট এবং সংবেদনশীল ডেটার প্রকারের উপর নির্ভর করে পরিবর্তিত হতে পারে। সামগ্রিকভাবে, এই দুর্বলতা শ্রেণীর প্রভাব হল PII এবং শংসাপত্রের মতো সম্ভাব্য গুরুত্বপূর্ণ তথ্যের গোপনীয়তা হারানো।

প্রশমন

সাধারণ

নকশা এবং বাস্তবায়নের সময় একটি সাধারণ অগ্রিম পরিমাপ হিসাবে, ন্যূনতম বিশেষাধিকারের নীতি অনুসারে বিশ্বাসের সীমানা আঁকুন। আদর্শভাবে, সংবেদনশীল ডেটা ট্রাস্টের যেকোন জায়গার বাইরে যাওয়া বা পৌঁছানো উচিত নয়। এটি বিশেষাধিকারের বিচ্ছেদকে শক্তিশালী করে।

সংবেদনশীল তথ্য লগ করবেন না. যখনই সম্ভব শুধুমাত্র লগ কম্পাইল-টাইম ধ্রুবক। আপনি কম্পাইল-টাইম ধ্রুবক টীকা জন্য ErrorProne টুল ব্যবহার করতে পারেন।

ট্রিগার করা ত্রুটির উপর নির্ভর করে সংবেদনশীল ডেটা সহ অপ্রত্যাশিত তথ্য থাকতে পারে এমন বিবৃতিগুলি মুদ্রণ করে এমন লগগুলি এড়িয়ে চলুন৷ যতটা সম্ভব, লগ এবং ত্রুটির লগগুলিতে মুদ্রিত ডেটা শুধুমাত্র অনুমানযোগ্য তথ্য অন্তর্ভুক্ত করা উচিত।

logcat লগিং এড়িয়ে চলুন। এর কারণ হল READ_LOGS অনুমতি সহ অ্যাপগুলির কারণে logcat লগিং করা একটি গোপনীয়তার সমস্যা হয়ে উঠতে পারে৷ এটি অকার্যকর কারণ এটি সতর্কতা ট্রিগার করতে পারে না বা জিজ্ঞাসা করা যায় না। আমরা সুপারিশ করি যে অ্যাপ্লিকেশনগুলি শুধুমাত্র বিকাশকারী বিল্ডের জন্য logcat ব্যাকএন্ড কনফিগার করে।

বেশিরভাগ লগ ম্যানেজমেন্ট লাইব্রেরি লগ লেভেল সংজ্ঞায়িত করার অনুমতি দেয়, যা ডিবাগ এবং প্রোডাকশন লগের মধ্যে বিভিন্ন পরিমাণ তথ্য লগ করার অনুমতি দেয়। লগ লেভেল পরিবর্তন করুন যাতে পণ্য পরীক্ষা শেষ হওয়ার সাথে সাথে এটি "ডিবাগ" থেকে আলাদা হয়।

উৎপাদন থেকে যতটা সম্ভব লগ লেভেল সরান। আপনি যদি প্রোডাকশনে লগ রাখা এড়াতে না পারেন, তাহলে লগ স্টেটমেন্ট থেকে অ-স্থির ভেরিয়েবল সরিয়ে দিন। নিম্নলিখিত পরিস্থিতিতে ঘটতে পারে:

  • আপনি উত্পাদন থেকে সমস্ত লগ মুছে ফেলতে সক্ষম।
  • আপনাকে উৎপাদনে সতর্কতা এবং ত্রুটি লগ রাখতে হবে।

এই উভয় ক্ষেত্রেই, R8 এর মতো লাইব্রেরি ব্যবহার করে স্বয়ংক্রিয়ভাবে লগগুলি সরান৷ ম্যানুয়ালি লগ মুছে ফেলার কোনো প্রচেষ্টা ত্রুটির প্রবণ। কোড অপ্টিমাইজেশানের অংশ হিসাবে, R8 নিরাপদে লগ লেভেলগুলি মুছে ফেলার জন্য সেট করা যেতে পারে যা আপনি ডিবাগিংয়ের জন্য রাখতে চান তবে উত্পাদনে ফালা।

আপনি যদি প্রোডাকশনে লগ ইন করতে যাচ্ছেন, কোন ঘটনার ক্ষেত্রে শর্তসাপেক্ষে লগিং বন্ধ করতে ব্যবহার করতে পারেন এমন পতাকা প্রস্তুত করুন। ঘটনা প্রতিক্রিয়া পতাকা অগ্রাধিকার দেওয়া উচিত: স্থাপনার নিরাপত্তা; গতি এবং স্থাপনের সহজলভ্যতা, লগ সংশোধন করার পুঙ্খানুপুঙ্খতা, মেমরি ব্যবহার এবং প্রতিটি লগ মেসেজ স্ক্যান করার পারফরম্যান্স খরচ।

R8 ব্যবহার করে প্রোডাকশন বিল্ড থেকে লগক্যাটে স্ট্রিপ লগ।

অ্যান্ড্রয়েড স্টুডিও 3.4 বা অ্যান্ড্রয়েড গ্রেডল প্লাগইন 3.4.0 এবং উচ্চতর, কোড অপ্টিমাইজেশন এবং সঙ্কুচিত করার জন্য R8 হল ডিফল্ট কম্পাইলার। যাইহোক, আপনাকে R8 সক্ষম করতে হবে।

R8 ProGuard প্রতিস্থাপন করেছে, কিন্তু প্রকল্পের রুট ফোল্ডারে থাকা নিয়ম ফাইলটিকে এখনও proguard-rules.pro বলা হয়। নিচের স্নিপেটটি একটি নমুনা proguard-rules.pro ফাইল দেখায় যা সতর্কতা এবং ত্রুটি ছাড়া উৎপাদন থেকে সমস্ত লগ সরিয়ে দেয়:

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

নিম্নলিখিত নমুনা proguard-rules.pro ফাইলটি উত্পাদন থেকে সমস্ত লগ সরিয়ে দেয়:

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

মনে রাখবেন যে R8 অ্যাপ-সঙ্কুচিত ক্ষমতা এবং লগ-স্ট্রিপিং কার্যকারিতা প্রদান করে। আপনি যদি শুধুমাত্র এর লগ-স্ট্রিপিং কার্যকারিতার জন্য R8 ব্যবহার করতে চান, তাহলে আপনার proguard-rules.pro ফাইলে নিম্নলিখিত যোগ করুন:

-dontwarn **
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontpreverify
-verbose

-optimizations !code/simplification/arithmetic,!code/allocation/variable
-keep class **
-keepclassmembers class *{*;}
-keepattributes *

সংবেদনশীল ডেটা সহ প্রোডাকশনের যেকোন শেষ লগগুলিকে স্যানিটাইজ করুন

সংবেদনশীল ডেটা ফাঁস এড়াতে, আপনার অ্যাপ্লিকেশনের নন-ডিবাগ সংস্করণগুলিতে logcat সমস্ত লগিং স্যানিটাইজ করা হয়েছে তা নিশ্চিত করুন। সংবেদনশীল হতে পারে এমন যেকোন ডেটা সরিয়ে দিন।

উদাহরণ:

কোটলিন

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

জাভা

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

লগে সংবেদনশীল ডেটা রিডাক্ট করুন

আপনি যদি আপনার লগগুলিতে সংবেদনশীল ডেটা অন্তর্ভুক্ত করতে চান, তাহলে আমরা সংবেদনশীল ডেটা অপসারণ বা অস্পষ্ট করার জন্য লগগুলি মুদ্রণের আগে সেগুলিকে স্যানিটাইজ করার পরামর্শ দিই৷ এটি করতে, নিম্নলিখিত কৌশলগুলির মধ্যে একটি ব্যবহার করুন:

  • টোকেনাইজেশন। যদি সংবেদনশীল ডেটা একটি ভল্টে সংরক্ষণ করা হয়, যেমন একটি এনক্রিপশন ম্যানেজমেন্ট সিস্টেম যা থেকে গোপনীয়তাগুলি টোকেনের মাধ্যমে উল্লেখ করা যেতে পারে, সংবেদনশীল ডেটার পরিবর্তে টোকেনটি লগ করুন৷
  • ডেটা মাস্কিং। ডেটা মাস্কিং একটি একমুখী অপরিবর্তনীয় প্রক্রিয়া। এটি সংবেদনশীল ডেটার একটি সংস্করণ তৈরি করে যা কাঠামোগতভাবে আসলটির মতো দেখায়, তবে একটি ক্ষেত্রের মধ্যে থাকা সবচেয়ে সংবেদনশীল তথ্য লুকিয়ে রাখে। উদাহরণ: ক্রেডিট কার্ড নম্বর 1234-5678-9012-3456 এর পরিবর্তে XXXX-XXXX-XXXX-1313 । আপনি আপনার অ্যাপটি উৎপাদনে প্রকাশ করার আগে, আমরা আপনাকে ডেটা মাস্কিংয়ের ব্যবহার যাচাই করার জন্য একটি নিরাপত্তা পর্যালোচনা প্রক্রিয়া সম্পূর্ণ করার পরামর্শ দিই। সতর্কতা: এমন ক্ষেত্রে ডেটা মাস্কিং ব্যবহার করবেন না যেখানে এমনকি সংবেদনশীল ডেটার শুধুমাত্র একটি অংশ প্রকাশ করা নিরাপত্তাকে উল্লেখযোগ্যভাবে প্রভাবিত করতে পারে, যেমন পাসওয়ার্ড পরিচালনা করার সময়।
  • রিডাকশন। রিডাকশন মাস্কিংয়ের মতোই, তবে একটি ক্ষেত্রের মধ্যে থাকা সমস্ত তথ্য লুকিয়ে রাখে। উদাহরণ: ক্রেডিট কার্ড নম্বর 1234-5678-9012-3456 এর পরিবর্তে XXXX-XXXX-XXXX-XXXX
  • ফিল্টারিং। আপনার পছন্দের লগিং লাইব্রেরিতে ফর্ম্যাট স্ট্রিংগুলি প্রয়োগ করুন যদি সেগুলি ইতিমধ্যে বিদ্যমান না থাকে, লগ স্টেটমেন্টে অ-স্থির মানগুলির পরিবর্তনের সুবিধার্থে।

লগ প্রিন্টিং শুধুমাত্র একটি "লগ স্যানিটাইজার" উপাদানের মাধ্যমে করা উচিত যা নিশ্চিত করে যে সমস্ত লগ প্রিন্ট করার আগে স্যানিটাইজ করা হয়েছে, যেমনটি নিম্নলিখিত কোড স্নিপেটে দেখানো হয়েছে।

কোটলিন

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

জাভা

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