daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

ios-uipasteboard.md (9126B)


      1 ---
      2 title: "iOS Pasteboard"
      3 section: "Mobile"
      4 sectionSlug: "mobile-pentesting"
      5 sourcePath: "src/mobile-pentesting/ios-pentesting/ios-uipasteboard.md"
      6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/mobile-pentesting/ios-pentesting/ios-uipasteboard.md"
      7 sha: "188de82beb54e70956b2952367a0af91d26758b8"
      8 isIndex: false
      9 modified: true
     10 license: "CC-BY-NC-4.0"
     11 ---
     12 
     13 # iOS Pasteboard
     14 
     15 Data sharing within and across applications on iOS devices is facilitated by `UIPasteboard`, which has two primary categories:<sup>[[1]](#references)[[4]](#references)</sup>
     16 
     17 - **Systemwide general pasteboard**: This is used for sharing data with **any application** and is designed to persist data across device restarts and app uninstallations, a feature that has been available since iOS 10.
     18 - **Custom / Named pasteboards**: These are specifically for data sharing **within an app or with another app** that shares the same team ID, and are not designed to persist beyond the life of the application process that creates them, following changes introduced in iOS 10.
     19 
     20 **Security considerations** play a significant role when utilizing pasteboards. For instance:<sup>[[1]](#references)[[2]](#references)</sup>
     21 
     22 - Starting in iOS 16, directly reading a value placed on the general pasteboard by another app requires the system to confirm user intent. A programmatic value read can therefore produce an approval prompt, whereas the edit menu, keyboard shortcut, or a visibly displayed and tapped `UIPasteControl` represents explicit paste intent.<sup>[[5]](#references)[[6]](#references)</sup>
     23 - To mitigate the risk of unauthorized background monitoring of the pasteboard, access is restricted to when the application is in the foreground (since iOS 9).
     24 - The use of persistent named pasteboards is discouraged in favor of shared containers due to privacy concerns.
     25 - The **Universal Clipboard** feature introduced with iOS 10, allowing content to be shared across devices via the general pasteboard, can be managed by developers to set data expiration and disable automatic content transfer.
     26 
     27 Ensuring that **sensitive information is not inadvertently stored** on the global pasteboard is crucial. Additionally, applications should be designed to prevent the misuse of global pasteboard data for unintended actions, and developers are encouraged to implement measures to prevent copying of sensitive information to the clipboard.<sup>[[2]](#references)</sup>
     28 
     29 ## Privacy-aware attack surface (iOS 16+)
     30 
     31 A paste prompt is both a protection and a useful test signal. Copy a unique, non-sensitive canary in a separate app, cold-start the target, and do **not** invoke any paste UI. A prompt at launch, resume, or view presentation indicates that the target attempted a programmatic value read. Repeat the flow while denying and allowing access, and correlate it with hooked selectors and network traffic to determine whether the app gates the read correctly or tries to upload the value. Finally, compare this with an explicit paste through the edit menu or `UIPasteControl`; this separates expected user-driven behavior from automatic clipboard harvesting.<sup>[[3]](#references)[[6]](#references)</sup>
     32 
     33 Do not confuse **classification** with **content access**. `detectPatterns(for:)` / `detectedPatterns(for:)` can disclose that an item resembles a URL, number, email address, phone number, postal address, tracking number, or other supported pattern without returning its value and without notifying the user. This is still a small metadata oracle worth recording during an assessment. Conversely, `detectValues(for:)` / `detectedValues(for:)` returns matched values and must be treated as a content read. Hook both API families to discover apps that first classify the pasteboard and only read it when a desired pattern matches.<sup>[[4]](#references)[[7]](#references)</sup>
     34 
     35 For sensitive writes, inspect whether the application supplies both `UIPasteboard.OptionsKey.localOnly` and `expirationDate`. `localOnly` keeps the item out of Handoff/Universal Clipboard, while `expirationDate` asks the system to remove it after a bounded interval. Their absence does not prove exploitability, but it increases the exposure window and number of reachable devices.<sup>[[4]](#references)</sup>
     36 
     37 ```swift
     38 import UniformTypeIdentifiers
     39 
     40 UIPasteboard.general.setItems(
     41   [[UTType.utf8PlainText.identifier: token]],
     42   options: [
     43     .localOnly: true,
     44     .expirationDate: Date().addingTimeInterval(60)
     45   ]
     46 )
     47 ```
     48 
     49 ### Static Analysis
     50 
     51 For static analysis, search the source code or binary for:<sup>[[3]](#references)[[4]](#references)</sup>
     52 
     53 - `generalPasteboard` to identify usage of the **systemwide general pasteboard**.
     54 - Value getters such as `string`, `strings`, `URL`, `URLs`, `image`, `images`, `items`, `itemProviders`, and `dataForPasteboardType:`. Prioritize reads reachable from application launch, scene activation, or view-loading callbacks.
     55 - Writers such as `setString:`, `setValue:forPasteboardType:`, `setItems:options:`, and `setItemProviders:localOnly:expirationDate:`. Trace whether secrets, session material, password-reset links, OTPs, or payment data can reach them.
     56 - `detectPatterns`, `detectedPatterns`, `detectValues`, and `detectedValues` to distinguish metadata checks from value extraction.
     57 - `UIPasteControl` and `UIPasteConfiguration` to identify intended user-mediated paste flows.
     58 - `pasteboardWithName:create:` and `pasteboardWithUniqueName` for creating **custom pasteboards**. Verify if persistence is enabled, though this is deprecated.
     59 
     60 ### Dynamic Analysis
     61 
     62 Dynamic analysis involves hooking or tracing specific methods:<sup>[[3]](#references)</sup>
     63 
     64 - Monitor `generalPasteboard` for system-wide usage.
     65 - Trace `pasteboardWithName:create:` and `pasteboardWithUniqueName` for custom implementations.
     66 - Observe deprecated `setPersistent:` method calls to check for persistence settings.
     67 - Hook getters and their return values separately from setters and their arguments. This identifies whether the target is a clipboard **source**, **sink**, or both, without relying only on periodic polling.
     68 - Exercise multiple pasteboard representations in the same item. An app may validate the string representation but consume a URL, rich-text, image, or custom UTI representation through another code path.
     69 
     70 Key details to monitor include:
     71 
     72 - **Pasteboard names** and **contents** (for instance, checking for strings, URLs, images).
     73 - **Number of items** and **data types** present, leveraging standard and custom data type checks.
     74 - **Expiry and local-only options** by inspecting the `setItems:options:` method.
     75 - **Call timing and stack traces**, especially reads performed on launch, foreground transitions, or before any visible paste action.
     76 - **Outbound requests** immediately after a canary is read, which can demonstrate exfiltration rather than merely local feature detection.
     77 
     78 An example of monitoring tool usage is **objection's pasteboard monitor**, which polls the `generalPasteboard` every 5 seconds for changes and outputs the new data. On iOS 16 and later this is an **active read**, not a transparent observer: injected polling executes in the target process and can itself trigger or alter paste-approval behavior. First capture the application's own `UIPasteboard` calls with hooks, then use polling in a separate run so that the monitor is not mistaken for application behavior.<sup>[[3]](#references)[[6]](#references)</sup>
     79 
     80 Here's a simple JavaScript script example, inspired by the objection's approach, to read and log changes from the pasteboard every 5 seconds:
     81 
     82 ```javascript
     83 const UIPasteboard = ObjC.classes.UIPasteboard
     84 const Pasteboard = UIPasteboard.generalPasteboard()
     85 var items = ""
     86 var count = Pasteboard.changeCount().toString()
     87 
     88 setInterval(function () {
     89   const currentCount = Pasteboard.changeCount().toString()
     90   const currentItems = Pasteboard.items().toString()
     91 
     92   if (currentCount === count) {
     93     return
     94   }
     95 
     96   items = currentItems
     97   count = currentCount
     98 
     99   console.log(
    100     "[* Pasteboard changed] count: " +
    101       count +
    102       " hasStrings: " +
    103       Pasteboard.hasStrings().toString() +
    104       " hasURLs: " +
    105       Pasteboard.hasURLs().toString() +
    106       " hasImages: " +
    107       Pasteboard.hasImages().toString()
    108   )
    109   console.log(items)
    110 }, 1000 * 5)
    111 ```
    112 
    113 
    114 ## References
    115 
    116 - [1] [OWASP MASTG - Pasteboard](https://mas.owasp.org/MASTG-KNOW-0083/)
    117 - [2] [OWASP iOS Exercise notes (iGoat-Swift)](https://hackmd.io/@robihamanto/owasp-robi)
    118 - [3] [MASTG-TEST-0073: Testing UIPasteboard](https://mas.owasp.org/MASTG/tests/ios/MASVS-PLATFORM/MASTG-TEST-0073/)
    119 - [4] [Apple - `UIPasteboard`](https://developer.apple.com/documentation/uikit/uipasteboard)
    120 - [5] [Apple - Supporting paste and pasteboard access](https://developer.apple.com/documentation/uikit/uipastecontrol)
    121 - [6] [Apple WWDC22 - What's new in privacy](https://developer.apple.com/videos/play/wwdc2022/10096/)
    122 - [7] [Apple - Detecting pasteboard patterns](https://developer.apple.com/documentation/uikit/uipasteboard/detectedpatterns%28for%3Ainitemset%3A%29)