Article

A quick intro to Needle

Needle is an open source modular framework which aims to streamline the entire process of conducting security assessments of iOS applications, and acts as a central point from which to do so.

This article is going to explain how to quickly get up to speed with Needle and its usage. To get a copy of Needle, and for a detailed walktrough on how to install it (since both Kali and OSX are supported), follow the "Installation Guide" on the project's Github Wiki.

 

First Use

Once ready, to launch Needle just open a console and type:

$ python needle.py
__ _ _______ _______ ______ ______
| \ | |______ |______ | \ | |______
| \_| |______ |______ |_____/ |_____ |______
Needle v0.0.3 [mwr.to/needle]
[MWR InfoSecurity (@MWRLabs) - Marco Lancini (@LanciniMarco)]

[needle] > help
Commands (type [help|?] <topic>):
---------------------------------
back exit info kill pull reload search shell show use
exec_command help jobs load push resource set shell_local unset

[needle] > show options
Name Current Value Required Description
------------ ------------- -------- -----------
APP no Bundle ID of the target application (e.g., com.example.app). Leave empty to launch wizard
DEBUG False yes Enable debugging output
IP 127.0.0.1 yes IP address of the testing device (set to localhost to use USB)
PASSWORD alpine yes SSH Password of the testing device
PORT 2222 yes Port of the SSH agent on the testing device (needs to be != 22 to use USB)
PROXY no Proxy server (address:port)
SETUP_DEVICE True yes Set to true to enable auto-configuration of the device (installation of all the tools needed)
USERNAME root yes SSH Username of the testing device
VERBOSE True yes Enable verbose output

[needle] >

 

One of the main goals we wanted to achieve with Needle was for it to be easy to use, even for those who are just starting to approach iOS security. With this in mind, as seen above, the command line interface resembles the one adopted by Metasploit. 

The tool has some global options (listed with the "show options" command, and set with the "set <option> <value>" command):

  • USERNAME, PASSWORD: SSH credentials of the testing device (set by default to "root" and "alpine", respectively)
  • IP, PORT: the session manager embedded in the core of Needle is able to handle SSH connections over Wi-Fi or USB. If SSH-over-USB is the chosen method, the IP option must be set to localhost ("set IP 127.0.0.1"), and PORT set to anything different from 22 ("set PORT 2222")
  • VERBOSE, DEBUG: if set to True, they will enable verbose and debug logging, respectively
  • SETUP_DEVICE: if set to True, Needle checks if all the dependencies needed are already present on the device, otherwise it will install them
  • APP: this is the bundle identifier of the app to analyze (e.g., "com.example.app"). If it is not known beforehand, this field can be left empty. In this case, Needle will launch a wizard which prompts the user to select an app among those already installed on the device

 

Basic Features

Although the power of Needle is comprised in its modules, the core itself offers some basic features that allow it to interact with the device.

 

Execute local command (<cmd>)
 

Needle's CLI is basically a shell itself, so it is possible to run commands on the local workstation just by typing them.

[needle] > cat /etc/hostname
[*] Executing Local Command: cat /etc/hostname
launchpad

[needle] > ifconfig lo
[*] Executing Local Command: ifconfig lo
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:48454 errors:0 dropped:0 overruns:0 frame:0
TX packets:48454 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:33149117 (31.6 MiB) TX bytes:33149117 (31.6 MiB)
Shell (shell)

Type "shell" to drop a shell on the remote device.

[needle] > shell
[*] Spawning a shell...
[*] Checking connection with device...
[V] Connection not present, creating a new instance
[V] Setting up USB port forwarding on port 2222
[V] Setting up SSH connection...
[+] Connected to: 127.0.0.1
Warning: Permanently added '[127.0.0.1]:2222' (RSA) to the list of known hosts.
MWR-iPhone:~ root# id
uid=0(root) gid=0(wheel) groups=0(wheel),...
Execute command on device (exec_command <cmd>)

To execute a single command on the remote device.

[needle] > exec_command id
[*] Checking connection with device...
[+] Already connected to: 127.0.0.1
[*] Executing: id
uid=0(root) gid=0(wheel) groups=0(wheel)...

 

Push/pull files (<push/pull> "<src>" "<dst>")

It is also possible to retrieve or upload files from/on the device. Note that both the source and destination paths must be enclosed in quotes.

[needle] > pull "/etc/hosts" "/tmp/iphone_hosts"
[*] Checking connection with device...
[+] Already connected to: 127.0.0.1
[*] Pulling: /etc/hosts -> /tmp/iphone_hosts
[needle] > cat /tmp/iphone_hosts
[*] Executing Local Command: cat /tmp/iphone_hosts
##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting. Do not change this entry.
##
127.0.0.1 localhost
255.255.255.255 broadcasthost
::1 localhost
Autoconfiguration

Configuration of the global options can also be automated, using a resource file. First, create a resource file with the commands you want to have automatically executed. For example:

$ cat config.txt
# This is a comment, it won't be executed
set DEBUG False
set VERBOSE False

# If SETUP_DEVICE is set to True, 
# Needle will automatically install all the required tools on the device
set SETUP_DEVICE False

set IP 192.168.0.10
set PORT 5555
set APP com.example.app
use binary/metadata

Then, launch Needle and instruct it to load the resource file:

python needle.py -r config.txt

 

Modular approach

Another goal that shaped Needle's design was for it to be easily extensible. That's the reason why every feature has been wrapped in its own module.

Since every module focuses on a particular task, with the core handling common problems (like communication with the device, actual execution of commands, etc.), creation of new modules is a matter of a few lines of python code.

The "show modules" command can be used to list all the modules currently available in the framework.

[needle][install] > show modules

Binary
------
binary/class_dump
binary/compilation_checks
binary/install
binary/metadata
binary/pull_ipa
binary/shared_libraries
binary/strings

Comms
-----
comms/certs/delete_ca
comms/certs/export_ca
...

Otherwise, the "search <query>" command can be used to search available modules that match the query.

[needle] > search binary
[*] Searching for "binary"...

Binary
------
binary/class_dump
binary/compilation_checks
binary/install
binary/metadata
binary/pull_ipa
binary/shared_libraries
binary/strings

Storage
-------
storage/data/files_binarycookies 

Once selected, the "info" command can be used to show details of a particular module.

[needle] > use binary/strings
[needle][strings] > info

Name: Strings
Path: modules/binary/strings.py
Author: @LanciniMarco (@MWRLabs)

Description:
Find strings in the (decrypted) application binary, then try to extract URIs and ViewControllers

Options:
Name Current Value Required Description
------- ------------- -------- -----------
ANALYZE True no Analyze recovered strings and try to recover URI
FILTER no Filter the output (grep)
LENGTH 10 yes Minimum length for a string to be considered
OUTPUT /root/.needle/tmp/strings.txt no Full path of the output file 

 Or, to get only the available options:

[needle][strings] > show options
Name Current Value Required Description
------- ------------- -------- -----------
ANALYZE True no Analyze recovered strings and try to recover URI
FILTER no Filter the output (grep)
LENGTH 10 yes Minimum length for a string to be considered
OUTPUT /root/.needle/tmp/strings.txt no Full path of the output file 

Like the global options, even module-specific ones can be edited with the "set" and "unset" commands.

[needle][strings] > set FILTER password
FILTER => password
[needle][strings] > show options
Name Current Value Required Description
------- ------------- -------- -----------
ANALYZE True no Analyze recovered strings and try to recover URI
FILTER password no Filter the output (grep)
LENGTH 10 yes Minimum length for a string to be considered
OUTPUT /root/.needle/tmp/strings.txt no Full path of the output file 

When all the options are set as preferred, the "run" command can be used to start the module's execution. If a target app has not been selected yet (with the global option "TARGET_APP" still unset), Needle will first launch a wizard that will help the user in selecting a target.

[needle][strings] > run
[*] Checking connection with device...
[+] Already connected to: 127.0.0.1
[V] Creating temp folder: /var/root/needle/
[*] Target app not selected. Launching wizard...
[V] Refreshing list of installed apps...
[+] Apps found:
0 - com.highaltitudehacks.dvia
1 - uk.co.bbc.newsuk
Please select a number: 0
[+] Target app: com.highaltitudehacks.dvia
[*] Decrypting the binary...
[?] The app might be already decrypted. Trying to retrieve the IPA...
[V] Decrypted IPA stored at: /var/root/needle/decrypted.ipa
[*] Unpacking the decrypted IPA...
[V] Analyzing binary...
[+] The following strings has been found:
%@: Unable to get password of credential %@
%s -- Cannot be used in OpenSSL mode. An IV or password is required
Both password and the key (%d) or HMACKey (%d) are set.
CFHTTPMessageAddAuthentication(httpMsg, _responseMsg, (__bridge CFStringRef)_credential.user, (__bridge CFStringRef)password, kCFHTTPAuthenticationSchemeBasic, _httpStatus == 407)
Cannot sign up without a password.
Congrats! You've found the right username and password!
Huh, couldn't get password of %@; trying again
Please enter a password
T@"NSString",&,N,V_password
T@"NSString",C,N,V_password
T@"UITextField",&,N,V_passwordTextField
...
[*] Saving output to file: /root/.needle/tmp/strings.txt

 

Finally, the "show source" command can be used to inspect the actual source code of the selected module.

[needle][strings] > show source
1|from core.framework.module import BaseModule
2|
3|
4|class Module(BaseModule):
5| meta = {
6| 'name': 'Strings',
7| 'author': '@LanciniMarco (@MWRLabs)',
8| 'description': 'Find strings in the (decrypted) application binary, then try to extract URIs and ViewControllers',
9| 'options': (
10| ('length', 10, True, 'Minimum length for a string to be considered'),
11| ('filter', '', False, 'Filter the output (grep)'),
12| ('output', True, False, 'Full path of the output file'),
13| ('analyze', True, False, 'Analyze recovered strings and try to recover URI'),
14| ),
15| }
16|
17| # ====================================================================
18| # UTILS
19| # ====================================================================
20| def __init__(self, params):
21| BaseModule.__init__(self, params)
...

  

Background jobs

Needle also has support for background jobs that can be left running during the execution of other modules. Some modules, especially those containing the "monitor" keyword in their name, rely on such background jobs.

[needle] > use dynamic/monitor/files
[needle][files] > info

Name: Monitor File changes
Path: modules/dynamic/monitor/files.py
Author: @LanciniMarco (@MWRLabs)

Description:
Monitor the app data folder and keep track of modified files

Options:
Name Current Value Required Description
------ ------------- -------- -----------
FOLDER no The folder to monitor (leave empty to use the app Data directory
OUTPUT /root/.needle/tmp/modifiedfiles.txt no Full path of the output file


[needle][files] > run
[*] Checking connection with device...
[+] Already connected to: 127.0.0.1
[+] Target app: com.highaltitudehacks.dvia
[+] Monitoring: /private/var/mobile/Containers/Data/Application/031CAB32-6115-4613-B56F-CFF61BCED692
[*] Monitoring in background...Kill this process when you want to see the dumped content

[needle] >

The "jobs" command can be used to list all the currently running background processes.

[needle] > jobs
[+] Running jobs:
0 - dynamic_monitor_files
[needle] >

The "kill" command can then be used to stop a background job, and therefore retrieve its output.

[needle][files] > kill 0
[D] [REMOTE CMD] Stopping Remote Background Command [pid: 510]
[D] [REMOTE CMD] Remote Command: kill 510
[*] Retrieving output file...
[*] Pulling: /var/root/needle/fsmon -> /root/.needle/tmp/modifiedfiles.txt
[+] Content of file '/root/.needle/tmp/modifiedfiles.txt':
FSE_CREATE_FILE 512 "DamnVulnerableIO" /private/var/mobile/Containers/Data/Application/05F34A75-55C6-41E4-BB51-0F3777DF6D97/tmp/cy-TS2mr3.dylib
FSE_DELETE 512 "DamnVulnerableIO" /private/var/mobile/Containers/Data/Application/05F34A75-55C6-41E4-BB51-0F3777DF6D97/tmp/cy-TS2mr3.dylib
FSE_CONTENT_MODIFIED 512 "DamnVulnerableIO" /private/var/mobile/Containers/Data/Application/05F34A75-55C6-41E4-BB51-0F3777DF6D97/tmp/cy-TS2mr3.dylib
FSE_XATTR_MODIFIED 512 "DamnVulnerableIO" /private/var/mobile/Containers/Data/Application/05F34A75-55C6-41E4-BB51-0F3777DF6D97/Library/Private Documents/Parse
FSE_XATTR_MODIFIED 512 "DamnVulnerableIO" /private/var/mobile/Containers/Data/Application/05F34A75-55C6-41E4-BB51-0F3777DF6D97/Library/Application Support/FlurryFiles
...
[*] A copy of the output has been saved at the following location: /root/.needle/tmp/modifiedfiles.txt
[needle] >

 

Features

Here we are going to list some of the modules included in v0.0.3 of Needle. For a complete (and up to date) list of supported features, please refer to the "Feature List" on the project's Github Wiki.

Binary Analysis
  • binary/class_dump: Dump the class interfaces
  • binary/compilation_checks: Check for basic binary protections (PIE, ARC, stack canaries, binary encryption)
  • binary/install: Automatically upload and install an IPA on the device
  • binary/metadata: Retrieve and display the app's metadata (UUID, app name/version, bundle name/id, bundle/data/binary directory, binary path/name, entitlements, url handlers, architectures, platform/sdk/os version)
  • binary/pull_ipa: Decrypt and pull the application's IPA from the device 
  • binary/shared_libraries: List the shared libraries used by the application
  • binary/strings: Find strings in the (decrypted) application binary, then tries to extract URIs and ViewControllers

 Storage
  • storage/caching/screenshot: Test if a screenshot of the application's main window is cached when the application's process is moved to the background
  • storage/data/files_binarycookies: List the Binary Cookies files contained in the app folders, along with their Data Protection Class. Plus, offers the chance to pull and inspect them
  • storage/data/files_cachedb: List the Cache.db files contained in the app folders, along with their Data Protection Class. Plus, offers the chance to pull and inspect them
  • storage/data/files_plist: List the plist files contained in the app folders, along with their Data Protection Class. Plus, offers the chance to inspect them
  • storage/data/files_sql: List the SQL files contained in the app folders, along with their Data Protection Class. Plus, offers the chance to pull and inspect them
  • storage/data/keychain_dump: Dump the keychain

Dynamic Analysis
  • dynamic/detection/jailbreak_detection: Verify that the app cannot be run on a jailbroken device
  • dynamic/ipc/open_uri: Test IPC attacks by launching URI Handlers
  • dynamic/memory/heap_dump: Dump memory regions of the app and look for strings
  • dynamic/monitor/files: Monitor the app data folder and keep track of modified files
  • dynamic/monitor/pasteboard: Monitor the OS Pasteboard and dump its content
  • dynamic/monitor/syslog: Monitor the syslog in background and dump its content
  • dynamic/watch/syslog: Watch the syslog in realtime

Hooking
  • hooking/cycript/cycript_shell: Spawn a Cycript shell attached to the target app
  • hooking/frida/frida_launcher: Run Frida scripts (JS payloads)
  • hooking/frida/frida_shell: Spawn a Frida shell attached to the target app
  • hooking/frida/frida_trace: Trace the specified functions using frida-trace
  • hooking/frida/script_enum-all-methods: Enumerate all methods from all classes in the application
  • hooking/frida/script_enum-classes: Enumerate available classes 
  • hooking/frida/script_find-class-enum-methods: Find the target class specified and enumerate its methods

Communications
  • comms/certs/delete_ca: Delete one (or more) certificates installed on device
  • comms/certs/export_ca: Export one (or more) certificates installed on device
  • comms/certs/import_ca: Import a certificate from a file in PEM format
  • comms/certs/install_ca_mitm: Install the CA Certificate of MitmProxy on the device
  • comms/certs/list_ca: List the certificates installed on device
  • comms/proxy/proxy_regular: Intercept the traffic generated by the device

Static Analysis
  • static/code_checks: Static analysis of the apps's source code. Aims to find usage of potentially insecure functions. If 2 folders are specified (for example if we have 2 versions of the same codebase), Needle will detect the files that has been modified, and will apply the checks only on those ones

 

Call to Action

Needle is publicly available on Github at the following address: mwr.to/needle

We’d be happy to hear feedback and work with the community to help enhance its capabilities and shape its future.