Bounty Report: How We Discovered Uber‘s Developer Applications Were Leaking Client Secrets and More

Uber car on city street at night

In October 2018, Anand Prakash and Manisha Sangwan from the AppSecure security research team discovered a critical information disclosure vulnerability in Uber‘s public API. The vulnerability allowed attackers to retrieve confidential data belonging to Uber developer applications, including client secrets, server tokens, and other sensitive details.

As a full-stack developer and coder, discovering a flaw like this in a major tech company‘s API is both exciting and concerning. It‘s a reminder that even the most well-resourced companies can make mistakes in API design and access control that put user data at risk. In this report, I‘ll share a detailed technical analysis of the vulnerability, the risks it posed, and the lessons learned for secure API development.

About Uber‘s Developer Platform

Uber is one of the most ubiquitous and influential tech companies of the past decade. With a mission to "ignite opportunity by setting the world in motion", Uber has revolutionized transportation and pioneered the gig economy. As of April 2022, Uber has over 118 million monthly active users worldwide and a market cap of $73 billion.

To achieve such massive scale, Uber relies heavily on its developer platform and API ecosystem. The Uber API allows third-party developers to integrate Uber services into their own apps, enabling use cases like:

  • Booking Uber rides from within a hotel or airline app
  • Expensing Uber trips for business travelers
  • Accessing trip data for analytics and visualization
  • Ordering food delivery via Uber Eats

Uber‘s API is RESTful and uses OAuth 2.0 for authentication and authorization. Developers can request different scopes to access specific resources and functions, like user profile data, trip history, or the ability to request rides on behalf of users.

When a developer registers an application with Uber, they receive a client_id and client_secret. The client_secret is a sensitive credential used to authenticate the application with Uber‘s API. Uber‘s documentation warns developers to protect their client_secret like a password:

The secret for your application. This should be treated like your application‘s password and must be kept confidential. Never share this value with anyone, and never include it in client-side code or binaries that could be decompiled. If you suspect that your client_secret has been compromised, reset it immediately in the Uber Developer Dashboard.

With over 200,000 registered developers and high-profile partners like Expensify, Booking.com, and Petco, the security of Uber‘s API is paramount. A vulnerability leaking client_secrets could allow attackers to compromise countless applications and put millions of users‘ data at risk.

Technical Details of the Vulnerability

The vulnerability resided in the /api/getAuthorisedApps endpoint of riders.uber.com. This API allowed authenticated Uber users to fetch a list of third-party applications connected to their account. However, the response contained excessive amounts of data belonging to the applications themselves, including client_secrets, server_tokens, and other confidential details.

Here‘s an example of the API request and response:

POST /api/getAuthorisedApps HTTP/1.1
Host: riders.uber.com
Content-Type: application/json
X-CSRF-Token: <user‘s CSRF token>
Cookie: <user‘s session cookie>

{}

HTTP/1.1 200 OK
Content-Type: application/json

{
  "data": [
    {
      "applicationDetails": {
        "applicationId": "abc123", 
        "applicationSecret": "542c9c1f-e221-4b47-8093-5a1a146d4a45",
        "serverTokens": [
          "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
        ],
        "description":"Example Application",
        "webhookUrl": "https://example.com/uber/webhook",
        "redirectUris":[
          "https://example.com/uber/oauth/callback"
        ],
        "clientScopes": [
          {
            "clientId": "abc123",  
            "scopes": ["profile", "history"]
          }  
        ],
        "owner": {
          "uuid": "575d25e9-62d2-44d9-b1d1-9ece4a943f93",
          "email": "[email protected]"  
        },
        "admins": [
          {
            "uuid": "df9375e1-3f73-402b-9c39-e8c74e32c234", 
            "email": "[email protected]"
          },
          {  
            "uuid": "2910ba15-023f-4dbc-9bb3-82b01c3218ac",
            "email": "[email protected]" 
          }
        ],
        // ... additional application fields
      }
    }
  ]
}

As you can see, the response exposed a veritable treasure trove of sensitive application data:

Data Description
applicationSecret The OAuth client_secret used to authenticate the application with Uber‘s API
serverTokens Privileged tokens used by the application backend to make API calls on behalf of users
owner.uuid, owner.email The user ID and email address of the application owner
admins[].uuid, admins[].email The user IDs and email addresses of the application admins
redirectUris The allowed callback URLs for the application‘s OAuth flow
webhookUrl The destination for Uber to send webhook event notifications to the application

Leaking any one of these pieces of data would be bad enough, but leaking them all together was a nightmare scenario. With the client_secret and server_tokens, an attacker could impersonate the application and make arbitrary API calls as any user who had granted it permissions. The attacker could extract additional user data, modify trip details, or even book fraudulent rides.

The inclusion of owner and admin email addresses also exposed these individuals to spear phishing and social engineering attacks. And the redirectUris could be used to craft malicious OAuth authorization URLs to steal user access tokens when clicking through.

Proof of Concept Attack Scenario

To demonstrate the severity of this vulnerability, let‘s walk through an example attack scenario:

  1. The attacker signs up for the Uber app and creates a rider account.

  2. The attacker tricks a victim user into granting access to a malicious application that the attacker controls. This could be done through phishing emails, social media links, malicious ads, etc.

  3. With the malicious application now authorized on the victim‘s account, the attacker makes a POST request to /api/getAuthorisedApps with the attacker‘s own session cookie to retrieve the application‘s client_secret and other details.

  4. Using the leaked client_secret, the attacker makes authenticated requests to Uber‘s API to access the victim‘s trip history, request rides on their behalf, and extract additional PII.

  5. The attacker could then attempt to compromise accounts on other services where the user might have reused their Uber password. The attacker could also use the victim‘s trip data for stalking, blackmail, or other malicious purposes.

  6. The attacker could potentially automate and scale up this attack to quickly compromise a large number of Uber users and connected applications.

Business Impact and Risks

The potential business impact of this API vulnerability was immense given Uber‘s scale and the sheer number of affected users and applications. If exploited in the wild, it could have resulted in:

  • Data breaches and regulatory fines: Leaking PII like user email addresses would likely run afoul of data protection regulations like GDPR and CCPA. Uber could face hefty penalties and lawsuits.

  • Reputation damage: A high-profile security incident leaking developer secrets would erode trust in Uber‘s API ecosystem. Partners might pull their applications and integrations.

  • Fraud losses: Attackers could abuse leaked client_secrets and server_tokens to book unauthorized trips and pocket the payments. Uber would likely have to eat these costs.

  • Competitive risk: Leaked application details and usage data could expose strategic partnerships and integrations before they were ready to be announced publicly.

The fact that this vulnerability made it into production and sat undetected for who knows how long was a major failure of Uber‘s API security practices. It‘s the type of flaw that should be caught by code reviews and security testing long before release.

Lessons for API Security

As a developer, what are the key takeaways from this incident for designing and implementing secure APIs? Here are some best practices to follow:

  1. Principle of Least Privilege: Only return the bare minimum data necessary in API responses. Sensitive application credentials should never be returned to end users.

  2. Granular Access Control: Restrict read access to sensitive resources to only trusted and authenticated entities. Implement granular role-based access control (RBAC) for different user types.

  3. Secure Defaults: Deny access to resources and data by default. Require explicit opt-in for applications to access sensitive scopes and user data.

  4. Input Validation: Sanitize and validate all incoming request data to prevent injection attacks and maintain data integrity.

  5. Strong Authentication: Implement multi-factor authentication for sensitive actions and require strong, unique API keys and secrets. Use short-lived access tokens instead of long-lived refresh tokens.

  6. Encryption in Transit: Use HTTPS/TLS for all API endpoints and encrypt sensitive data like access tokens in transit. Implement HTTP Strict Transport Security (HSTS).

  7. Security Testing: Conduct thorough security reviews of API code changes and perform penetration testing to proactively find vulnerabilities. Leverage static code analysis tools to detect sensitive data leakage.

  8. Security Monitoring: Use API gateways and web application firewalls to monitor traffic and detect anomalous activity. Audit access to sensitive data and credentials.

  9. Incident Response: Have a documented incident response plan for quickly investigating and remediating API security incidents. Practice these procedures with regular tabletop exercises.

API security is a complex and multifaceted challenge, especially for large platforms like Uber with sprawling ecosystems of internal and third-party applications. The stakes are high – Gartner predicts that by 2022, API abuses will be the most frequent attack vector for enterprise web applications.

Uber definitely dropped the ball with this /getAuthorisedApps endpoint, but to their credit, they responded quickly and transparently once notified. They deployed a fix within a month, rewarded the researchers with a $5,000 bug bounty, and disclosed the vulnerability to all potentially impacted developers.

No application is immune to bugs and security holes, but a rapid and coordinated response can make all the difference in mitigating damage. Uber has published guidelines for responsible disclosure of vulnerabilities, including a PGP key for encrypted communications.

The Road Ahead for API Security

In today‘s hyper-connected web ecosystem, APIs are the glue holding everything together. Virtually every modern web and mobile app relies on APIs under the hood to access data and functionality. API traffic already makes up over 80% of all web traffic for many industries.

But as API usage has exploded, so too has the API attack surface. Akamai found that up to 75% of credential abuse attacks target APIs directly. High-profile API breaches at companies like Facebook, Venmo, and Panera Bread have exposed billions of users‘ personal data.

The hard truth is that many organizations simply don‘t put enough emphasis on API security. 31% of companies have no API security strategy in place. APIs are often treated as an afterthought in the software development lifecycle, with testing and monitoring bolted on after the fact.

If we want to get serious about API security, this mindset needs to change. Security must be a key consideration from day one of API development. Threat modeling, secure design reviews, and security testing need to be integrated into every stage of the API lifecycle.

At the same time, we need more transparency and collaboration across the industry when it comes to identifying and mitigating API vulnerabilities. Uber sharing this client_secret leakage flaw so candidly is a step in the right direction. The more organizations adopt coordinated vulnerability disclosure and safe harbor for researchers, the safer the API ecosystem will become.

Conclusion

As a developer, it‘s easy to become numb to the constant barrage of security horror stories. But we owe it to our users and customers to treat every vulnerability with the gravity it deserves, no matter how "minor" it may seem. Leaking API keys and tokens is the digital equivalent of leaving the vault doors wide open at a bank.

No company is too big to fail when it comes to API security. Uber is a technological juggernaut with near-limitless resources, yet it still managed to ship a major vulnerability that put millions of users‘ data at risk. It‘s a sobering reminder that there is no finish line when it comes to securing our software.

As the internet continues its relentless march towards API-fication, it‘s up to us as developers to prioritize security just as highly as scalability and performance. Every line of code we write should be held to the highest standards of security scrutiny.

Let‘s treat our users‘ data with the care and respect it deserves. Let‘s design APIs that are resilient, fault-tolerant, and secure by default. Let‘s ruthlessly test and monitor our applications for any signs of weakness.

And if we do discover vulnerabilities, let‘s have the courage to be transparent, own up to our mistakes, and work diligently to make things right. Our users are counting on us.

Similar Posts