I haven’t used Firefox as my primary browser in many years, so I have to admit that I hadn’t heard of Pocket until I saw this Bugzilla bug in a Hacker News post. In short, the Mozilla Foundation bundled what is essentially an opt-out, non-removable Pocket extension into all versions of Firefox. In spite of a mild end-user revolt on Bugzilla and the Mozilla governance mailing list, the Mozilla Foundation made no changes to their policy of bundling Pocket with Firefox.
So what is Pocket? Pocket allows users to save web pages for later reading. The links can then be read offline on various web and mobile platforms. As an information security practitioner, I’ve found this type of functionality often leads to very predictable security vulnerabilities, so I decided to take a quick look at Pocket.
One may notice that I discuss using basic application functionality to demonstrate these vulnerabilities, as most were exploitable by an attacker with only a browser, the Pocket mobile app, and access to a server in Amazon EC2. No sophisticated tooling was required to exploit these issues, nor was even basic scripting.
Note that Pocket has a responsible disclosure policy. All the vulnerabilities detailed below were reported to Pocket immediately, and this disclosure was voluntarily delayed for 21 days from the initial report to allow Pocket time to remediate the issues identified.
Pocket was responsive throughout the reporting process. The exact first-order attack vectors I reported to Pocket were quickly fixed, and can no longer be used to exploit the application.
The queue management on the Pocket website allows users to manually add a URL to their queue. Given the purpose of the application, these links should be limited to http and https URLs. First, I tried adding some of the following links to my Pocket queue:
Unfortunately none of these worked.
I had previously noticed an Apache error message on the Apache server status page. This message is commonly seen when .htaccess or Apache configuration limits server-status access to localhost, or some trusted netblocks.
Forbidden You don't have permission to access /server-status on this server.
I added a new link to my Pocket queue. When a link is added to the Pocket queue, a backend server will make an HTTP request to obtain the content. Would Apache trust a request from localhost?
This attempt was successful. Soon I saw the following in my Pocket queue:
Apache Server Status for 127.0.0.1 Server Version: Apache/2.2.29 (Unix) DAV/2 Server Built: Mar 12 2015 03:50:17 Current Time: Tuesday, 28-Jul-2015 10:07:45 CDT Restart Time: Tuesday, 28-Jul-2015 03:20:12 CDT Parent Server Generation: 12 Server uptime: 6 hours 47 minutes 32 seconds Total accesses: 241913 - Total Traffic: 4.1 GB CPU Usage: u1209.24 s110.06 cu0 cs0 - 5.4% CPU load 9.89 requests/sec - 177.5 kB/second - 17.9 kB/request 40 requests currently being processed, 14 idle workers ...
The full output from server-status then was synced to my Android, and was visible when I switched from web to article view. Apache’s mod_status can provide a great deal of useful information, such as internal source and destination IP address, parameters of URLs currently being requested, and query parameters. For Pocket’s app, the URLs being requested include URLs being viewed by users of the Pocket application, as some of these requests are done as HTTP GETs.
These details can be omitted by disabling ExtendedStatus in Apache. Most of Pocket’s backend servers had ExtendedStatus disabled, however it remained enabled on a small subset, which would provide meaningful information to attackers.
Additionally, by modifying GET parameters to server-status, an attacker could force the page to be downloaded again, possibly giving the response from a different server:
As Pocket allowed users to retrieve responses from web applications running on the Pocket backend server itself, it was time to see what other data could be exfiltrated with this vulnerability. Simple usage of dig showed that Pocket was using Amazon EC2. A very convenient feature of EC2 instances is Amazon’s instance metadata service. This service is accessible internally, without authentication, on any EC2 instance. Perhaps Pocket would let me inspect the metadata on their EC2 instances?
Once the links appeared in the Pocket queue on my phone, the full contents of the server responses were available. EC2 metadata can include useful information for attackers such as IAM credentials, in addition to details about the instance such as availability zone, instance type, network type, MAC address, details on attached block storage, and so on.
What else could an attacker do here? All of these techniques are easily automatable:
From large enterprises to small startups, it’s relatively common to encounter web applications that are only accessible internally, either from a network segment or the localhost interface on a server. These applications often don’t require authentication, so a malicious attacker would likely attempt to take advantage of this.
From the AWS metadata service, it was apparent that Pocket uses EC2 in the us-east-1 region with classic networking (Note: there are other less intrusive techniques to determine the region of a running EC2 instance). EC2 offers two network types: EC2-Classic and VPC. VPC is the preferred solution today, and certain instance types are only available through VPC. VPC allows for added flexibility to create subnets, ACLs, which allow users to properly segment their network.
Since Pocket was using EC2-Classic, obtaining access to the internal IP addresses revealed in server-status is as simple as spinning up a 2 cent/hour t1.micro instance in us-east-1. From there attackers can use the RFC-1918 addresses to access services running on these instances, such as ssh or http. Portscanning these address is also trivial from an EC2-Classic instance in the same region. These instances are protected by EC2 security groups, however these are often setup in a less restrictive fashion when an elastic IP is not connected.
Using these internal IP addresses to access the backend web servers has a few advantages: namely it bypasses the frontend load balancers and any potential WAF-like functionality on the frontend. In a typical environment with frontend load balancers, it also allows the attacker to set an X-Forwarded-For header which is subsequently treated as the actual source IP address on the backend web application (this header is normally how frontend load balancers forward source IP information). This can be helpful when attackers need to evade ACLs or falsify logs.
From communications with Pocket, I understand that they are currently moving away from EC2-Classic networking.
Applications similar to Pocket require some logic to handle HTTP redirects on links. Misbehaved redirects are often overlooked in such applications. I added a link to my queue that resulted in a somewhat malicious redirect:
HTTP/1.1 301 Moved Permanently Location: file:///etc/passwd Content-Length: 52 Date: Tue, 28 Jul 2015 18:42:58 GMT Connection: keep-alive Moved Permanently. Redirecting to file:///etc/passwd
After refreshing the Pocket app on my Android phone, the list included file:///etc/passwd. Clicking on the item revealed the full contents of /etc/passwd.
Yes, the contents of /etc/passwd were here. Removed at request of Pocket.
The impact of this vulnerability is left as an exercise to the reader.
When testing Pocket, I requested file:///proc/self/status using the redirect vulnerability. This file in the /proc filesystem can be used to determine additional information on the running process.
I didn’t review the content of this redirect until after the issue was remediated. The following is an excerpt from the process status:
Uid: 0 0 0 0 Gid: 0 0 0 0
The consequence of running this process as root is left as another exercise to the reader.
Pocket quickly responded to my reports to remediate the issues I reported, so I was unable to chain multiple vulnerabilities together. But what could a truly malicious attacker have done here?