Swift Core Data Format String Injection
…Or how I developed a love/hate relationship with format strings
The last couple of months since WWDC have been an interesting exercise in forgetting the complexity of Objective-C (ObjC), falling in love with Swift, and then realizing Apple hasn’t completely dropped ObjC for Swift. Programming an iOS application in Swift quickly becomes a translation effort in converting ObjC code to use Swift syntax and format, since even Apple’s own developer site still references ObjC examples in documentation and Class References. In addition, the Xcode 6 beta and Swift are not a complete match. Auto-generated code often fails when using Apple’s provided templates, including Cocoa Touch Classes. Pay attention to the compiler errors and warnings before trying to actually deploy anything.
This post explores Swift’s interaction with Core Data and how to break (and secure) format strings using wildcards and injection techniques. Core Data’s is Apple’s object graph and persistence framework that makes it easy for Mac and iOS developers to store and retrieve data without the overhead of dealing with databases or other network services. If you are unfamiliar with Core Data, Apple’s tutorial is quite extensive and can take some time to get through. I would recommend Techtopia’s iOS 7 Core Data tutorial to get the basic gist of working with the technology. The one issue is that most tutorials still only address Core Data use with ObjC, so translation to Swift is something you’ll have to figure out.
Interaction with Core Data hasn’t changed much between ObjC and Swift. The following Swift code snippet shows how a test application logs into an iOS application based on the ‘User’ object that is stored in as a Core Data object.
The function is fairly straightforward, but the interesting part to a security professional is the NSPredicate declaration, which is defined as a format string that limits what data is returned from Core Data.
This format string should set off all sorts of alarm bells to anyone creating authentication routines. This application does not follow proper security best practices when creating the predicate or building the associated format string.
First of all, the use of the ‘LIKE’ statement enables simple bypass of authentication within this app. A failed attempt at logging into the app results in:
But the use of wildcards (this is the star ‘*’ for format strings)
results in successful entry into the app.
As in creation of secure SQL statements, use of the ‘LIKE’ keyword within NSPredicate creation should be avoided for everything but search utilities. Not only does it allow an attacker to present wildcards to Core Data, it also allows an attacker to enumerate through all of the relevant accounts in the database (a*, b*, etc). In fact, any keyword that allows the use of wildcards (e.g. LIKE, CONTAINS) or uses them implicitly (BEGINSWITH, ENDSWITH) should be avoided. A full description of format string syntax can be found in Apple’s Predicate Programming Guide.
Remediation of wildcard injection vulnerabilities is a fairly simple matter. First of all, convert the format string ‘LIKE’ keyword to ‘=’. A ‘LIKE’ query is unnecessary within the authentication routine.
This simple change corrects the easy authentication bypass seen in the previous example.
However, the format string is still vulnerable to injection and can be bypassed by using more complicated predicate instructions. For example, entering the string ’) OR 1=1 OR (password LIKE ‘* into the username field allows an attacker to successfully bypass the authentication requirement.
This attack is very similar to SQL Injection and is the result of string concatenation during format string creation. To complete the secure format string, move the user input to format string objects that are added at runtime as follows.
This fully escapes any attempts at injection using double quotes, which are required to escape out of the format string when built in this manner.
Finally, our application login function is secure from format string injection.
As an application penetration tester, identifying format string injection points is critical to determining the security of an application. During an assessment, identification of Core Data use can be difficult. Some fields may be linked to user preferences or backend web services. The only sure way to identify these vulnerabilities is through source code analysis. Given client limitations in providing an Xcode project for analysis, fuzz each available field with the values identified in this guide, including the single quote (‘), double quote (“), and wildcard character (*).
In future blog posts, we will explore other mobile security issues as they relate to Swift and iOS development, including the OWASP Mobile Top 10. In the meantime, feel free to reach out to me (seth [at] nvisium.com or @sethlaw) with issues or questions related to Swift Security.