презентацию

Практические советы по
выживанию Android и iOSприложений в недоверенном
окружении
Михаил Дударев
Licel, 2015
О себе
Михаил Дударев - эксперт в области
технологий Java Card и безопасности
мобильных устройств, технический
консультант Global Platform.
О нас
•
LICEL занимается
созданием решений для
защиты программного от
нелегального
использования и
модификации третьими
лицами для Java и Android
платформ.
•
jCardSim - реализация Java
Card с открытым исходным
кодом, получившая самую
престижную мировую
премию для разработчиков
программного обеспечения
Oracle Duke’s Choice Awards
2013.
Краткое содержание
• Предполетный check-in
• Анализ окружающей среды. Детектирование
root/jailbreak и других признаков «иной»
активности
• Наследие ушедших цивилизаций. Как не
попасть под false positive антивируса, и что
делать если «попали».
Предполетный check-in
Проверка содержимого APK
• Структура APK
– META-INF
– assets/
– lib/
– res/
– classes.dex
– resources.arsc
Инструменты (бесплатные!): ApkTool, Androguard, Dex2jar
Проверка содержимого APK
• В APK не стоит хранить
– исходные файлы (*.java)
– Java байткод (*.class)
– Java библиотеки (*.jar)
– метафайлы IDE для сборки проекта
Инструменты (бесплатные!): ApkTool, Androguard, Dex2jar
Анализ Dalvik байткода
• Вызовы критичных функций
– Работа с криптографией
– Системы лицензирования
– Работа с пользовательскими данными
– Взаимодействие с сервером
• соединение
• аутентификация
Инструменты (бесплатные!): ApkTool, Smali, Dex2jar
Механизмы контроля целостности
APK - файл
APK - файл
Замер
Хеш()
Контроль
Доверенная среда
Успех/
Ошибка
Замер
Состояние
Недоверенная среда
Контроль APK
PackageManager pm = context.getPackageManager();
PackageInfo info = pm.getPackageInfo(context.getPackageName(),
PackageManager.GET_SIGNATURES);
if(info.signatures[0].toCharsString().equals(YOUR_SIGNATURE))
{
//signature is OK
}
Контроль APK
PackageManager pm = context.getPackageManager();
PackageInfo info = pm.getPackageInfo(context.getPackageName(),
PackageManager.GET_SIGNATURES);
AuthStateManager am = AuthStateManager.getInstance();
am.updateInternalState(info.signatures[0].toCharsString());
Обфускация с помощью ProGuard
• Подход заключается в переименовывании
классов/методов/переменных
• Требует нетривиальной конфигурации
• Производится на этапе компиляции
• Оптимизирует размер кода
Обфускация с помощью ProGuard.
Минусы
•
•
•
•
Мнимая защита
Приложение легко модифицировать
Нельзя спрятать вызовы API
Нет механизмов защиты целостности
Продвинутые методы защиты
• Защита приложения
–
–
–
–
–
Шифрование кода
Шифрование ресурсов
Контроль целостности
Защита API (сокрытие)
O-LLVM и NDK
• Защита данных приложения и пользователя
Инструменты (Платные) DexProtector, DexGuard
Шифрование строк и защита API
на примере Google Play LVL. До..
// Google Play LVL Sample
public class MainActivity extends Activity {
private static final String BASE64_PUBLIC_KEY = “PUBLIC KEY”;
private static final byte[] SALT = new byte[] {..};
private LicenseCheckerCallback mLicenseCheckerCallback;
private LicenseChecker mChecker;
@Override
public void onCreate(Bundle savedInstanceState) {
// Getting the ID of a device
String deviceId= Secure.getString(getContentResolver(),Secure.ANDROID_ID);
// Initializing the license checker classes
mLicenseCheckerCallback = new MyLicenseCheckerCallback();
mChecker = new LicenseChecker(this, new ServerManagedPolicy(this,
new AESObfuscator(SALT, getPackageName(), deviceId)),
BASE64_PUBLIC_KEY);
// Checking the license
mChecker.checkAccess(mLicenseCheckerCallback); }
}
Шифрование строк и защита API
на примере Google Play LVL. После..
Object localObject = ha.kkbab(ha.pnbab(this), R.MainActivity.1.access$300("犆讞燮‫ ﵷ‬葃䷿뎟"));
ha.mlmbo(this, ha.ilbab(this, null), 4140);
ha.mlmbo(this, ha.fgbab(this, ha.kjbab(this, ha.libab((byte[])ha.kllgi(4141), ha.mmdab(this),
localObject)), R.MainActivity.1.access$300("犪讽燺‫ ﵕ‬萗䷿뎵ꀙ黖返邝鷂睪螂䨎 븂⨄‫ צ‬舣 쫋쁄봲浽
䷿ᖻ䷿豧椘╋爬䷿ᄣホ绛肷顣䷿㙵
䌖䷿ꏴ驻掇㛏˓⭊⤹敔䏁ꅥ䷿䷿䷿䷿款엾騩ⵥ⾦㣂㔞췐鳒삮ὃɃ힀↲粓줓 빼碔
Ᏸ䶯䷿姧꾮ืҒ╋珖ȳ䧗굵ᙏ摎헟ֽ쾽羪䷿硰䨌쨆Ⰸ޴냴 ꌒ睇云묠蚃급켌 ነ鞤낗蚜뤫훴鋙䋩ඣ 瓚逯貚ꏵ
㤁⃟㏢䚗댜হ즙䷿䌪웂래뗬㆚耥풑칝鎰먋菲취ϩ弫匆希⩴䷿䡢ᔂ嫵率䷿əኔ拏辛 䔗 돶 ൗ ䷿醗곃䷿ 挺驐薡
䷿瘧㯑޴뿔뻔未汊盧䈵 솔躤鞽⣾ಱዓ灐쮀毄宽씤 ş У請혛㱂졌")), 4138);
ha.ikcab(this);
Шифрование данных
РЕЦЕПТ
ОТ
ГРОМОЗЕКИ
Шифрование данных приложения
Приправы (соль/перец)
SecureRandom srnd = new SecureRandom();
byte[] salt = new byte[saltLength];
srnd.nextBytes(salt);
byte[] iv = new byte[ivLength];
srnd.nextBytes(iv);
Шифрование данных приложения
Основной ингредиент (следим за качеством продукта)
KeySpec keySpec = new PBEKeySpec(password.toCharArray(),
salt,
iterationCount, keyLength);
SecretKeyFactory keyFactory = SecretKeyFactory
.getInstance("PBKDF2WithHmacSHA1");
byte[] keyBytes = keyFactory.generateSecret(keySpec).getEncoded();
SecretKey key = new SecretKeySpec(keyBytes, "AES")
Шифрование данных приложения
Процедура готовки (тщательно перемешиваем и следим за
объемом)
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
IvParameterSpec ivParams = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, key, ivParams);
byte[] ciphertext = cipher.doFinal(plaintext);
Анализ окружающей среды
Детектирование аномалий
• Проверка на root
– Наличие в сборке тестовых ключей
– Установленные подозрительные приложения
– Наличия su пользователя или su-консолей
– Нестандартные системные файлы
Инструменты (бесплатные!): https://github.com/Stericson/RootTools
Детектирование аномалий
• Состояние WIFI
–
–
–
–
Алгоритмы шифрования
Механизмы аутентификации
Список доступных сетей
Предыдущая выбранная сеть
Работа с результатами анализа
AuthStateManager am = AuthStateManager.getInstance();
am.updateInternalState(AnomalyDetector.testBuildKeys());
am.updateInternalState(AnomalyDetector.listApplications());
am.updateInternalState(AnomalyDetector.listSuShels());
am.updateInternalState(AnomalyDetector.calcFirmareChecksum());
am.updateInternalState(AnomalyDetector.getWifiState());
SSL Pinning (iOS)
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;
SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, 0);
NSData *remoteCertificateData = CFBridgingRelease(SecCertificateCopyData(certificate));
NSData *xxxCertData = [self xxxCert];
if ([remoteCertificateData isEqualToData:xxxCertData] || [self isSSLPinning] == NO) {
if ([self isSSLPinning] || [remoteCertificateData isEqualToData:xxxCertData]) {
[self printMessage:@"The server's certificate is the valid xxx certificate. Allowing the request."];
}
else {
[self printMessage:@"The server's certificate does not match xxx.com. Continuing anyway."];
}
NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust];
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
}
else {
[self printMessage:@"The server's certificate does not match xxx.com. Canceling the request."];
[[challenge sender] cancelAuthenticationChallenge:challenge];
}
}
SSL Pinning (Android)
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException
{
String PUB_KEY = ”...”;
// Perform customary SSL/TLS checks
TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
tmf.init((KeyStore) null);
for (TrustManager trustManager : tmf.getTrustManagers()) {
((X509TrustManager) trustManager).checkServerTrusted(chain, authType);
}
String encoded = new BigInteger(1, RSAPublicKey) chain[0].getPublicKey().getEncoded()).toString(16);
// Pin it!
if (!PUB_KEY.equalsIgnoreCase(encoded)) {
throw new CertificateException("checkServerTrusted: Expected public key: "
+ PUB_KEY + ", got public key:" + encoded);
}
}
}
SSL Pinning (Атаки)
– Сертификат внутри приложения может быть
подменен
– Сертификат сервера может быть навязан
– Функция валидации сертификата может быть
заменена
Эксплуатация уязвимостей:
Android SSL Bypass/Android-SSL-TrustKiller/iOS SSL Kill Switch
SSL Pinning. Как обезопасить?
AndroidKeyStore
– Хранение ключевых пар (RSA/EC)
– Хранение сертификатов
– Операции подписи/проверки подписи
KeyChain
– Доступ к системному хранилищу ключевой
информации и сертификатов
Выводы
– Контролируйте целостность и состояние
приложения
– Управляйте рисками на сервере
– Защищайте пользовательские данные
– Используйте возможности аппаратной
платформы
Контакты
•
•
•
•
Email: [email protected]
Twitter: @MikhailDudarev
Web: http://licelus.com
DexProtector: http://dexprotector.com