ضعفهای رمزنگاری (Weak Cryptography)
رمزنگاری ستون فقرات امنیت دادههاست. اما استفاده از الگوریتمهای منسوخ شده، شیوه عملکرد اشتباه (مانند ECB) یا تولید اعداد تصادفی قابل پیشبینی، میتواند قدرتمندترین مکانیزمهای امنیتی را به یک قفل کاغذی تبدیل کند.
در تست نفوذ، ما به دنبال "رمزنگاریهای شکسته" یا "پیادهسازیهای غلط" میگردیم.
۱. الگوریتمهای منسوخ شده (Legacy Algorithms)
برخی الگوریتمها که در دهه ۹۰ میلادی امن بودند، امروزه با قدرت پردازشی گوشیهای موبایل در چند ثانیه شکسته میشوند. اگر این نامها را در کد دیدید، یک آسیبپذیری قطعی پیدا کردهاید:
- DES / 3DES: طول کلید بسیار کوتاه (۵۶ بیت) که به راحتی Brute-force میشود.
- RC4: دارای ضعفهای آماری شدید در تولید جریان کلید (Keystream).
- MD5 / SHA-1: برای هشینگ استفاده میشوند اما به دلیل آسیبپذیری "تصادم" (Collision)، دیگر امن نیستند.
نمونه کد آسیبپذیر:
/* استفاده از الگوریتم ضعیف DES */
Cipher cipher = Cipher.getInstance("DES");
/* استفاده از MD5 برای هش کردن پسورد (قابل کرک شدن) */
MessageDigest md = MessageDigest.getInstance("MD5");۲. شیوه عملکرد ناامن: AES-ECB
مهمترین آسیبپذیری رمزنگاری در اندروید، استفاده از AES در حالت ECB (Electronic Code Book) است. در این حالت، بلاکهای داده مشابه، دقیقا خروجی رمزنگاری شده مشابهی تولید میکنند. این یعنی الگوهای داده (Patterns) در متن رمزنگاری شده باقی میمانند.
هشدار جدی
اگر در کد جاوا Cipher.getInstance("AES") را ببینید و شیوه عملکرد مشخص نشده باشد، در بسیاری از نسخههای قدیمی اندروید به طور پیشفرض ECB انتخاب میشود.
کد آسیبپذیر (ECB):
/* خطرناک: استفاده از AES بدون مشخص کردن شیوه (پیشفرض در برخی نسخهها ECB است) */
Cipher c = Cipher.getInstance("AES");
/* خطرناک: استفاده صریح از ECB */
Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding");
/* روش صحیح و امن: */
// Cipher c = Cipher.getInstance("AES/GCM/NoPadding");۳. استفاده از اعداد تصادفی ناامن (Insecure PRNG)
کلیدهای رمزنگاری و IV (Initialization Vector) باید کاملا غیرقابل پیشبینی باشند. اگر توسعهدهنده از کلاس java.util.Random استفاده کند، اعداد تولید شده "قطعی" (Deterministic) هستند. یعنی اگر زمان تولید عدد (Seed) را بدانید، میتوانید کلید رمزنگاری را حدس بزنید.
- راه حل امن: همیشه باید از
java.security.SecureRandomاستفاده شود.
کد آسیبپذیر (Random):
/* تولید کلید رمزنگاری با Random معمولی */
import java.util.Random;
Random weakRandom = new Random();
/* اگر هکر زمان دقیق (System.currentTimeMillis) را بداند، کلید را حدس میزند */
int keyPart = weakRandom.nextInt();
/* روش صحیح: */
// SecureRandom secureRandom = new SecureRandom();۴. رمزنگاریهای سفارشی (Custom / Rolling your own Crypto)
بدترین نوع رمزنگاری زمانی است که برنامهنویس تصمیم میگیرد الگوریتم خودش را بنویسد.
معمولا این کار با استفاده از XOR کردن دادهها با یک رشته ثابت انجام میشود. این روش رمزنگاری نیست، بلکه صرفا "مبهمسازی" (Obfuscation) است و با تحلیل فرکانسی ساده شکسته میشود.
نمونه کد سفارشی (XOR):
public String sillyEncryption(String input) {
char[] key = {'S', 'e', 'c', 'r', 'e', 't'};
StringBuilder output = new StringBuilder();
for(int i = 0; i < input.length(); i++) {
/* عملیات XOR ساده که به راحتی برگشتپذیر است */
output.append((char) (input.charAt(i) ^ key[i % key.length]));
}
return output.toString();
}