iOS UIPasteboard

The UIPasteboard enables sharing data within an app, and from an app to other apps. There are two kinds of pasteboards:

  • systemwide general pasteboard: for sharing data with any app. Persistent by default across device restarts and app uninstalls (since iOS 10).

  • custom / named pasteboards: for sharing data with another app (having the same team ID as the app to share from) or with the app itself (they are only available in the process that creates them). Non-persistent by default (since iOS 10), that is, they exist only until the owning (creating) app quits.

Some security considerations:

  • Users cannot grant or deny permission for apps to read the pasteboard.

  • Since iOS 9, apps cannot access the pasteboard while in background, this mitigates background pasteboard monitoring.

  • Apple warns about persistent named pasteboards and discourages their use. Instead, shared containers should be used.

  • Starting in iOS 10 there is a new Handoff feature called Universal Clipboard that is enabled by default. It allows the general pasteboard contents to automatically transfer between devices. This feature can be disabled if the developer chooses to do so and it is also possible to set an expiration time and date for copied data.

Then, it's important to check that sensitive information isn't being saved inside the global pasteboard. It's also important to check that an application isn't using the global pasteboard data to perform actions, as malicious application could tamper this data.

An application can also prevent its users to copy sensitive data to the clipboard (which is recommended).

Static Analysis

The systemwide general pasteboard can be obtained by using generalPasteboard, search the source code or the compiled binary for this method. Using the systemwide general pasteboard should be avoided when dealing with sensitive data.

Custom pasteboards can be created with pasteboardWithName:create: or pasteboardWithUniqueName. Verify if custom pasteboards are set to be persistent as this is deprecated since iOS 10. A shared container should be used instead.

Dynamic analysis

Hook or trace the following:

  • generalPasteboard for the system-wide general pasteboard.

  • pasteboardWithName:create: and pasteboardWithUniqueName for custom pasteboards.

You can also Hook or trace the deprecated setPersistent: method and verify if it's being called.

When monitoring the pasteboards, there is several details that may be dynamically retrieved:

  • Obtain pasteboard name by hooking pasteboardWithName:create: and inspecting its input parameters or pasteboardWithUniqueName and inspecting its return value.

  • Get the first available pasteboard item: e.g. for strings use string method. Or use any of the other methods for the standard data types.

  • Get the number of items with numberOfItems.

  • Check for existence of standard data types with the convenience methods, e.g. hasImages, hasStrings, hasURLs (starting in iOS 10).

  • Check for other data types (typically UTIs) with containsPasteboardTypes:inItemSet:. You may inspect for more concrete data types like, for example an picture as public.png and public.tiff (UTIs) or for custom data such as com.mycompany.myapp.mytype. Remember that, in this case, only those apps that declare knowledge of the type are able to understand the data written to the pasteboard. Retrieve them using itemSetWithPasteboardTypes: and setting the corresponding UTIs.

  • Check for excluded or expiring items by hooking setItems:options: and inspecting its options for UIPasteboardOptionLocalOnly or UIPasteboardOptionExpirationDate.

If only looking for strings you may want to use objection's command ios pasteboard monitor:

Hooks into the iOS UIPasteboard class and polls the generalPasteboard every 5 seconds for data. If new data is found, different from the previous poll, that data will be dumped to screen.

You may also build your own pasteboard monitor that monitors specific information as seen above.

For example, this script (inspired from the script behind objection's pasteboard monitor) reads the pasteboard items every 5 seconds, if there's something new it will print it:

const UIPasteboard = ObjC.classes.UIPasteboard;
    const Pasteboard = UIPasteboard.generalPasteboard();
    var items = "";
    var count = Pasteboard.changeCount().toString();

setInterval(function () {
      const currentCount = Pasteboard.changeCount().toString();
      const currentItems = Pasteboard.items().toString();

      if (currentCount === count) { return; }

      items = currentItems;
      count = currentCount;

      console.log('[* Pasteboard changed] count: ' + count +
      ' hasStrings: ' + Pasteboard.hasStrings().toString() +
      ' hasURLs: ' + Pasteboard.hasURLs().toString() +
      ' hasImages: ' + Pasteboard.hasImages().toString());
      console.log(items);

    }, 1000 * 5);

References

Last updated