Vulnerabilities and Threats in Local Authorization on iOS Devices

We present potential threats of performing local authorization on iOS. You will learn how to protect your resources against unauthorized access.

Wojciech Reguła 2022.01.12   –   7 MIN read
local authorisation security

TL;DR

  • All checks done on the device can be bypassed
  • Move access control logic to the server
  • If you support in-app purchases always verify receipt server-server

Context

As the “mobile-first” slogan became a truth, the market moved the crucial functionalities to the mobile applications. It is natural that complicated applications restrict access to information, data or features. This article shows three patterns that I commonly observe during iOS app pentests. They are all caused by overtrust in the devices and the client-side checks. As the devices shouldn’t be trusted, developers have to keep in mind that any client-side check can be bypassed.

Vulnerability 1: Managing users – Cross-role access control on iOS

The first common vulnerable pattern is improper verification if the currently logged user has a proper role to perform certain action. Consider the following scenario:

  1. After the first startup, the user logs in.
  2. The backend returns an OAuth token containing the role
  3. The application verifies the token by checking the signature
  4. If the validation succeeded, the app saves the user’s role in the user defaults
  5. Based on that role application grants access to the proper views

The problem starts when the server doesn’t verify if the user should even have access to that view. The user sends a HTTP request without having an appropriate role. Since the server accepts that request, the attacker performed an action that shouldn’t have access to.

Proof of concept:

The analyzed application saves the role in the user defaults that was observed using Passionfruit:

The attacker attached lldb and overwritten the role value:

Now the Passionfruit shows:

Vulnerability 2: Locked features

Another example of a bad pattern is restricting features / access to resources that are already on the devices. Once, during pentests I analyzed a video streaming application that was restricting access to videos. If the user had bought access to the movie they could open it. I investigated how the validation mechanism works. As it turned out, the videos were downloaded on the device and then the access validation was performed. Let’s consider the following Swift code:

static func hasPremium() -> Bool {
   if someLogic() {
       return true
   }
   return false
}

The code contains a function checking if the user has a premium account. It returns a boolean accordingly. The easiest way to bypass that logic is to attach the lldb and change the return function.

So, let’s set a breakpoint on the hasPremium function.

Continue the execution of the application.

Then go right after the function and change the value of x0 register.

As you can see in the screenshot below, we were able to change the code execution flow and modify the returned value. Make a notice that we’ve done that in the application coded in Swift. I heard from developers many times that Swift is not Objective-C and cannot be easily manipulated. We’ve just confirmed where the truth lies.

Threats in In-app purchases on iOS

Purchases that users make in the application are the most obvious way to monetize the applications. Abusing the purchases in your application may directly harass your business, so I decided to write a subsection especially for that problem. Implementing a secure application with purchases has to start during the architecture creation process. If you implement your application incorrectly it may lead to bugs described in the previous subsections. You may say – “how many clients will be security experts being able to attach a debugger and modify the code execution flow?”. Rather not many. However, in most cases, the potential attackers don’t have to be security experts or even developers. There are universal tweaks available which every script kiddie can install. Take a look at the https://techinformerz.com/localiapstore/. Another scenario is that a “security expert” will patch your application and place it in the jailbreakers store. So, again, any script kiddie will be able to get your application with all the premium content.

On the screenshot below you can see the transaction process using Apple’s standard StoreKit API.

The user taps the buy button, the App Store’s alert is displayed, the user pays for the product and Apple sends you a receipt. It’s on your side now to validate if the receipt is valid and grant access to the bought resources. According to Apple’s documentation, the receipt contains purchase Information, certificates and signature. As you probably guess, if you do the receipt validation locally in your application you lost the battle. The only way to do it securely is to move the access logic to your server! So, the algorithm should be:

  1. The user buys a product
  2. The Apple’s receipt is delivered to the user’s device
  3. The user’s device sends the receipt to your server along with the session identifier (You have to know who sent the receipt)
  4. The server sends the receipt to Apple using this API.

Now your server knows if the user bought the product or not. The server should decide whether the access should be granted or not. Please remember that the attacker may change the HTTP responses that the server sends to your application. Make sure you have designed the application architecture well.

Summary

The purpose of this article was to warn you about the potential threats of performing local authorization. If you are interested in other aspects of mobile application security we highly recommend you our Guidelines on mobile application security – iOS edition

As you saw in this article, attackers can modify everything that is stored on their devices. Most of the protections can be bypassed even by the inexperienced person knowing a little bit of simple reverse engineering methodologies. If your business is to sell premium content via application, make sure you do that correctly. As there is usually no need to use sophisticated methods requiring more than installing one simple tweak, even script kiddies can harm your business. The conclusion is very straightforward – keep as much authorization logic as possible on your server.

If you have any questions about this article feel free to contact us via contact form. 

Wojciech Reguła
Wojciech Reguła Principal IT Security Consultant
Head of Mobile Security