# Prevent copy & paste into other iOS apps

Especially for enterprise apps it is essential to protect sensitive information by preventing end-users from copying & paste the content into other apps.

In this blog post, I show you multiple ways to introduce such kind of advanced clipboard protection for your iOS app.

# No code instrumentation is needed when using MDM

Apple @ Work introduced Managed Pasteboard in iOS 15 which allows IT administrators to apply restrictions to the copy & paste functionality, meaning that information copied from corporate apps cannot be pasted into unmanaged apps and/or the reverse.

%[https://9to5mac.com/2022/02/19/managed-pasteboard-in-ios-15-continues-the-options-of-securing-corporate-data/] 

# Code instrumentation within your app

Let's start by explaining that Apple uses the term `pasteboard` instead of `clipboard`. Also, it is essential to know that there are two kinds of pasteboards:

* **systemwide general pasteboard**: for sharing data with **any app**. Persistent across device restarts and app uninstalls. Can be obtained by using `UIPasteboard.general`
    
* **custom / named pasteboards**: for sharing data **with another app/extension** (having the same team ID as the app to share from) or with the **app itself**. Non-persistent by default. Such can be created with `UIPasteboard.pasteboardWithName:create:` or `UIPasteboard.pasteboardWithUniqueName`.
    

## Good start: Clear systemwide general pasteboard

Allowing a user to copy/paste within our iOS application and preventing the user from pasting into other apps.

When the user attempts to switch apps then it is possible to get notified through the `NotificationCenter` and then clear, i.e. override, the clipboard.

```swift
NotificationCenter.default.addObserver(
    self,
    selector: #selector(appMovedToBackground),
    name: UIApplication.willResignActiveNotification,
    object: nil
)

@objc
func appMovedToBackground() {
    UIPasteboard.general.string = ""
}
```

A drawback of this technique is that critical information might stay on the clipboard for a long time and attackers might read out the clipboard by periodically querying its content. Also Apple's handoff feature **Universal Clipboard** may automatically transfer content to other devices and therefore increases the attack vector.

> Using the systemwide general pasteboard should be avoided when dealing with sensitive data.

P.S.: It is not an option to listen to `UIPasteboard.changedNotification` and immediately clear the clipboard because this would prevent the user from copying & paste within the app.

## Better: Ensure the use of custom pasteboard through swizzling

The goal is to return a custom `UIPasteBoard` whenever the system-wide pasteboard (`UIPateboard.general`) is requested. Using Swizzling guarantees that the custom pasteboard is always used. Even if the end-user uses the build-in copy capability from UI elements like `UITextField` that would normally use the system-wide pasteboard.

I'll demonstrate two swizzling techniques

* Objective-C Runtime
    
* Swift Native with `@_dynamicReplacement`
    

### Swizzling with Objective-Runtime

```swift
class AppDelegate: NSObject, UIApplicationDelegate {
    static var privatePasteboard = UIPasteboard.withUniqueName()

    func application(_: UIApplication, didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
        swizzleUIPasteboardGeneral()
        return true
    }

    func swizzleUIPasteboardGeneral() {
        let aClass: AnyClass! = object_getClass(UIPasteboard.general)
        let targetClass: AnyClass! = object_getClass(self)

        let originalMethod = class_getClassMethod(aClass, #selector(getter: UIPasteboard.general))
        let swizzledMethod = class_getInstanceMethod(targetClass, #selector(privatePasteboard))

        if let originalMethod, let swizzledMethod {
            method_exchangeImplementations(originalMethod, swizzledMethod)
        }
    }

    @objc
    func privatePasteboard() -> UIPasteboard {
        return AppDelegate.privatePasteboard
    }
}
```

On application start the original implementation of `UIPasteboard.general` gets replaced with an implementation that returns a `UIPasteboard` that was created with `UIPasteboard.withUniqueName()`

### Swift Native swizzling

Easier is the native Swift swizzling technique by using experimental Swift Attribute [@\_dynamicReplacement(for: targetFunc(label:))](https://github.com/apple/swift/blob/release/5.7/docs/ReferenceGuides/UnderscoredAttributes.md#_dynamicreplacementfor-targetfunclabel)

```swift
    extension UIPasteboard {
        @_dynamicReplacement(for: generalPasteboard)
        static var privatePasteboard: UIPasteboard {
            return AppDelegate.privatePasteboard
        }
    }
```

The code replacement happens at the program start (or loading a shared library), instead of at an arbitrary point in time.

For a deep dive into Swift's native swizzling technique, I recommend the following article:

%[https://www.guardsquare.com/blog/swift-native-method-swizzling] 

You can try both techniques in a sample application I published on GitHub.

%[https://github.com/MarcoEidinger/swift-swizzling-uipasteboard-demo] 

The private UIPasteboard gets honored by WKWebView and UIWebView so the <mark>solution works for native controls as well as web views</mark>.

Another important piece of information, in case it is not obvious, the <mark>user will also not be able to paste content from other apps into the app</mark>.

# Conclusion

By using a non-persistent, custom pasteboard, you can reduce the risk that attackers might steal sensitive information.

By using swizzling, you can guarantee that the custom pasteboard is always used. Even if the end-user uses the build-in copy capability from UI elements like `UITextField`.

Shoutout to Hacktricks iOS Pentesting article about [iOS UIPasteboard](https://book.hacktricks.xyz/mobile-pentesting/ios-pentesting/ios-uipasteboard)!
