Deserialization ناامن چیست؟
سریالسازی (Serialization) تبدیل یک شیء در حافظه به رشتهای قابلذخیره یا انتقال است، و Deserialization عکس آن. Deserialization ناامن وقتی رخ میدهد که برنامه دادهی سریالشدهی تحت کنترل مهاجم را با فرمتی که از نمونهسازی نوع دلخواه و فراخوانیهای چرخهی حیات شیء پشتیبانی میکند، به شیء تبدیل کند. پیامد معمولاً اجرای کد از راه دور است، و گاهی منع سرویس یا دور زدن احراز هویت.
نکتهی محوری این است که مهاجم به یک کلاس آسیبپذیر در کد خودِ برنامه نیاز ندارد؛ او متدهای معمولی را در طول کتابخانههای موجود روی classpath به هم زنجیر میکند تا به یک اثر خطرناک برسد. این همان مفهوم زنجیرهی گجت (Gadget Chain) است.
برای درک شهودی: هنگام بازسازی یک شیء، رانتایم بهطور خودکار متدهای خاصی را فراخوانی میکند (در جاوا هنگام readObject، در PHP متدهای جادویی مثل __wakeup و __destruct). اگر مهاجم بتواند نوع و مقادیر شیء بازسازیشده را کنترل کند، میتواند دنبالهای از این فراخوانیهای خودکار را طوری بچیند که در انتها به اجرای فرمان، خواندن فایل یا برقراری اتصال شبکه برسد. کل «کد» این حمله در واقع همان دادهی سریالشده است — به همین دلیل فیلترهای ورودی متنی معمولاً آن را نمیگیرند.
فرمتهای آسیبپذیر: جاوا، PHP، پایتون، داتنت
این ضعف به یک زبان محدود نیست؛ در هر اکوسیستمی که فرمت سریالسازی غنی دارد ظاهر میشود:
- جاوا: سریالسازی بومی از راه
ObjectInputStream.readObject؛ و کتابخانههایی با مدیریت نوع چندریختی مانند Jackson باenableDefaultTyping، نسخههای قدیمی Fastjson و SnakeYAML. - PHP: تابع
unserialize()با زنجیرههای POP از راه متدهای جادویی__wakeup،__destructو__toString. - پایتون: ماژولهای
pickle،cPickle،shelveوdillکه بهطراحی میتوانند کد اجرا کنند. - داتنت:
BinaryFormatter،LosFormatter،ObjectStateFormatterوTypeNameHandlingدر Json.NET.
روند فعلی این است که واریانت سریالسازی بومی در پشتههای نگهداریشده رو به کاهش است — جاوا فیلترسازی سریالسازی (ObjectInputFilter، JEP 290) را افزوده و BinaryFormatter در داتنت مدتهاست منسوخ و در نسخههای اخیر بهصورت پیشفرض غیرفعال شده است — درحالیکه واریانت گیجی نوع در JSON/YAML چندریختی در حال رشد است. بهبیان دیگر، مهاجمان از سریالسازی بومی بهسمت پیکربندیهای ناامنِ کتابخانههای JSON/YAML کوچ کردهاند؛ جایی که فعال بودن حل نوع چندریختی (مثل enableDefaultTyping در Jackson یا TypeNameHandling در Json.NET) اجازه میدهد داده، نوع شیء مقصد را دیکته کند. برای یک تیم توسعه، پیام عملی روشن است: صرفِ بهروزرسانی رانتایم کافی نیست، باید پیکربندی کتابخانههای سریالسازی را هم بازبینی کرد.
«ما از JSON استفاده میکنیم، پس deserialization ناامن نداریم؛ این فقط مشکل فرمتهای باینری است.» نادرست است. اگر کتابخانهی JSON یا YAML با حل نوع چندریختی پیکربندی شده باشد (مانند enableDefaultTyping در Jackson، TypeNameHandling در Json.NET یا Constructor در SnakeYAML)، همان داده میتواند نوع شیء مقصد را دیکته کند و به زنجیرهی گجت برسد. خطر در «باینری بودن» فرمت نیست، در اجازهدادن به داده برای تعیین نوع است.
زنجیرهی گجت و ابزار ysoserial
ساخت دستی زنجیرهی گجت کاری تخصصی است؛ به همین دلیل ابزارهای آماده وجود دارند. مرجع در جاوا، ysoserial است که برای مجموعهای از کتابخانههای پرکاربرد، بار سریالشدهی رسیدن به اجرا را تولید میکند. معادل PHP آن phpggc و در داتنت ysoserial.net است.
تشخیص وجود دادهی سریالشده در ترافیک، از روی امضای شروع داده ممکن است:
# امضای شروع دادهی سریالشده
Java: AC ED 00 05 (Base64: rO0AB)
PHP: O:4:"User":... یا a:...
.NET: AAEAAAD/////
Python: pickle، اغلب Base64 با gASV یا gAJدیدن این الگوها در کوکی، فیلد مخفی یا بدنهی درخواست، نشانهی قوی برای بررسی این آسیب است.
سناریوی واقعی و کشف در تست نفوذ
سناریوی متعارف: یک برنامهی جاوا وضعیت کاربر را در یک کوکی سریالشده ذخیره میکند و هنگام هر درخواست آن را deserialize میکند. مهاجم کوکی را با یک بار ساختهشده جایگزین میکند که هنگام تبدیل به شیء، زنجیرهای از متدها را تا اجرای فرمان فعال میکند.
روش کشف در تست نفوذ وب:
- یافتن نقاطی که دادهی سریالشده میپذیرند (کوکی، فیلد مخفی، پارامتر، پیام صف).
- تشخیص فرمت از روی امضای شروع داده.
- پروب کنترلشده برای اثبات وجود deserialize (مثلاً یک تعامل خارجباند بیخطر با Burp Suite) — بدون اجرای زنجیرهی بهرهبرداری واقعی.
- مکمل با بازبینی کد منبع برای یافتن فراخوانیهای
readObject،unserializeوpickle.loadsروی دادهی نامعتمد.
برای آموزش تیم توسعه در پیشگیری از این کلاس آسیب، دورهی سازمانی توسعه امن راهکار مناسبی است.
ارتباط با OWASP و CWE
Deserialization ناامن شناسهی CWE-502 (Deserialization of Untrusted Data) را دارد و در OWASP Top 10:2025 زیر دستهی A08:2025 نقص یکپارچگی نرمافزار یا داده (Software or Data Integrity Failures) قرار میگیرد؛ در فهرست ۲۵گانهی CWE سال ۲۰۲۵ رتبهی پانزدهم است. این آسیب یکی از مسیرهای پرتکرار رسیدن به RCE در برنامههای سازمانی است. مرور دستهبندی در صفحهی OWASP و مقالهی OWASP Top 10 نسخه ۲۰۲۵.
پرسشهای متداول
زنجیرهی گجت (Gadget Chain) چیست؟
ترتیبی از متدهای معمولیِ موجود در کتابخانههای روی classpath که هنگام deserialize به هم زنجیر میشوند و به یک اثر خطرناک مثل اجرای فرمان میرسند. نکته این است که به کلاس آسیبپذیر در کد خود برنامه نیازی نیست.
ابزار ysoserial چه کاری میکند؟
ysoserial برای مجموعهای از کتابخانههای پرکاربرد جاوا، بار سریالشدهی متناظر با زنجیرهی گجت را تولید میکند. معادل آن در PHP ابزار phpggc و در داتنت ysoserial.net است.
چطور بفهمم یک درخواست دادهی سریالشده دارد؟
از روی امضای شروع داده: جاوا با AC ED 00 05 (Base64 با rO0AB)، PHP با O: یا a:، داتنت با AAEAAAD///// و pickle پایتون اغلب Base64 با gASV. دیدن اینها در کوکی یا بدنه نشانهی بررسی است.