Nativescript - 在 iOS 上检测越狱和动态检测
Nativescript - Detect Jailbreak and Dynamic Instrumentation on iOS
考虑到 Nativescript 社区中可用的插件,您的 Nativescript 应用可能足以通过安全渗透测试,也可能不足以通过安全渗透测试。
下面列出了两个插件。
- https://www.npmjs.com/package/@nstudio/root-detection
- https://www.npmjs.com/package/nativescript-jailbreak-detector
在某些情况下,您可以通过手动编写自己的越狱和动态检测(例如 Frida)检查来获得更好的结果,因为现在有很多工具可以绕过越狱检测(例如 HideJB)。
我们可以通过哪些方法检测越狱并防止 iOS Nativescript 上的动态检测?
可进行多层次检测:
- 检查 URL 是否可以通过非法 URL 方案打开
- 检查非法目录中的文件是否可打开
- 检查是否存在非法文件(包括Cydia、Sileo、HideJB等)
- 检查受限目录中的文件是否可写
代码
public amIJailbroken(): boolean {
let urlSchemes: Array<string> = ['undecimus://', 'cydia://', 'sileo://', 'zbra://', 'filza://', 'activator://'];
// List of suspicious files associated with jailbreak
let paths: Array<string> = [
'/.bootstrapped_electra',
'/.cydia_no_stash',
'/.installed_unc0ver',
'/Applications/blackra1n.app',
'/Applications/Cydia.app',
'/Applications/FakeCarrier.app',
'/Applications/HideJB.app',
'/Applications/Icy.app',
'/Applications/IntelliScreen.app',
'/Applications/MxTube.app',
'/Applications/RockApp.app',
'/Applications/SBSettings.app',
'/Applications/SBSetttings.app',
'/Applications/Sileo.app',
'/Applications/Snoop-itConfig.app',
'/Applications/WinterBoard.app',
'/bin.sh',
'/bin/bash',
'/bin/sh',
'/etc/apt',
'/etc/apt/sources.list.d/electra.list',
'/etc/apt/sources.list.d/sileo.sources',
'/etc/apt/undecimus/undecimus.list',
'/etc/ssh/sshd_config',
'/jb/amfid_payload.dylib',
'/jb/jailbreakd.plist',
'/jb/libjailbreak.dylib',
'/jb/lzma',
'/jb/offsets.plist',
'/Library/dpkg/info/re.frida.server.list',
'/Library/LaunchDaemons/re.frida.server.plist',
'/Library/MobileSubstrate/CydiaSubstrate.dylib',
'/Library/MobileSubstrate/DynamicLibraries/LiveClock.plist',
'/Library/MobileSubstrate/DynamicLibraries/Veency.plist',
'/Library/MobileSubstrate/HideJB.dylib',
'/Library/MobileSubstrate/MobileSubstrate.dylib',
'/Library/PreferenceBundles/ABypassPrefs.bundle',
'/Library/PreferenceBundles/FlyJBPrefs.bundle',
'/Library/PreferenceBundles/HideJBPrefs.bundle',
'/Library/PreferenceBundles/LibertyPref.bundle',
'/Library/PreferenceBundles/ShadowPreferences.bundle',
'/private/etc/apt',
'/private/etc/dpkg/origins/debian',
'/private/etc/ssh/sshd_config',
'/private/var/cache/apt/',
'/private/var/lib/apt',
'/private/var/lib/apt/',
'/private/var/lib/cydia',
'/private/var/log/syslog',
'/private/var/mobile/Library/SBSettings/Themes',
'/private/var/mobileLibrary/SBSettingsThemes/',
'/private/var/stash',
'/private/var/tmp/cydia.log',
'/private/var/Users/',
'/System/Library/LaunchDaemons/com.ikey.bbot.plist',
'/System/Library/LaunchDaemons/com.saurik.Cydia.Startup.plist',
'/usr/bin/cycript',
'/usr/bin/ssh',
'/usr/bin/sshd',
'/usr/lib/libcycript.dylib',
'/usr/lib/libhooker.dylib',
'/usr/lib/libjailbreak.dylib',
'/usr/lib/libsubstitute.dylib',
'/usr/lib/substrate',
'/usr/lib/TweakInject',
'/usr/libexec/cydia/',
'/usr/libexec/cydia/firmware.sh',
'/usr/libexec/sftp-server',
'/usr/libexec/ssh-keysign',
'/usr/local/bin/cycript',
'/usr/sbin/frida-server',
'/usr/sbin/sshd',
'/usr/share/jailbreak/injectme.plist',
'/var/binpack',
'/var/cache/apt',
'/var/checkra1n.dmg',
'/var/lib/apt',
'/var/lib/cydia',
'/var/lib/dpkg/info/mobilesubstrate.md5sums',
'/var/log/apt',
'/var/log/syslog',
'/var/tmp/cydia.log',
];
// Check if target is not an iOS simulator
if (!isIOS || !this.isTarget()) return false;
else {
// Check URL schemes
for (const url of urlSchemes) {
if (this.canOpenIllegalURL(url)) return true;
}
// Check files and directories associated with jailbreaks
for (const path of paths) {
if (this.canOpenIllegalFile(path)) return true;
}
// Check file permissions outside device sandbox, if writtable = jailbroken
if (this.canWriteToRestrictedDirectories()) return true;
return false;
}
}
/*
********** Helper Methods **********
*/
/* Check if environment is being run as a RELEASE build */
private isTarget() {
return process.env.RELEASE_ENV;
}
/* Check if we can open illegal URL schemes */
private canOpenIllegalURL(url): boolean {
return UIApplication.sharedApplication.canOpenURL(NSURL.URLWithString(url + 'package/com.example.app'));
}
/* Check if file is openable */
private canOpenIllegalFile(path): boolean {
const file = fopen(path, 'r');
if (!file) {
fclose(file);
return this.fileExists(path) || this.directoryExists(path);
}
fclose(file);
return true;
}
/* Check if file exists at path */
private fileExists(path): boolean {
return NSFileManager.defaultManager.fileExistsAtPath(path);
}
/* Check if directory exists at path */
private directoryExists(path): boolean {
return NSFileManager.defaultManager.fileExistsAtPathIsDirectory(path, new interop.Reference());
}
/* Check if file is writtable to illegal directory */
private canWriteToRestrictedDirectories(): boolean {
let error;
try {
const stringToBeWritten = NSString.stringWithString('I am evil.');
stringToBeWritten.writeToFileAtomicallyEncodingError('/private/jailbreak.txt', true, NSUTF8StringEncoding);
stringToBeWritten.writeToFileAtomicallyEncodingError('/root/jailbreak.txt', true, NSUTF8StringEncoding);
NSFileManager.defaultManager.removeItemAtPathError('/private/jailbreak.txt');
NSFileManager.defaultManager.removeItemAtPathError('/root/jailbreak.txt');
} catch (e) {
error = e;
}
return !error ? true : false;
}
参考资料
研究来自对以下想法的整合:
- https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06j-testing-resiliency-against-reverse-engineering
- https://github.com/securing/IOSSecuritySuite/blob/master/IOSSecuritySuite/JailbreakChecker.swift
- https://github.com/avltree9798/isJailbroken/blob/master/isJailbroken/JB.m
改进
欢迎大家多多指教!
例如使用 _dyld_get_image_name
检查内存中的非法动态库
考虑到 Nativescript 社区中可用的插件,您的 Nativescript 应用可能足以通过安全渗透测试,也可能不足以通过安全渗透测试。
下面列出了两个插件。
- https://www.npmjs.com/package/@nstudio/root-detection
- https://www.npmjs.com/package/nativescript-jailbreak-detector
在某些情况下,您可以通过手动编写自己的越狱和动态检测(例如 Frida)检查来获得更好的结果,因为现在有很多工具可以绕过越狱检测(例如 HideJB)。
我们可以通过哪些方法检测越狱并防止 iOS Nativescript 上的动态检测?
可进行多层次检测:
- 检查 URL 是否可以通过非法 URL 方案打开
- 检查非法目录中的文件是否可打开
- 检查是否存在非法文件(包括Cydia、Sileo、HideJB等)
- 检查受限目录中的文件是否可写
代码
public amIJailbroken(): boolean {
let urlSchemes: Array<string> = ['undecimus://', 'cydia://', 'sileo://', 'zbra://', 'filza://', 'activator://'];
// List of suspicious files associated with jailbreak
let paths: Array<string> = [
'/.bootstrapped_electra',
'/.cydia_no_stash',
'/.installed_unc0ver',
'/Applications/blackra1n.app',
'/Applications/Cydia.app',
'/Applications/FakeCarrier.app',
'/Applications/HideJB.app',
'/Applications/Icy.app',
'/Applications/IntelliScreen.app',
'/Applications/MxTube.app',
'/Applications/RockApp.app',
'/Applications/SBSettings.app',
'/Applications/SBSetttings.app',
'/Applications/Sileo.app',
'/Applications/Snoop-itConfig.app',
'/Applications/WinterBoard.app',
'/bin.sh',
'/bin/bash',
'/bin/sh',
'/etc/apt',
'/etc/apt/sources.list.d/electra.list',
'/etc/apt/sources.list.d/sileo.sources',
'/etc/apt/undecimus/undecimus.list',
'/etc/ssh/sshd_config',
'/jb/amfid_payload.dylib',
'/jb/jailbreakd.plist',
'/jb/libjailbreak.dylib',
'/jb/lzma',
'/jb/offsets.plist',
'/Library/dpkg/info/re.frida.server.list',
'/Library/LaunchDaemons/re.frida.server.plist',
'/Library/MobileSubstrate/CydiaSubstrate.dylib',
'/Library/MobileSubstrate/DynamicLibraries/LiveClock.plist',
'/Library/MobileSubstrate/DynamicLibraries/Veency.plist',
'/Library/MobileSubstrate/HideJB.dylib',
'/Library/MobileSubstrate/MobileSubstrate.dylib',
'/Library/PreferenceBundles/ABypassPrefs.bundle',
'/Library/PreferenceBundles/FlyJBPrefs.bundle',
'/Library/PreferenceBundles/HideJBPrefs.bundle',
'/Library/PreferenceBundles/LibertyPref.bundle',
'/Library/PreferenceBundles/ShadowPreferences.bundle',
'/private/etc/apt',
'/private/etc/dpkg/origins/debian',
'/private/etc/ssh/sshd_config',
'/private/var/cache/apt/',
'/private/var/lib/apt',
'/private/var/lib/apt/',
'/private/var/lib/cydia',
'/private/var/log/syslog',
'/private/var/mobile/Library/SBSettings/Themes',
'/private/var/mobileLibrary/SBSettingsThemes/',
'/private/var/stash',
'/private/var/tmp/cydia.log',
'/private/var/Users/',
'/System/Library/LaunchDaemons/com.ikey.bbot.plist',
'/System/Library/LaunchDaemons/com.saurik.Cydia.Startup.plist',
'/usr/bin/cycript',
'/usr/bin/ssh',
'/usr/bin/sshd',
'/usr/lib/libcycript.dylib',
'/usr/lib/libhooker.dylib',
'/usr/lib/libjailbreak.dylib',
'/usr/lib/libsubstitute.dylib',
'/usr/lib/substrate',
'/usr/lib/TweakInject',
'/usr/libexec/cydia/',
'/usr/libexec/cydia/firmware.sh',
'/usr/libexec/sftp-server',
'/usr/libexec/ssh-keysign',
'/usr/local/bin/cycript',
'/usr/sbin/frida-server',
'/usr/sbin/sshd',
'/usr/share/jailbreak/injectme.plist',
'/var/binpack',
'/var/cache/apt',
'/var/checkra1n.dmg',
'/var/lib/apt',
'/var/lib/cydia',
'/var/lib/dpkg/info/mobilesubstrate.md5sums',
'/var/log/apt',
'/var/log/syslog',
'/var/tmp/cydia.log',
];
// Check if target is not an iOS simulator
if (!isIOS || !this.isTarget()) return false;
else {
// Check URL schemes
for (const url of urlSchemes) {
if (this.canOpenIllegalURL(url)) return true;
}
// Check files and directories associated with jailbreaks
for (const path of paths) {
if (this.canOpenIllegalFile(path)) return true;
}
// Check file permissions outside device sandbox, if writtable = jailbroken
if (this.canWriteToRestrictedDirectories()) return true;
return false;
}
}
/*
********** Helper Methods **********
*/
/* Check if environment is being run as a RELEASE build */
private isTarget() {
return process.env.RELEASE_ENV;
}
/* Check if we can open illegal URL schemes */
private canOpenIllegalURL(url): boolean {
return UIApplication.sharedApplication.canOpenURL(NSURL.URLWithString(url + 'package/com.example.app'));
}
/* Check if file is openable */
private canOpenIllegalFile(path): boolean {
const file = fopen(path, 'r');
if (!file) {
fclose(file);
return this.fileExists(path) || this.directoryExists(path);
}
fclose(file);
return true;
}
/* Check if file exists at path */
private fileExists(path): boolean {
return NSFileManager.defaultManager.fileExistsAtPath(path);
}
/* Check if directory exists at path */
private directoryExists(path): boolean {
return NSFileManager.defaultManager.fileExistsAtPathIsDirectory(path, new interop.Reference());
}
/* Check if file is writtable to illegal directory */
private canWriteToRestrictedDirectories(): boolean {
let error;
try {
const stringToBeWritten = NSString.stringWithString('I am evil.');
stringToBeWritten.writeToFileAtomicallyEncodingError('/private/jailbreak.txt', true, NSUTF8StringEncoding);
stringToBeWritten.writeToFileAtomicallyEncodingError('/root/jailbreak.txt', true, NSUTF8StringEncoding);
NSFileManager.defaultManager.removeItemAtPathError('/private/jailbreak.txt');
NSFileManager.defaultManager.removeItemAtPathError('/root/jailbreak.txt');
} catch (e) {
error = e;
}
return !error ? true : false;
}
参考资料
研究来自对以下想法的整合:
- https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06j-testing-resiliency-against-reverse-engineering
- https://github.com/securing/IOSSecuritySuite/blob/master/IOSSecuritySuite/JailbreakChecker.swift
- https://github.com/avltree9798/isJailbroken/blob/master/isJailbroken/JB.m
改进
欢迎大家多多指教!
例如使用 _dyld_get_image_name