1

Given the plugins that are available in the Nativescript community, your Nativescript app may or may not be sufficient to pass security penetration testing.

Below are two plugins to list a few.

In some scenarios, you could achieve better results by manually writing your own checks against a jailbreak and dynamic instrumentation (e.g. Frida), since there are so many tools to bypass jailbreak detection (e.g. HideJB) nowadays.

What are some ways we can detect jailbreak and protect against dynamic instrumentation on iOS Nativescript?

Keith OYS
  • 2,285
  • 5
  • 32
  • 38

1 Answers1

4

Detection can be carried out on multi-levels:

  • Check if URLs are openable via illegal URL schemes
  • Check if files are openable on illegal directories
  • Check if illegal files exist (incl. Cydia, Sileo, HideJB, etc.)
  • Check if files are writable on restricted directories

Code

  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;
  }

References

The research comes from a consolidation of the following ideas:


Improvements

Please feel free to suggest!

E.g. Checking for illegal dynamic libraries in memory using _dyld_get_image_name

Keith OYS
  • 2,285
  • 5
  • 32
  • 38