Description
Description
We are using firebase ios sdk for our ios app. Our NowSecure dynamic analysis security team have reported the security issue regarding Use of Unsafe Serialization API Exposes App to Remote Code Execution.
Following are the details of the issue
This application was found to use deprecated nscoding functionalities for serialization/deserialization of data.
Caution should be taken when an application has logic to receive arbitrary data and to then deserialize the data into an object. Remote code execution is possible if raw data is permitted to choose an arbitrary class as the object it becomes deserialized to.
In iOS applications, object deserialization/serialization is usually implemented using the NSCoding protocol, which allows the developer to implement the serialization logic for their own classes, or the NSSecureCoding protocol which extends the NSCoding protocol. An implementation which uses the NSCoding protocol is vulnerable to data being deserialized to a different object than what was expected by the developer, also referred to as an "object substitution attack" in Apple's documentation. For more information, watch https://developer.apple.com/videos/play/wwdc2018/222/.
FirebaseMessaging.framework still has usage of NSKeyedUnarchiver unarchiveObjectWithData which is causing this issue .
Recommended Fix
Make sure you have adopted NSSecureCoding in the data you decode. When writing a class that supports secure coding, ensure that the + (BOOL)supportsSecureCoding class property getter returns true. Ensure that all - (id)decodeObjectForKey:(NSString_)key calls are replaced with - (id)decodeObjectOfClass:(Class)c forKey:(NSString_)key.
Also avoid using the deprecated unarchive_ObjectWithData and unarchive_ObjectWithFile classes and instead implement unarchive*OfClass classes. Refer to NSSecureCoding for further details.
It should be noted that third party libraries may be the cause of this finding. In cases where a third party library is the source of this issue, make sure that versions of the library are up-to-date and that the library is necessary.
Code Samples
Good Code Example (.swift)
class Post: NSSecureCoding
{
static var supportsSecureCoding: Bool {
get { return true }
}
// Later on down the road, you might do something like this...
func updatePostsCache()
{
let saveURL = URL(fileURLWithPath: "someDestination")
let archiver = NSKeyedArchiver.archivedData(withRootObject: posts)
try? archiver.write(to: saveURL)
}
// And eventually get it back out...
let postCache:[Data] = /* Data loaded up */
let posts = try postCache.map { postData in
guard let postBlob = try NSKeyedUnarchiver.unarchiveTopLevelObject(with: postData), let post = postBlob as? Post else { throw /* Error handling */ }
return post
}
//Interacting with Object Class
decoder.decodeObject(of:Post.self, forKey: "Posts")
Good Code Example (.objc)
// Inside @interface
@interface Post : NSObject <NSSecureCoding> {
// Add support for secure coding
(BOOL) supportsSecureCoding {
return YES;
}
//...other data
}
//Interacting with Object Class
id obj = [decoder decodeObjectOfClass:Post.class forKey:@"Posts"];
if (![obj isKindOfClass:[MyClass class]]) { /* ...fail... */ }
Additional Guidance
This article describes the NSCoding protocol which may be insecure if an attacker injects an object of different type(s https://developer.apple.com/documentation/foundation/nscoding
This article introduces the NSSecureCoding protocol which allows secure encoding and decoding of objects (checking types before creating the object https://developer.apple.com/documentation/foundation/nssecurecoding
Reproducing the issue
No response
Firebase SDK Version
11.7.0
Xcode Version
16
Installation Method
CocoaPods
Firebase Product(s)
All
Targeted Platforms
iOS
Relevant Log Output
If using Swift Package Manager, the project's Package.resolved
Expand Package.resolved
snippet
Replace this line with the contents of your Package.resolved.
If using CocoaPods, the project's Podfile.lock
Expand Podfile.lock
snippet
- Alamofire (5.10.1)
- AmplitudeSwift (1.9.4):
- AnalyticsConnector (~> 1.0.1)
- AnalyticsConnector (1.0.3)
- CocoaLumberjack/Core (3.8.5)
- CocoaLumberjack/Swift (3.8.5):
- CocoaLumberjack/Core
- CSCoursePlayer (0.0.1):
- GCDWebServer
- CSOD-Tracker (2.1.7):
- AmplitudeSwift (~> 1.9.4)
- DeviceKit (5.5.0)
- Firebase/AnalyticsWithoutAdIdSupport (11.7.0):
- Firebase/CoreOnly
- FirebaseAnalytics/WithoutAdIdSupport (~> 11.7.0)
- Firebase/CoreOnly (11.7.0):
- FirebaseCore (~> 11.7.0)
- FirebaseABTesting (11.7.0):
- FirebaseCore (~> 11.7.0)
- FirebaseAnalytics/WithoutAdIdSupport (11.7.0):
- FirebaseCore (~> 11.7.0)
- FirebaseInstallations (~> 11.0)
- GoogleAppMeasurement/WithoutAdIdSupport (= 11.7.0)
- GoogleUtilities/AppDelegateSwizzler (~> 8.0)
- GoogleUtilities/MethodSwizzler (~> 8.0)
- GoogleUtilities/Network (~> 8.0)
- "GoogleUtilities/NSData+zlib (~> 8.0)"
- nanopb (~> 3.30910.0)
- FirebaseCore (11.7.0):
- FirebaseCoreInternal (~> 11.7.0)
- GoogleUtilities/Environment (~> 8.0)
- GoogleUtilities/Logger (~> 8.0)
- FirebaseCoreExtension (11.7.0):
- FirebaseCore (~> 11.7.0)
- FirebaseCoreInternal (11.7.0):
- "GoogleUtilities/NSData+zlib (~> 8.0)"
- FirebaseCrashlytics (11.7.0):
- FirebaseCore (~> 11.7.0)
- FirebaseInstallations (~> 11.0)
- FirebaseRemoteConfigInterop (~> 11.0)
- FirebaseSessions (~> 11.0)
- GoogleDataTransport (~> 10.0)
- GoogleUtilities/Environment (~> 8.0)
- nanopb (~> 3.30910.0)
- PromisesObjC (~> 2.4)
- FirebaseInstallations (11.7.0):
- FirebaseCore (~> 11.7.0)
- GoogleUtilities/Environment (~> 8.0)
- GoogleUtilities/UserDefaults (~> 8.0)
- PromisesObjC (~> 2.4)
- FirebaseMessaging (11.7.0):
- FirebaseCore (~> 11.7.0)
- FirebaseInstallations (~> 11.0)
- GoogleDataTransport (~> 10.0)
- GoogleUtilities/AppDelegateSwizzler (~> 8.0)
- GoogleUtilities/Environment (~> 8.0)
- GoogleUtilities/Reachability (~> 8.0)
- GoogleUtilities/UserDefaults (~> 8.0)
- nanopb (~> 3.30910.0)
- FirebaseRemoteConfig (11.7.0):
- FirebaseABTesting (~> 11.0)
- FirebaseCore (~> 11.7.0)
- FirebaseInstallations (~> 11.0)
- FirebaseRemoteConfigInterop (~> 11.0)
- FirebaseSharedSwift (~> 11.0)
- GoogleUtilities/Environment (~> 8.0)
- "GoogleUtilities/NSData+zlib (~> 8.0)"
- FirebaseRemoteConfigInterop (11.7.0)
- FirebaseSessions (11.7.0):
- FirebaseCore (~> 11.7.0)
- FirebaseCoreExtension (~> 11.7.0)
- FirebaseInstallations (~> 11.0)
- GoogleDataTransport (~> 10.0)
- GoogleUtilities/Environment (~> 8.0)
- GoogleUtilities/UserDefaults (~> 8.0)
- nanopb (~> 3.30910.0)
- PromisesSwift (~> 2.1)
- FirebaseSharedSwift (11.7.0)
- GCDWebServer (3.5.4):
- GCDWebServer/Core (= 3.5.4)
- GCDWebServer/Core (3.5.4)
- GoogleAppMeasurement/WithoutAdIdSupport (11.7.0):
- GoogleUtilities/AppDelegateSwizzler (~> 8.0)
- GoogleUtilities/MethodSwizzler (~> 8.0)
- GoogleUtilities/Network (~> 8.0)
- "GoogleUtilities/NSData+zlib (~> 8.0)"
- nanopb (~> 3.30910.0)
- GoogleDataTransport (10.1.0):
- nanopb (~> 3.30910.0)
- PromisesObjC (~> 2.4)
- GoogleUtilities/AppDelegateSwizzler (8.0.2):
- GoogleUtilities/Environment
- GoogleUtilities/Logger
- GoogleUtilities/Network
- GoogleUtilities/Privacy
- GoogleUtilities/Environment (8.0.2):
- GoogleUtilities/Privacy
- GoogleUtilities/Logger (8.0.2):
- GoogleUtilities/Environment
- GoogleUtilities/Privacy
- GoogleUtilities/MethodSwizzler (8.0.2):
- GoogleUtilities/Logger
- GoogleUtilities/Privacy
- GoogleUtilities/Network (8.0.2):
- GoogleUtilities/Logger
- "GoogleUtilities/NSData+zlib"
- GoogleUtilities/Privacy
- GoogleUtilities/Reachability
- "GoogleUtilities/NSData+zlib (8.0.2)":
- GoogleUtilities/Privacy
- GoogleUtilities/Privacy (8.0.2)
- GoogleUtilities/Reachability (8.0.2):
- GoogleUtilities/Logger
- GoogleUtilities/Privacy
- GoogleUtilities/UserDefaults (8.0.2):
- GoogleUtilities/Logger
- GoogleUtilities/Privacy
- Introspect (0.1.4)
- KeychainSwift (24.0.0)
- Kingfisher (8.1.0)
- mobileSharedLib (1.0.0.95)
- Mockingjay (3.0.0-alpha.1):
- Mockingjay/Core (= 3.0.0-alpha.1)
- Mockingjay/XCTest (= 3.0.0-alpha.1)
- Mockingjay/Core (3.0.0-alpha.1):
- URITemplate (~> 3.0)
- Mockingjay/XCTest (3.0.0-alpha.1):
- Mockingjay/Core
- nanopb (3.30910.0):
- nanopb/decode (= 3.30910.0)
- nanopb/encode (= 3.30910.0)
- nanopb/decode (3.30910.0)
- nanopb/encode (3.30910.0)
- Nimble (11.2.0)
- ObjectMapper (4.4.2)
- PINCache (3.0.4):
- PINCache/Arc-exception-safe (= 3.0.4)
- PINCache/Core (= 3.0.4)
- PINCache/Arc-exception-safe (3.0.4):
- PINCache/Core
- PINCache/Core (3.0.4):
- PINOperation (~> 1.2.3)
- PINOperation (1.2.3)
- PromiseKit (8.1.2):
- PromiseKit/CorePromise (= 8.1.2)
- PromiseKit/Foundation (= 8.1.2)
- PromiseKit/UIKit (= 8.1.2)
- PromiseKit/CorePromise (8.1.2)
- PromiseKit/Foundation (8.1.2):
- PromiseKit/CorePromise
- PromiseKit/UIKit (8.1.2):
- PromiseKit/CorePromise
- PromisesObjC (2.4.0)
- PromisesSwift (2.4.0):
- PromisesObjC (= 2.4.0)
- Quick (5.0.0)
- Realm (10.34.0):
- Realm/Headers (= 10.34.0)
- Realm/Headers (10.34.0)
- RealmSwift (10.34.0):
- Realm (= 10.34.0)
- SwiftLint (0.57.0)
- SwiftSoup (2.7.3)
- Toast-Swift (5.1.1)
- TPKeyboardAvoiding (1.3.5)
- UICircularProgressRing (8.0.0)
- URITemplate (3.0.1)
- ViewInspector (0.10.0)
- youtube-ios-player-helper (1.0.4)
- ZIPFoundation (0.9.19)
DEPENDENCIES:
- Alamofire
- CocoaLumberjack/Swift
- CSCoursePlayer (from `CSCoursePlayer`)
- CSOD-Tracker (from `https://bitbucket.csod.com/scm/csod/csod-tracker.git`, commit `de1c6be6369e7294410bb3d88530f972715ace48`)
- DeviceKit
- Firebase/AnalyticsWithoutAdIdSupport (~> 11.7.0)
- FirebaseCore (~> 11.7.0)
- FirebaseCrashlytics (~> 11.7.0)
- FirebaseMessaging (~> 11.7.0)
- FirebaseRemoteConfig (~> 11.7.0)
- Introspect
- KeychainSwift
- Kingfisher
- mobileSharedLib (from `https://artifacts.saba.com/mobile-cocoapods-devqa-hq/mobileSharedLib/1.0.0.95/mobileSharedLib.podspec`)
- Mockingjay (from `https://github.com/kylef/Mockingjay.git`, branch `master`)
- Nimble
- ObjectMapper
- PINCache
- PromiseKit
- Quick (= 5.0.0)
- RealmSwift (= 10.34.0)
- SwiftLint
- SwiftSoup
- Toast-Swift
- TPKeyboardAvoiding
- UICircularProgressRing
- ViewInspector (= 0.10.0)
- youtube-ios-player-helper
- ZIPFoundation
SPEC REPOS:
https://github.com/CocoaPods/Specs.git:
- Alamofire
- AmplitudeSwift
- AnalyticsConnector
- CocoaLumberjack
- DeviceKit
- Firebase
- FirebaseABTesting
- FirebaseAnalytics
- FirebaseCore
- FirebaseCoreExtension
- FirebaseCoreInternal
- FirebaseCrashlytics
- FirebaseInstallations
- FirebaseMessaging
- FirebaseRemoteConfig
- FirebaseRemoteConfigInterop
- FirebaseSessions
- FirebaseSharedSwift
- GCDWebServer
- GoogleAppMeasurement
- GoogleDataTransport
- GoogleUtilities
- Introspect
- KeychainSwift
- Kingfisher
- nanopb
- Nimble
- ObjectMapper
- PINCache
- PINOperation
- PromiseKit
- PromisesObjC
- PromisesSwift
- Quick
- Realm
- RealmSwift
- SwiftLint
- SwiftSoup
- Toast-Swift
- TPKeyboardAvoiding
- UICircularProgressRing
- URITemplate
- ViewInspector
- youtube-ios-player-helper
- ZIPFoundation
EXTERNAL SOURCES:
CSCoursePlayer:
:path: CSCoursePlayer
CSOD-Tracker:
:commit: de1c6be6369e7294410bb3d88530f972715ace48
:git: https://bitbucket.csod.com/scm/csod/csod-tracker.git
mobileSharedLib:
:podspec: https://artifacts.saba.com/mobile-cocoapods-devqa-hq/mobileSharedLib/1.0.0.95/mobileSharedLib.podspec
Mockingjay:
:branch: master
:git: https://github.com/kylef/Mockingjay.git
CHECKOUT OPTIONS:
CSOD-Tracker:
:commit: de1c6be6369e7294410bb3d88530f972715ace48
:git: https://bitbucket.csod.com/scm/csod/csod-tracker.git
Mockingjay:
:commit: b88c9dce2b7561cccbf35e2882b3c71a2efa387a
:git: https://github.com/kylef/Mockingjay.git
SPEC CHECKSUMS:
Alamofire: 840d2a1ad82355b536ec6ba5f97e5bfa54600ca3
AmplitudeSwift: d10ae6afdb0740e4ae843866bce8ab1119a53d74
AnalyticsConnector: a53214d38ae22734c6266106c0492b37832633a9
CocoaLumberjack: 6a459bc897d6d80bd1b8c78482ec7ad05dffc3f0
CSCoursePlayer: ff8c764c47858027b2aad24e2c4e2bf1e66e1343
CSOD-Tracker: 2c0e66c4c905a92a4a5cbcea0fcb60264f783313
DeviceKit: d83e38ca196a4ebf0cc5f37d6f0316a24b794d5b
Firebase: a64bf6a8546e6eab54f1c715cd6151f39d2329f4
FirebaseABTesting: 08b3e19b28504632a9cd03e7a796b355c5d39b27
FirebaseAnalytics: bc9e565af9044ba8d6c6e4157e4edca8e5fdf7ec
FirebaseCore: 3227e35f4197a924206fbcdc0349325baf4f5de4
FirebaseCoreExtension: 206c1b399f0d103055207c16f299b28e3dbd1949
FirebaseCoreInternal: d6c17dafc8dc33614733a8b52df78fcb4394c881
FirebaseCrashlytics: 785a73b624715bbc09a40bb56cdc3829a801cc98
FirebaseInstallations: 9347e719c3d52d8d7b9074b2c32407dd027305e9
FirebaseMessaging: 00ece041b71ddb52a2862ffdee73fb6e9824bd0c
FirebaseRemoteConfig: aa1d4cb05ef4caad203448dfc87842de12f1ea8d
FirebaseRemoteConfigInterop: ca12abf9da0003efd3a476b2dff4f7a04fd31b4f
FirebaseSessions: 32ed7a9387ae71efe3a35a7f20f3a7292950957b
FirebaseSharedSwift: a45efd84d60ebbfdcdbaebc66948af3630459e62
GCDWebServer: 2c156a56c8226e2d5c0c3f208a3621ccffbe3ce4
GoogleAppMeasurement: 0471a5b5bff51f3a91b1e76df22c952d04c63967
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
GoogleUtilities: 26a3abef001b6533cf678d3eb38fd3f614b7872d
Introspect: b62c4dd2063072327c21d618ef2bedc3c87bc366
KeychainSwift: 007c4647486e4563adca839cf02cef00deb3b670
Kingfisher: dfbf20b6249ed4ef6f18d6a96c847bce860bdb95
mobileSharedLib: 97862f3704b84fe9abc5eb6012be6a4dd78b6584
Mockingjay: 97656c6f59879923976a0a52ef09da45756cca82
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
Nimble: cab2cc29436a378f595e8babd231440dfcb0a358
ObjectMapper: e6e4d91ff7f2861df7aecc536c92d8363f4c9677
PINCache: d9a87a0ff397acffe9e2f0db972ac14680441158
PINOperation: fb563bcc9c32c26d6c78aaff967d405aa2ee74a7
PromiseKit: e057b5b3c0ce9a0145674d633930924234104ee3
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
PromisesSwift: 9d77319bbe72ebf6d872900551f7eeba9bce2851
Quick: f58aae30d750b27918005b93d870c187353a7bf0
Realm: 991e7c4d6d37f1d6470a48bb072782ef00b91b67
RealmSwift: 11e77934e4af6d011d2970645fe56e11fa0e3c2c
SwiftLint: eb47480d47c982481592c195c221d11013a679cc
SwiftSoup: e3849c3293b1efee9cf892f91f6ae5c22bfeb5f7
Toast-Swift: 7a03a532afe3a560d4044bc7c237e2864d295173
TPKeyboardAvoiding: d55b3ea7b362540af8fcf36aa3ed2e87bf210cc6
UICircularProgressRing: 19927375b2b21b5fa5fd9582f15ccdef9659da16
URITemplate: 5f5a79f3e384884102c4e6b3325d159c20a8035a
ViewInspector: 2ec5f7d3c572956c560f29a3fd757e5c59a44788
youtube-ios-player-helper: e9b97535e816db3152179d84d999bc1807ecd689
ZIPFoundation: b8c29ea7ae353b309bc810586181fd073cb3312c
PODFILE CHECKSUM: 07a5c439f003aa3d772e960aa1401492ffc716dc
COCOAPODS: 1.15.2