असुरक्षित Deserialization: जोखिम और बचाव
अविश्वसनीय pickle, Java serialization और PHP unserialize डेटा खतरनाक व्यवहार कैसे चला सकता है, और इसे कैसे बदलें या सीमित करें।
💡 सरल भाषा में (ELI5)
Serialization को मॉडल जोड़ने के निर्देश डाक से भेजने जैसा समझें। Deserialization उन निर्देशों से डेटा फिर बनाता है। कुछ formats पुनर्निर्माण के दौरान class चुन सकते हैं या hook चला सकते हैं। इसलिए अविश्वसनीय निर्देश स्वीकार करने से अनचाहा व्यवहार हो सकता है। असर format, runtime, उपलब्ध classes और application context पर निर्भर करता है।
Core Concepts & Key Terms
- Serialization / deserialization
- डेटा या objects को संग्रहण/परिवहन योग्य रूप में बदलना और फिर program में parse या पुनर्निर्मित करना।
- Deserialization hooks
- Python __reduce__, Java readObject, या PHP __wakeup / __unserialize जैसे callbacks जो object बनाते समय चल सकते हैं।
- Gadget chain
- पहले से मौजूद libraries के व्यवहारों की श्रृंखला जो अनचाहा प्रभाव पैदा कर सकती है। उपलब्धता application और versions पर निर्भर है।
- Deserialization filter
- Object stream पढ़ते समय classes या graph metrics सीमित करने की नीति। यह जोखिम घटाती है, पर untrusted native object streams को पसंदीदा format नहीं बनाती।
How Unsafe Deserialization Can Become an Exploit Chain
अविश्वसनीय bytes decoder तक पहुँचते हैं
Cookie, API body, queue message या stored record में attacker के नियंत्रण वाला डेटा हो सकता है।
Application native object format चलाता है
Code bytes को Python pickle, Java ObjectInputStream या PHP unserialize() जैसे decoder को देता है।
Reconstruction format-विशिष्ट व्यवहार चलाता है
Format और उपलब्ध classes के आधार पर constructors, hooks, autoloading या library methods application validation से पहले चल सकते हैं।
असर उपलब्ध व्यवहार पर निर्भर है
उपलब्ध gadget या hook अनधिकृत प्रभाव कर सकता है; अन्य input केवल fail या संसाधन खर्च कर सकता है। हर मामले में code execution स्वतः नहीं होता।
Python / Flask: Unsafe Object Loading vs. Primitive JSON Validation
# VULNERABLE: pickle can execute behavior during unpickling.
from flask import Flask, request
import pickle
app = Flask(__name__)
@app.post("/api/session")
def load_session():
# Never deserialize attacker-controlled bytes with pickle.
session = pickle.loads(request.get_data())
return {"user_id": session.user_id}
# SAFER: parse JSON primitives, then validate expected shape.
from flask import Flask, abort, request
app = Flask(__name__)
app.config["MAX_CONTENT_LENGTH"] = 16 * 1024
@app.post("/api/session")
def load_session():
payload = request.get_json()
if not isinstance(payload, dict):
abort(400, "Expected a JSON object")
user_id = payload.get("user_id")
if type(user_id) is not int or user_id <= 0:
abort(400, "Invalid user_id")
# Resolve authorization and session state server-side.
return {"user_id": user_id}
इंजीनियरिंग सुरक्षा सुदृढ़ीकरण जाँच-सूची
JSON के लिए भी input-size limits और structure validation आवश्यक हैं। पुराने object formats में केवल class allowlist पर निर्भर न रहें: deserialization से पहले exact serialized bytes को authenticate करें और keys सुरक्षित रखें। MAC डेटा को encrypt नहीं करता और replay को नहीं रोकता।
- अविश्वसनीय native object streams को Python pickle या PHP unserialize से न पढ़ें; schema और आकार जाँचे हुए JSON जैसे primitive formats चुनें।
- Java serialization हटाना अभी संभव न हो तो ObjectInputFilter allowlist और graph limits लगाएँ; हर deployment में filter अपने-आप चालू नहीं होता।
- पुराने payload की integrity चाहिए तो deserialization से पहले सुरक्षित MAC key से exact bytes authenticate करें; MAC encryption या replay protection नहीं है।
- Session authority server पर रखें या expiry, audience और key rotation वाले maintained framework-signed tokens का उपयोग करें।