# Security Analysis: Purolator Mobile App - Tracking API Credentials

## 🔴 CRITICAL VULNERABILITY: Hardcoded & Extractable API Keys

### Executive Summary

Your tracking API credentials are **trivially extractable** from the APK. While they appear "encrypted," all decryption components are bundled in the app, making this a **false sense of security**.

---

## Vulnerability Details

### 1. **Location of Hardcoded Credentials**

**File:** `com/purolator/mobileapp/utils/security/X.java`

**Method:** `c()` - Line 77

```java
TuplesKt.a(KCART, d("EiTT1YdYxrJeWAMlSoyhIs8AZlB3ye8qPpd" + a2.c(), a2.h(), a2.f()))
```

**What's exposed:**

- `KCART` = "TRACK" reversed → **Tracking API token**
- `KNIL_KCART` = "TRACK_LINK" → **Tracking API endpoint URL**
- `P_KCART` = "TRACK_P" → **Tracking API authentication parameter**

### 2. **Encryption Method Analysis**

**File:** `com/purolator/mobileapp/utils/security/X.java`

**Method:** `d()` - Lines 79-119

**Encryption Details:**

- **Algorithm:** AES/CBC (despite saying GCM)
- **Mode:** CBC with IvParameterSpec
- **Padding:** PKCS7 (implicit)
- **Key:** Base64-encoded, fetched from Firebase Remote Config
- **IV:** Plain string from Firebase Remote Config

**The Fatal Flaw:**

```java
private final String d(String str, String str2, String str3) {
    // str = encrypted value (partially hardcoded in APK)
    // str2 = base64 encryption key (from Firebase)
    // str3 = IV string (from Firebase)

    byte[] d2 = BasicBase64.d(str2);  // Decode key
    SecretKeySpec secretKeySpec = new SecretKeySpec(d2, 0, d2.length, "AES");
    byte[] bytes = str3.getBytes(UTF_8);  // IV from string
    cipher.init(2, secretKeySpec, new IvParameterSpec(bytes));  // Decrypt mode
    byte[] doFinal = cipher.doFinal(BasicBase64.d(str));  // Decrypt
    return new String(doFinal, UTF_8).trim();
}
```

### 3. **Data Flow Architecture**

```
┌─────────────────────────────────────────────────────────────────┐
│                        APK (Decompiled)                         │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  1. X.java - Line 77:                                          │
│     "EiTT1YdYxrJeWAMlSoyhIs8AZlB3ye8qPpd" + Firebase_Suffix    │
│                                                                 │
│  2. Firebase Remote Config (fetched at runtime):               │
│     {                                                           │
│       "KCART": "...rest_of_encrypted_token...",                │
│       "SSAP": "base64_encryption_key",                         │
│       "ROTCEV": "initialization_vector",                       │
│       "KNIL": {                                                 │
│         "HT": "encrypted_http_url_part1",                      │
│         "KCART": "encrypted_http_url_part2"                    │
│       }                                                         │
│     }                                                           │
│                                                                 │
│  3. Decryption happens in X.d():                               │
│     decrypted_token = AES_CBC_decrypt(                         │
│         encrypted_value,                                       │
│         base64_decode(SSAP),                                   │
│         ROTCEV                                                 │
│     )                                                           │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘
                              │
                              ▼
                    ┌─────────────────────┐
                    │  Tracking API Call  │
                    │  with decrypted     │
                    │  credentials        │
                    └─────────────────────┘
```

### 4. **Attack Vector (How Attackers Extract Credentials)**

#### **Step 1: Decompile APK**

```bash
apktool d purolator.apk
```

#### **Step 2: Extract Hardcoded Partial Encrypted Strings**

From `X.java` line 77:

- `KCART`: `EiTT1YdYxrJeWAMlSoyhIs8AZlB3ye8qPpd` + Firebase suffix
- Similar for other credentials

#### **Step 3: Extract Firebase Remote Config**

**Method A - From Running App (ADB):**

```bash
adb shell
run-as com.purolator.mobileapp
cat shared_prefs/com.google.firebase.remoteconfig_FirebaseRemoteConfig.xml
```

**Method B - Runtime Hooking (Frida):**

```javascript
Java.perform(function () {
  var Utils = Java.use("com.purolator.mobileapp.utils.Utils");
  Utils.j0.implementation = function () {
    var result = this.j0();
    console.log("[+] Firebase Config: " + result.toString());
    return result;
  };
});
```

**Method C - Network Interception:**

- Proxy app traffic through Burp Suite/mitmproxy
- Bypass certificate pinning (if any)
- Capture Firebase Remote Config API response

#### **Step 4: Decrypt Credentials**

Using the provided `decrypt_tracking_api.py` script:

```python
# Concatenate hardcoded prefix + Firebase suffix
full_encrypted = "EiTT1YdYxrJeWAMlSoyhIs8AZlB3ye8qPpd" + firebase_kcart_suffix

# Decrypt using Firebase-provided key and IV
tracking_token = AES_CBC_decrypt(
    base64_decode(full_encrypted),
    base64_decode(firebase_ssap),
    firebase_rotcev
)
```

#### **Step 5: Use Credentials for Unauthorized Access**

- Make direct API calls to tracking endpoint
- Bypass app authentication
- Access tracking data without proper authorization
- Potentially abuse rate limits or costs

---

## Additional Exposed Credentials

### From Line 77 of X.java:

| Key (Reversed) | Original Name  | Description         | Hardcoded Prefix                                                                |
| -------------- | -------------- | ------------------- | ------------------------------------------------------------------------------- |
| `KCART`        | `TRACK`        | Tracking API token  | `EiTT1YdYxrJeWAMlSoyhIs8AZlB3ye8qPpd...`                                        |
| `TNUOCCA`      | `ACCOUNT`      | Account credentials | `FQ/E1KpKybV2Kn87ao2UAcZXf3JbzOsZHek7d09yXrsn+nghl...`                          |
| `DRAC_TIDERC`  | `CREDIT_CARD`  | Credit card data    | `FQ/E1KpK3qZubmgVYoyUEsZWf3FUkesZCew7cGIpXZUkpW0Ijyv...`                        |
| `DI_SELAS`     | `SALES_ID`     | Sales identifier    | `ZCPh+vApxalGQWNIW9X7JscBZF9zqfNoM6MWWVwiTIs6u2s4hlnDvcbLtQvAdpVNW5V2r4pb8m...` |
| `TERCES_SELAS` | `SALES_SECRET` | Sales secret        | `EiuBiosoptFtIXVKMfj7FN5RdgEhypVmfOFCLR0CJqpGihAJ6...`                          |
| `P_HTUA`       | `AUTH_P`       | Auth parameter      | (from Firebase)                                                                 |
| `P_RAEB`       | `BEAR_P`       | Bearer token param  | (from Firebase)                                                                 |

---

## Why This Is Vulnerable

### ❌ **Common Misconceptions:**

1. **"It's encrypted, so it's safe"**

   - ❌ The decryption key is also in the app
   - ❌ The IV is in Firebase Remote Config (easily accessible)
   - ❌ The algorithm is known (AES-CBC)

2. **"Firebase Remote Config adds security"**

   - ❌ Firebase Remote Config is publicly accessible via API
   - ❌ No authentication required to fetch config
   - ❌ Attackers can intercept or directly query Firebase

3. **"Obfuscation protects the code"**
   - ❌ Decompilation tools handle obfuscation
   - ❌ String concatenation is visible
   - ❌ Method names can be traced

### ✅ **Reality:**

- **All components for decryption are available to attackers**
- **Time to extract: ~30 minutes for experienced attacker**
- **Skill level required: Intermediate (not advanced)**

---

## Real-World Attack Scenario

1. **Attacker downloads your APK** from Play Store or third-party site
2. **Decompiles using jadx/apktool** (5 minutes)
3. **Finds X.java** and extracts hardcoded prefixes (5 minutes)
4. **Intercepts Firebase Remote Config** using proxy or ADB (10 minutes)
5. **Runs decryption script** (provided above) (2 minutes)
6. **Gets tracking API credentials** in plaintext
7. **Makes unauthorized API calls** to track shipments
8. **Potential impacts:**
   - Track any shipment without authorization
   - Scrape tracking data at scale
   - Abuse your API quota/costs
   - Potentially access customer PII through tracking APIs

**Total Time:** ~30 minutes  
**Cost:** $0  
**Detection:** Difficult (looks like legitimate API traffic)

---

## Recommended Fixes

### 🔥 **Immediate Actions (Do This Now)**

1. **Rotate ALL exposed credentials**

   - Change tracking API keys
   - Update Firebase Remote Config values
   - Invalidate old tokens

2. **Add server-side authentication**
   - Don't trust client-side credentials
   - Validate requests on your backend
   - Use short-lived tokens

### 🛡️ **Long-Term Solutions**

#### **Option 1: Backend Proxy (BEST)**

```
Mobile App → Your Backend → Tracking API
            ↑ (authenticated)
```

**Benefits:**

- ✅ No credentials in app
- ✅ Full control over access
- ✅ Rate limiting
- ✅ Logging and monitoring
- ✅ Can rotate credentials without app update

**Implementation:**

- Create `/api/track` endpoint on your server
- Authenticate users (OAuth, JWT, etc.)
- Proxy requests to tracking API
- Never send API keys to client

#### **Option 2: Dynamic Token Exchange**

```
App requests token → Backend validates → Issues short-lived token → App uses token
```

**Benefits:**

- ✅ Tokens expire quickly (5-60 minutes)
- ✅ Can revoke tokens
- ✅ Tied to user session

#### **Option 3: App Attestation**

- Use Google Play Integrity API
- Verify app hasn't been tampered with
- Issue tokens only to verified apps
- Block rooted/modified devices

#### **Option 4: Certificate Pinning + Token Encryption**

- Pin SSL certificates
- Encrypt tokens with device-specific keys
- Use Android Keystore for secure storage
- Make extraction much harder (but not impossible)

---

## Testing the Vulnerability

I've created a decryption script: `decrypt_tracking_api.py`

**To test:**

1. Extract Firebase Remote Config from your app
2. Run the script
3. Provide the Firebase values when prompted
4. Script will output decrypted credentials

**This proves:**

- The vulnerability is real
- Credentials are extractable
- Attackers can do this easily

---

## Compliance & Legal Impact

### **Potential Violations:**

- **PCI DSS:** Storing credit card data insecurely
- **PIPEDA (Canada):** Inadequate protection of personal information
- **SOC 2:** Failure to protect sensitive credentials
- **ISO 27001:** Insufficient access controls

### **Business Impact:**

- Customer data breach
- Financial losses from API abuse
- Reputational damage
- Legal liability
- Regulatory fines

---

## Timeline for Remediation

| Priority  | Action                         | Timeline        |
| --------- | ------------------------------ | --------------- |
| 🔴 **P0** | Rotate all exposed credentials | **Immediately** |
| 🔴 **P0** | Implement backend proxy        | **1-2 weeks**   |
| 🟠 **P1** | Add app attestation            | **2-4 weeks**   |
| 🟠 **P1** | Remove hardcoded values        | **2-4 weeks**   |
| 🟡 **P2** | Certificate pinning            | **4-6 weeks**   |
| 🟢 **P3** | Security audit & pen test      | **6-8 weeks**   |

---

## Questions?

If you need help implementing any of these fixes, I can:

1. Write the backend proxy code
2. Implement token exchange system
3. Set up app attestation
4. Review your new security architecture

**Remember:** The goal isn't to make extraction impossible (it never is), but to make it:

1. **Hard enough** that only sophisticated attackers try
2. **Detectable** so you know when it happens
3. **Revokable** so you can respond quickly
4. **Limited in impact** through proper scoping

The current implementation fails all four criteria.
