অনিরাপদ ডিসিরিয়ালাইজেশন

OWASP বিভাগ: MASVS-CODE: কোডের গুণমান

সংক্ষিপ্ত বিবরণ

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

যদিও সিরিয়ালাইজেশন পরিচালনার জন্য Serializable ক্লাস একটি প্রচলিত পদ্ধতি, অ্যান্ড্রয়েডের নিজস্ব একটি ক্লাস আছে যার নাম ParcelParcel ক্লাস ব্যবহার করে, অবজেক্ট ডেটাকে বাইট স্ট্রিম ডেটাতে সিরিয়ালাইজ করা যায় এবং Parcelable ইন্টারফেসের মাধ্যমে একটি Parcel এ প্যাক করা যায়। এর ফলে Parcel আরও দক্ষতার সাথে পরিবহন বা সংরক্ষণ করা যায়।

তথাপি, Parcel ক্লাস ব্যবহার করার সময় সতর্ক বিবেচনা করা উচিত, কারণ এটি একটি উচ্চ-দক্ষতা সম্পন্ন IPC ট্রান্সপোর্ট মেকানিজম হিসেবে ব্যবহৃত হলেও, লোকাল পারসিস্টেন্ট স্টোরেজে সিরিয়ালাইজড অবজেক্ট সংরক্ষণ করার জন্য এটি ব্যবহার করা উচিত নয়, কারণ এর ফলে ডেটা সামঞ্জস্যের সমস্যা বা ডেটা হারানোর ঝুঁকি থাকতে পারে। যখন ডেটা পড়ার প্রয়োজন হয়, তখন Parcelable ইন্টারফেস ব্যবহার করে Parcel ডিসিরিয়ালাইজ করে পুনরায় অবজেক্ট ডেটাতে পরিণত করা যায়।

অ্যান্ড্রয়েডে ডিসিরিয়ালাইজেশন কাজে লাগানোর তিনটি প্রধান উপায় রয়েছে:

  • ডেভেলপারদের এই ভুল ধারণার সুযোগ নেওয়া হয় যে, একটি কাস্টম ক্লাস টাইপ থেকে আসা অবজেক্টগুলোকে ডিসিরিয়ালাইজ করা নিরাপদ। বাস্তবে, যেকোনো ক্লাস থেকে প্রাপ্ত যেকোনো অবজেক্টকে ক্ষতিকর কন্টেন্ট দিয়ে প্রতিস্থাপন করা যেতে পারে, যা সবচেয়ে খারাপ পরিস্থিতিতে, একই বা অন্য অ্যাপ্লিকেশনের ক্লাস লোডারের কাজে হস্তক্ষেপ করতে পারে। এই হস্তক্ষেপ বিপজ্জনক ভ্যালু প্রবেশ করানোর মাধ্যমে ঘটে, যা ক্লাসের উদ্দেশ্য অনুযায়ী, উদাহরণস্বরূপ, ডেটা এক্সফিলট্রেশন বা অ্যাকাউন্ট দখলের দিকে নিয়ে যেতে পারে।
  • ডিজাইনগতভাবেই অনিরাপদ বলে বিবেচিত ডি-সিরিয়ালাইজেশন পদ্ধতিগুলোর অপব্যবহার করা (উদাহরণস্বরূপ CVE-2023-35669 , একটি লোকাল প্রিভিলেজ এসকেলেশন ত্রুটি যা একটি ডিপ-লিঙ্ক ডি-সিরিয়ালাইজেশন ভেক্টরের মাধ্যমে যথেচ্ছ জাভাস্ক্রিপ্ট কোড ইনজেকশনের সুযোগ দিত)।
  • অ্যাপ্লিকেশন লজিকের ত্রুটি কাজে লাগানো (উদাহরণস্বরূপ CVE-2023-20963 , একটি লোকাল প্রিভিলেজ এসকেলেশন ত্রুটি যা অ্যান্ড্রয়েডের WorkSource পার্সেল লজিকের একটি ত্রুটির মাধ্যমে একটি অ্যাপকে বিশেষাধিকারপ্রাপ্ত পরিবেশে কোড ডাউনলোড এবং এক্সিকিউট করার সুযোগ দিত)।

প্রভাব

যে কোনো অ্যাপ্লিকেশন যা অবিশ্বস্ত বা ক্ষতিকারক সিরিয়ালাইজড ডেটা ডিসিরিয়ালাইজ করে, তা রিমোট কোড এক্সিকিউশন বা ডিনায়াল অফ সার্ভিস অ্যাটাকের ঝুঁকিতে থাকতে পারে।

ঝুঁকি: অবিশ্বস্ত ইনপুটের ক্রমবিচ্যুতি

একজন আক্রমণকারী অ্যাপ্লিকেশন লজিকের মধ্যে পার্সেল ভেরিফিকেশনের অভাবকে কাজে লাগিয়ে যথেচ্ছ অবজেক্ট প্রবেশ করাতে পারে, যা একবার ডিসিরিয়ালাইজ করা হলে অ্যাপ্লিকেশনটিকে ক্ষতিকারক কোড চালাতে বাধ্য করতে পারে। এর ফলে ডিনায়াল অফ সার্ভিস (DoS), প্রিভিলেজ এসকেলেশন এবং রিমোট কোড এক্সিকিউশন (RCE) ঘটতে পারে।

এই ধরনের আক্রমণগুলো সূক্ষ্ম হতে পারে। উদাহরণস্বরূপ, একটি অ্যাপ্লিকেশনে এমন একটি ইন্টেন্ট থাকতে পারে যা শুধুমাত্র একটি প্যারামিটার প্রত্যাশা করে এবং যা যাচাই করার পর ডিসিরিয়ালাইজ করা হবে। যদি কোনো আক্রমণকারী প্রত্যাশিত প্যারামিটারটির সাথে দ্বিতীয়, অপ্রত্যাশিত একটি ক্ষতিকারক অতিরিক্ত প্যারামিটার পাঠায়, তাহলে ইনজেক্ট করা সমস্ত ডেটা অবজেক্ট ডিসিরিয়ালাইজ হয়ে যাবে, কারণ ইন্টেন্টটি এই অতিরিক্ত প্যারামিটারগুলোকে একটি Bundle হিসেবে গণ্য করে। একজন ক্ষতিকারক ব্যবহারকারী এই আচরণকে কাজে লাগিয়ে এমন অবজেক্ট ডেটা ইনজেক্ট করতে পারে, যা একবার ডিসিরিয়ালাইজ হয়ে গেলে RCE (রিটার্ন-দ্য-কাউন্টার ইভেন্ট), ডেটার নিরাপত্তা লঙ্ঘন বা ডেটা হারানোর কারণ হতে পারে।

প্রশমন

একটি উত্তম অনুশীলন হিসেবে, ধরে নিন যে সমস্ত সিরিয়ালাইজড ডেটা অবিশ্বস্ত এবং সম্ভাব্য ক্ষতিকারক। সিরিয়ালাইজড ডেটার অখণ্ডতা নিশ্চিত করতে, ডেটাটির উপর যাচাইকরণ পরীক্ষা চালান যাতে নিশ্চিত হওয়া যায় যে এটি অ্যাপ্লিকেশনটির প্রত্যাশিত সঠিক ক্লাস এবং ফরম্যাটের।

A feasible solution could be to implement the look-ahead pattern for the java.io.ObjectInputStream library . By modifying the code responsible for deserialization, you can make sure that only an explicitly specified set of classes is deserialized within the intent.

As of Android 13 (API level 33), several methods have been updated within the Intent class that are considered safer alternatives to older and now-deprecated methods for handling parcels. These new type-safer methods, such as getParcelableExtra(java.lang.String, java.lang.Class) and getParcelableArrayListExtra(java.lang.String, java.lang.Class) perform data type checks to catch mismatch weaknesses that might cause applications to crash and potentially be exploited to perform privilege escalation attacks, such as CVE-2021-0928 .

নিম্নলিখিত উদাহরণটি দেখায় যে কীভাবে Parcel ক্লাসের একটি নিরাপদ সংস্করণ বাস্তবায়ন করা যেতে পারে:

ধরা যাক, UserParcelable ক্লাসটি Parcelable ইমপ্লিমেন্ট করে এবং ইউজার ডেটার একটি ইনস্ট্যান্স তৈরি করে, যা পরে একটি Parcel এ লেখা হয়। এরপর সিরিয়ালাইজড পার্সেলটি পড়ার জন্য readParcelable এর নিম্নলিখিত টাইপ-সেফার মেথডটি ব্যবহার করা যেতে পারে:

কোটলিন

val parcel = Parcel.obtain()
val userParcelable = parcel.readParcelable(UserParcelable::class.java.classLoader)

জাভা

Parcel parcel = Parcel.obtain();
UserParcelable userParcelable = parcel.readParcelable(UserParcelable.class, UserParcelable.CREATOR);

উপরের জাভা উদাহরণটিতে মেথডের ভিতরে UserParcelable.CREATOR এর ব্যবহার লক্ষ্য করুন। এই আবশ্যক প্যারামিটারটি readParcelable মেথডকে বলে দেয় যে এটি কোন ধরনের ডেটা আশা করবে এবং এটি readParcelable মেথডের বর্তমানে অপ্রচলিত সংস্করণটির চেয়ে বেশি কার্যকর।

নির্দিষ্ট ঝুঁকি

এই বিভাগে এমন ঝুঁকিগুলো একত্রিত করা হয়েছে যেগুলোর জন্য অ-প্রমিত প্রশমন কৌশল প্রয়োজন অথবা যেগুলো কোনো নির্দিষ্ট SDK স্তরে প্রশমিত করা হয়েছে এবং এগুলো এখানে সম্পূর্ণতার জন্য রাখা হয়েছে।

ঝুঁকি: অনাকাঙ্ক্ষিত অবজেক্ট ডিসিরিয়ালাইজেশন

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

প্রশমন

OWASP-এর নির্দেশনা অনুযায়ী, যদি কোনো ক্লাস Serializable ইন্টারফেস থেকে উত্তরাধিকার সূত্রে প্রাপ্ত হয়, তবে ক্লাসের মধ্যে থাকা এক সেট অবজেক্ট যাতে ডিসিরিয়ালাইজ হতে না পারে, তা এড়ানোর জন্য readObject মেথডটি নিম্নোক্তভাবে ইমপ্লিমেন্ট করা উচিত:

কোটলিন

@Throws(IOException::class)
private final fun readObject(in: ObjectInputStream) {
    throw IOException("Cannot be deserialized")
}

জাভা

private final void readObject(ObjectInputStream in) throws java.io.IOException {
    throw new java.io.IOException("Cannot be deserialized");
}

সম্পদ