Attackers want your data and they're getting it from your API

Tim Bond

Cascadia PHP - October 24, 2024

Who am I?

  • PHP developer
  • API developer
  • API connoisseur
  • Frontend developer
    (when I have to be)
  • Cyclocross racer

Who am I NOT?

  • Lawyer
  • Security expert
  • Penetration tester
  • Knower of everything
  • Cat 1 cyclocross racer

What is this talk?

  • Things I've seen
  • Things I can talk about
  • Written from a mobile app perspective
  • Still applicable to web APIs
  • Also applicable to M2M APIs

What is this talk NOT?

  • A hacking workshop
  • The answer to every question
  • The only thing you should consider
  • Targeting SaaS APIs (e.g. Stripe, Twilio)
  • Going to have any more cyclocross references

What is considered an API?

  • For the web app
  • For the mobile app
  • AJAX endpoints
  • Partner integrations
  • Internal integrations
  • Webpages*

Why attack an API?

  • Curiosity/data mining
  • Espionage or "competitor analysis"
  • Grudge
  • No other way to get data
  • Want to build their own frontend/bot
  • API key application was rejected
  • Automation

'Automating' comes from the roots 'auto-' meaning 'self-', and 'mating', meaning 'screwing'.

Image credit: XKCD "Automation", licensed Creative Commons Attribution-NonCommercial 2.5

TL;DR:

  • Limit your API responses
    • Only the data you need to make the app work
  • Only who needs to see it
  • Ongoing monitoring - automated and human-assisted

Code bugs > everything else

  • Google+ breach in November 2018
  • 52.5 million users
    • Name
    • Email address
    • Occupation
    • Gender
    • Age

An example app

Obscurity != Security

Let's hack it!

  1. Set up a packet sniffer
    • Counter measure: use HTTPS
  2. Set up a Man-In-The-Middle attack
    • Counter measure: use certificate pinning
  3. Bypass certificate pinning
    • Counter measure: dynamic integrity check
    • Maybe: check for root

iOS Call Recorder app

[security researcher Anand] Prakash could view and modify the network traffic going in and out of the app. That meant he could replace his phone number registered with the app with the phone number of another app user, and access their recordings on his phone."

Let's hack it!

GET http://api.example.com/items
POST http://api.example.com/analytics
PUT http://api.example.com/scan/498044355635
POST http://api.example.com/analytics

Look at the payload: GET /items

[
    {
        "title": "Bleach",
        "upc": 0498044355635
    },
    // more items
]

Look at the payload: PUT /scan/nnn

{
    "user_id": 1234,
    "latitude": 41.9972705,
    "longitude": -87.8834467
}

How can we hack it?

  • API has no authentication 🥳
  • There are some analytics, but we can probably ignore that
  • Upon opening the app, we get a list of all the products
    • Just iterate over that list and send 10 PUT requests
    • Put it in a cron job and you'll have a coupon every time you shop
    • Set it up for your friends (just get their ID)

Let's keep exploring the API

  • Try some other routes
    • It looks RESTful, so how about /user/123
    • Or /users
  • Any docs?  Try URLs like /docs or /swagger.json
  • Let's try a route we know doesn't exist, and see if we get a stack trace

Rate limiters

  • /user/123
  • /user/124

 

(more on this later)

A case for UUIDs

  • /users/123
    • /users/124
  • /users/FA091B58-B0E8-46E9-8DEE-592EBA4D62C4
    • ??

Get User Example

// GET /api/users/{id}
public function getUser(string $id) {
    return $this->database->getUser($id);
}

View Models to the Rescue

public function getUser(string $id) {
    $info = $this->database->getUser($id);
    
    if($this->currentUser->isAdmin()) {
        return new AdminUserResponse($info);
    } elseif($this->currentUser->id == $info->id) {
    	return new UserResponse($info);
    } else {
        return new OtherUserResponse($info);
        //or throw new HttpNotAuthorizedException();
    }
}

Write tests!

  • Test every endpoint:
    • Authenticated
    • Unauthenticated
    • Every role
    • Every query string param

Web Application Firewall

  • Protects against common exploits
    • XSS, SQL injection, etc
  • Designed to detect and stop scraping attacks

Maybe it's time for some auth

  • Auth Basic
  • Auth Digest

Maybe it's time for some auth

  • API keys?
    • Partner/User API keys
    • Application API keys
  • NEVER use static API keys
    • Compromised as soon as they're used
    • Generally easy to find in the source code
    • Hard to rotate

Want a key?  Check GitHub!

Token Authentication

  • Assign a unique string to each user
  • Better: assign to each user to each session
  • Has a defined TTL
  • Server can revoke or extend at any time
  • In a way it's a per-user API key
    • Now we can identify who makes each request

How it Started...

...How it's Going

Central Auth Server

Auth

Server

Search API

Map

API

JWT

JWT

  • Know exactly who is making the request
    • Can assign to known users and unknown
  • Time limited
  • Can't revoke one
    • But you can revoke them all

JWT

  • What to do when it expires?
    • Force the user to log back in
    • Use refresh tokens

Don't give access to everything

👈 No access to Purchase API

With valid auth,
users can still make
any request

Let 'em sniff, but kill repeatability

  • HMAC
    • Hash-based Message Authentication Code
  • Gather the payload and sign the request

Signed

GET /users/123

API_KEY = NWTPk4

APP_ID = wQrDfM

Unsigned

GET /users/123

API_KEY = NWTPk4

APP_ID = wQrDfM

HMAC = APvNwF

🔒

Bonus: the API can returned signed URLs

Getting the (client side) signing key

  • Look around the app source for a key
  • Set a breakpoint just before the HTTP request
  • See if the app logs to a console
    • Browser console on web
    • deviceconsole on iOS
    • logcat on Android

Make the signing key dynamic

  • Much more difficult to find in code
  • Must be deterministic so server can duplicate

Example: concatenate:

  • The string length of some class name
  • The app version number
  • The UTC date + hour

Reverse engineering the runtime

  • Connect the app to a debugger
  • Decompile the Android app
  • Works on iOS too--ask the jailbreakers

Proxify the APIs

  • App only uses one secret
  • Proxy verifies that secret
  • Proxy reaches out to the actual APIs on the user's behalf
    • Much easier to rotate API auth for 3rd party systems
  • But we're still dealing with a secret 😕

Secrets as a Service

API

Shared secret

Unauthenticated request

Secret token

API call ✅

Dynamic

Integrity
Check

Using OAuth 2

API 1

API
Gateway

Authorization request

Auth token

App Auth request

App token

OAuth 2 service

App auth service

API calls

Registered

app info

Registered

user info

API 2

API 3

Key 3

Key 1

Key 2

OAuth 2 flow

  • Authorize both who (user) and what (app)
  • Only time-limited, runtime tokens
  • Don't think of OAuth2 as user authit's an access token generator
  • Rotate secrets without touching devices
  • API gateway does rate limiting and authentication

What about endpoints that can't have authentication?

  • Can still authenticate the device
  • Rate limiting

What about endpoints that can't have authentication?

  • Can still authenticate the device
  • Rate limiting
  • Monitoring
  • Heuristics
    • IP
    • User agent
    • Time between requests
    • Geo data
  • Your API gateway might do this for you!

No API?  No problem!

No API?  No problem!

<?php
$crawler = $client->get('https://www.example.com/log-in');
$crawler->filter('#email')->sendKeys('tim.bond');
$crawler->filter('#password')->sendKeys('test123');
$crawler->filter('#log-in')->click();
$client->waitForStaleness('#log-in');

$client->waitFor('#price')->filter('#price')->getText();

But we have a CAPTCHA!

  • Dozens of services will solve those
  • Images recognized with OCR/AI and/or Humans

Conclusion

  • Dumping an API via HTTP > DB via SSH
  • If they want it bad enough they will try hard enough
  • Reveal only what the current user needs
  • Don't use static authentication
  • Debug protection and code obfuscation thwart semi-determined attackers
  • Authenticate the app (environment) as well as the user

Further Reading

  • OWASP API Security Top 10 2019
    • 2023 edition being written as of February
  • Hacking APIs: Breaking Web Application Programming Interfaces by Corey Ball
  • Web Security Academy: Free Online Training from PortSwigger
  • OWASP Mobile Application Security Verification Standard (MASVS)

Questions