Certificate Pinning (پین کردن گواهی) — یک تکنیک امنیتی است که در آن برنامه موبایل بررسی میکند که گواهی سرور با نمونه از پیش شناخته شده مطابقت دارد و نه صرفاً به هر گواهی از زنجیره CA اعتماد میکند. برخلاف بررسی استاندارد TLS که به صدها مرکز صدور گواهی متکی است، pinning اعتماد را به یک گواهی خاص یا کلید عمومی آن محدود میکند. طبق OWASP Mobile Security Testing Guide (2024)، پیادهسازی Certificate Pinning 100% سناریوهای حملات Man-in-the-Middle مرتبط با جایگزینی گواهی را مسدود میکند. OWASP MSTG, 2024
نکات اصلی
Certificate Pinning — یک مکانیزم امنیتی است که در آن برنامه یک نمونه از گواهی سرور را ذخیره میکند (یا «میدوزد» — pin) و در هر اتصال، گواهی دریافتی را با این نمونه مقایسه میکند. اگر گواهی مطابقت نداشته باشد — حتی اگر به طور رسمی توسط یک مرکز صدور گواهی معتبر امضا شده باشد — اتصال قطع میشود. این کار در برابر حملاتی محافظت میکند که در آن مهاجم از طریق یک CA به خطر افتاده گواهی جعلی دریافت میکند (مانند اتفاقاتی که با DigiNotar در 2011 یا Comodo در 2011 رخ داد).
فرآیند pinning از سه مرحله تشکیل شده است: استخراج اثر انگشت (fingerprint) گواهی یا کلید عمومی از یک نمونه معتبر؛ ذخیره این اثر انگشت در کد یا منابع برنامه؛ مقایسه در مرحله TLS-handshake. توسعهدهنده میتواند اثر SHA-256 کل گواهی یا فقط کلید عمومی (Public Key Pinning) را ثبت کند. رویکرد دوم ترجیح داده میشود: هنگام تمدید گواهی، کلید عمومی اغلب ثابت میماند و برنامه ارتباط خود را با سرور از دست نمیدهد. طبق توصیه OWASP حداقل تعداد پینها — ۲: یکی فعلی و یکی پشتیبان برای مواقع چرخش کلیدها. کتابخانههای مدرن مانند OkHttp و TrustKit فرآیند بررسی پینهای مشخص شده را در هر اتصال TLS بدون هزینه اضافی برای توسعهدهنده خودکار میکنند. مهم است بدانید که pinning جایگزین بررسی استاندارد TLS نمیشود، بلکه آن را تکمیل میکند: ابتدا handshake معمولی با اعتبارسنجی زنجیره گواهی انجام میشود و سپس — بررسی pinning اضافی. چنین محافظت دو سطحی آسیبپذیریهای مرتبط با به خطر افتادن CA، از جمله موارد صدور اشتباه گواهی و حملات به زیرساخت مراکز صدور گواهی را برطرف میکند.
چندین رویکرد برای پیادهسازی Certificate Pinning وجود دارد که هر کدام ویژگیهای ذخیرهسازی و بررسی خاص خود را دارند. انتخاب روش به معماری برنامه، دفعات بهروزرسانی گواهیها و الزامات انعطافپذیری بستگی دارد.
| نوع pinning | چه چیزی ذخیره میشود | انعطافپذیری | مثال استفاده |
|---|---|---|---|
| Certificate Pinning | کل گواهی X.509 | کم | گواهی ثابت برای ۱–۲ سال |
| Public Key Pinning | کلید عمومی (SPKI) | متوسط | رویکرد توصیه شده OWASP |
| Hash Pinning | اثر SHA-256 | متوسط | محبوب در OkHttp (certificatePinner) |
| CA Pinning | CA میانی | زیاد | برنامههای سازمانی |
متعادلترین روش Public Key Pinning است که توسط OWASP و Google توصیه میشود. به جای گواهی خاص (که هر ۱–۲ سال تغییر میکند) برنامه اثر SubjectPublicKeyInfo — انتزاع کلید عمومی — را ذخیره میکند. اگر گواهی با همان کلید تمدید شود (key reuse)، پین معتبر باقی میماند. اگر کلید تغییر کند — توسعهدهنده از قبل یک پین پشتیبان در بهروزرسانی برنامه اضافه میکند. در پروژههای موبایل از استراتژی min/max pins استفاده میشود: حداقل ۲ پین، از جمله پشتیبان، و حداکثر ۴ برای جلوگیری از بزرگ شدن و افزایش زمان بررسی.
انتخاب نوع خاص pinning به معماری و الزامات برنامه بستگی دارد. برای برنامههای موبایل عمومی که از طریق یک دامنه با REST API کار میکنند، Public Key Pinning با دو پین از طریق OkHttp یا TrustKit بهینه است. برای برنامههای سازمانی با مرکز صدور گواهی خود، CA Pinning مناسب است — هنگام تغییر گواهیهای مشتری نیازی به بهروزرسانی ندارد، زیرا اعتماد به CA متصل است نه به گواهی نهایی. برای سیستمهای IoT و embedded، Certificate Pinning با ثبت کامل گواهی توصیه میشود: دستگاهها به ندرت بهروزرسانی میشوند، بنابراین کنترل بر کل زنجیره اعتماد حیاتی است. نظارت بر تاریخ انقضای پینها — یک عمل اجباری است: هشدارهایی را ۳۰، ۱۴ و ۷ روز قبل از انقضای گواهی تنظیم کنید تا قبل از نامعتبر شدن گواهی فعلی، بهروزرسانی برنامه با پینهای جدید منتشر شود. برای خودکارسازی انتشار بهروزرسانیها با پینهای جدید، توصیه میشود از Firebase Remote Config یا API پیکربندی خود استفاده کنید که امکان بهروزرسانی پویای لیست پینها را بدون انتشار نسخه جدید در فروشگاه برنامه فراهم میکند.
Certificate Pinning امنیت برنامه موبایل را به طور قابل توجهی افزایش میدهد، اما بار عملیاتی را بر تیم توسعه تحمیل میکند. مهم است که مزایای محافظت و خطر مسدود شدن اتصال در صورت پیادهسازی نادرست را بسنجید.
مزیت اصلی — محافظت در برابر حملات Man-in-the-Middle، از جمله موارد به خطر افتادن CA است. Pinning گواهیهای جعلی صادر شده توسط مهاجم را بیفایده میکند: حتی اگر CA یک جعلی را امضا کند، برنامه آن را رد میکند. مزیت اضافی — محافظت در برابر پروکسیهای سازمانی که گواهیها را برای بازرسی ترافیک جایگزین میکنند. طبق Google Security Blog (2023)، برنامههای دارای pinning در مقایسه با برنامههایی که فقط از بررسی استاندارد TLS استفاده میکنند، ۸۶٪ شانس کمتری برای هک شدن از طریق رهگیری ترافیک دارند.
عیب اصلی pinning — خطر خود مسدود شدن است: اگر گواهی سرور قبل از انتشار بهروزرسانی برنامه تغییر کند (تمدید، تغییر ارائهدهنده، چرخش کلیدها)، کاربران دسترسی به سرور را از دست میدهند. معایب اضافی: دشواری اشکالزدایی (در هر تغییر تنظیمات باید پینها را بهروز کنید)، افزایش اندازه APK به میزان ۵–۱۵ کیلوبایت هنگام استفاده از TrustKit و عدم امکان بازگردانی سریع تغییرات بدون نسخه جدید. برای به حداقل رساندن خطرات، از پینهای پشتیبان، چرخش خودکار هر ۲–۳ ماه و دوره گذار (grace period) استفاده میشود که در آن برنامه هم گواهی قدیمی و هم جدید را میپذیرد. همچنین مهم است در نظر بگیرید که هنگام توسعه با pinning فعال، نمیتوان از ابزارهای پروکسی (Burp Suite, Charles) برای اشکالزدایی درخواستهای شبکه استفاده کرد — برای ساختهای توسعه، pinning باید از طریق پرچم BuildConfig.DEBUG غیرفعال شود و آزمایش QA باید بر روی امضای انتشار با محافظت فعال انجام شود. برخی تیمها از دامنه staging با گواهی pinning جداگانه برای محیط توسعه استفاده میکنند تا محافظت را حتی در مرحله توسعه حفظ کنند.
نمونه پیادهسازی Certificate Pinning در Android با استفاده از OkHttp — کتابخانه استاندارد برای درخواستهای شبکه — را بررسی میکنیم. OkHttp CertificatePinner داخلی را فراهم میکند که هشهای SHA-256 کلیدهای عمومی را میپذیرد.
val certificatePinner = CertificatePinner.Builder()
.add(
"api.example.com",
"sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
)
.add(
"api.example.com",
"sha256/BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB="
)
.build()
val client = OkHttpClient.Builder()
.certificatePinner(certificatePinner)
.build()
در کد بالا دو پین برای دامنه api.example.com اضافه میکنیم: اصلی (گواهی فعلی) و پشتیبان (برای مواقع چرخش). OkHttp به طور خودکار بررسی میکند که گواهی سرور با یکی از اثرهای SHA-256 مشخص شده مطابقت دارد. برای دریافت اثر SHA-256 گواهی از دستور استفاده میشود: openssl s_client -connect api.example.com:443 | openssl x509 -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | base64. مهم است که اثرها را نه به صورت آشکار در کد، بلکه رمزگذاری شده یا مبهم ذخیره کنید: تحلیل ایستای MobSF به راحتی رشتههای خام SHA-256 را در فایلهای DEX پیدا میکند. توصیه میشود پینها را در منابع res/raw رمزگذاری شده با AES ذخیره کرده و در هنگام راهاندازی برنامه از طریق کد بومی (NDK/JNI) رمزگشایی کنید.
در iOS ابزار اصلی Certificate Pinning کتابخانه منبعباز TrustKit است. برخلاف OkHttp، TrustKit به صورت اعلامی از طریق Info.plist پیکربندی میشود که امکان تغییر پینها را بدون کامپایل مجدد برنامه فراهم میکند. پیکربندی شامل یک دیکشنری با دامنهها و آرایهای از اثرهای SHA-256 کلیدهای عمومی است. TrustKit به طور خودکار درخواستهای NSURLSession را رهگیری میکند و گواهیها را قبل از شروع انتقال داده بررسی میکند. ویژگی کلیدی TrustKit — پشتیبانی از گزارشهای تأیید پین: کتابخانه میتواند در صورت عدم مطابقت پین، گزارشهایی را به endpoint مشخص شده ارسال کند که امکان واکنش سریع به ناهنجاریهای گواهی را فراهم میکند. Apple همچنین مکانیزم بومی NSPinnedDomains را در Info.plist از iOS 14 فراهم میکند، اما TrustKit به دلیل پیکربندی انعطافپذیرتر، پشتیبانی از گزارشها و امکان تعویض داغ پینها بدون بهروزرسانی سیستم، انتخاب ارجح باقی میماند. TrustKit از طریق دلیگیت didReceiveChallenge با URLSession ادغام میشود و در صورت تأیید موفق پین .performDefaultHandling و در صورت عدم مطابقت .cancelAuthenticationChallenge را برمیگرداند. برای نظارت بر گزارشهای تأیید پین، توصیه میشود یک endpoint جداگانه تنظیم کنید که فراوانی خطاها را تحلیل میکند: اگر تعداد گزارشها به شدت افزایش یابد — این میتواند نشاندهنده حمله MitM یا نزدیک شدن به انقضای گواهی باشد که نیاز به بهروزرسانی فوری پینها دارد.
سوالات متداول
Certificate Pinning — مانند ذخیره اثر انگشت دوست در تلفن است: شما به یاد میسپارید که گواهی «درست» سرور چگونه به نظر میرسد و به هیچ کس دیگری اعتماد نمیکنید، حتی اگر کسی گواهی از یک مرکز «رسمی» ارائه دهد.
HTTPS معمولی به هر گواهی امضا شده توسط هر CA از صدها مرکز اعتماد میکند. Certificate Pinning یک بررسی «از بالا» اضافه میکند: گواهی نه تنها باید معتبر باشد، بلکه باید دقیقاً همان گواهی باشد که شما در کد برنامه ثبت کردهاید.
توصیه میشود ۲–۳ پین ذخیره کنید: فعلی و پشتیبان برای گواهی جدید. ۱–۲ ماه قبل از تغییر گواهی، نسخه جدید برنامه را با پین گواهی آینده اضافه شده منتشر کنید. پس از تغییر، پین قدیمی از نسخه بعدی حذف میشود.
بله، میتوان. Pinning با هر گواهی از جمله Let's Encrypt کار میکند. مهم است به خاطر داشته باشید که گواهیهای رایگان مدت اعتبار کوتاهی دارند (۳ ماه)، بنابراین استراتژی پینهای پشتیبان و چرخش خودکار اجباری میشود.
برای تست pinning از Burp Suite یا mitmproxy استفاده کنید. اگر برنامه با pinning به درستی پیکربندی شده باشد، ابزار پروکسی نمیتواند ترافیک را رهگیری کند — اتصال در مرحله handshake قطع میشود. برای تستهای یکپارچهسازی از MockWebServer OkHttp استفاده کنید.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید