DevByte
security ops
[ok]ایمن‌سازی کانال ارتباطی …
loading assets000%
رفتن به محتوای اصلی
بازگشت به مقالات
موبایل۱۴۰۵/۲/۳۱·۱۴ دقیقه

دور زدن TLS Pinning در اندروید با Frida روی نسخه منتشرشده

پینینگ کردن گواهی یک لایه است، نه یک دیوار. این راهنما مسیر کامل از شناسایی ابزار پینینگ تا قلاب‌گذاری تابع اعتبارسنجی را، روی یک APK واقعی از فروشگاه، قدم‌به‌قدم نشان می‌دهد.

AndroidFridaReverse EngineeringMASVS

خلاصه کلیدی

پینینگ گواهی یک لایه است، نه یک دیوار. مسیر واقعی دور زدن آن روی یک APK منتشرشده، از شناسایی کتابخانه تا قلاب‌گذاری تابع بررسی، مشخص و تکرارپذیر است.

تقریباً هر تیم موبایل در سال‌های اخیر یکی از این سه کار را انجام داده است: پینینگ گواهی را فعال کرده، از پروکسی شبکه داخلی خودداری کرده، یا هر دو. این تصمیم‌ها ارزشمندند — اما اغلب با این باور همراه می‌شوند که اپلیکیشن حالا «فقط از طریق کانال امن ارتباط برقرار می‌کند». این باور، نادرست است.

گام ۱: شناسایی کتابخانه پینینگ

پیش از هر قلاب‌گذاری، باید بدانید با چه چیزی طرفید. سه خانواده رایج وجود دارد و هر کدام راه‌حل متفاوتی می‌خواهد:

  • OkHttp CertificatePinner — جدیدترین پروژه‌های اندروید؛ در فراخوانی `CertificatePinner.check()` قابل مشاهده است.
  • TrustManager / X509TrustManager سفارشی — کلاس‌هایی با نام‌هایی مثل `CustomTrustManager` یا `PinnedTrustManager` در decompile دیده می‌شوند.
  • network_security_config.xml — پیکربندی اعلام‌شده در مانیفست؛ ضعفی که با تغییر فایل در APK رفع می‌شود.
bash
# pull and decompile the real store build
apktool d app-release.apk -o out

# look for OkHttp pinning
grep -rn "CertificatePinner\|certificatePinner" out/smali* | head

# look for a custom TrustManager
grep -rln "X509TrustManager\|checkServerTrusted" out/smali* | head

# check the declared security config
grep -rn "networkSecurityConfig" out/AndroidManifest.xml
cat out/res/xml/network_security_config.xml
شناسایی سریع در نسخه منتشرشده

گام ۲: قلاب‌گذاری فراخوانی بررسی گواهی

در اینجا Frida وارد می‌شود. ما فراخوانی اعتبارسنجی را قلاب می‌زنیم و اعتبار یک گواهی تولیدشده محلی را برمی‌گردانیم. نکته مهم این است که این کار را روی نسخه منتشرشده از فروشگاه انجام می‌دهیم، نه روی بیلد دیباگ — چون بیلد دیباگ معمولاً متفاوت است و نتیجه قابل اتکا نیست.

javascript
Java.perform(function () {
  var Pinner = Java.use("okhttp3.CertificatePinner");

  Pinner.check.overload("java.lang.String", "java.util.List")
    .implementation = function (hostname, pins) {
      console.log("[*] pinned host: " + hostname);
      // bypass: return without throwing
      return;
    };

  // also cover the varargs form used on some versions
  try {
    Pinner.check.overload("java.lang.String", "java.util.List[]")
      .implementation = function (hostname, pins) {
        console.log("[*] pinned host: " + hostname);
        return;
      };
  } catch (e) { /* not present on this version */ }
});
اسکریپت Frida برای OkHttp CertificatePinner
bash
# 1. device with USB debugging (or an emulator you control)
adb devices

# 2. spawn the real process so hooks land before startup
frida -U -f com.target.app -l bypass-pinning.js --no-pause

# 3. confirm the hook fired
#    [*] pinned host: api.target.com
اجرا روی دستگاه متصل

گام ۳: چه چیزی بعد از پینینگ پیدا می‌شود

پینینگ معمولاً تنها آخرین لایه‌ای نیست که در تست‌های ما کنار می‌رود. پس از باز شدن کانال، معمولاً با این موارد روبه‌رو می‌شویم:

  • توکن نشست که پس از تغییر شماره تلفن یا ایمیل، بدون احراز هویت مجدد صادر می‌شود.
  • رمزنگاری محلی که کلیدش از یک مقدار ثابت در کد می‌آید.
  • اعتبارسنجی سمت سرور که به یک هدر غیرقابل‌جعل اتکا می‌کند.
  • داده‌های حساس که در SharedPreferences بدون رمزنگاری ذخیره می‌شوند.
  • منابعی که مستقیماً از APK قابل استخراج‌اند و نباید باشند.

دفاع درست: لایه‌بندی به جای یک لایه

توصیه ما به تیم‌هایی که با این نتیجه مواجه می‌شوند ساده است: پینینگ را نگه دارید، اما آن را به‌عنوان تنها دفاع حساب نکنید. یک دفاع لایه‌بندی‌شده به این ترتیب ساخته می‌شود:

  1. 1اعتبارسنجی سمت سرور، همیشه. هیچ تصمیم امنیتی نباید به داده‌ای که کلاینت می‌فرستد تکیه کند.
  2. 2توکن‌های کوتاه‌عمر با امکان باطل‌سازی واقعی، نه توکن‌های بلندعمر که فقط رمزنگاری دارند.
  3. 3ذخیره‌سازی محلی با کلید مشتق‌یافته از Keystore سیستم‌عامل، نه از یک ثابت در کد.
  4. 4پینینگ گواهی، به‌عنوان یک لایه در انتهای زنجیره.

اگر تنها کاری که می‌توانید انجام دهید یک لایه است، آن لایه باید جایی باشد که حداکثر ارزش را دارد — نه جایی که پیاده‌سازی‌اش آسان‌تر است.

DevByte Research
تیم تست نفوذ و مهندسی معکوس