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

Tim Bond

PHP UK Conference - 16 February, 2023

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

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",
        "ean": 0498044355635
    },
    // more items
]

Look at the payload: PUT /scan/nnn

{
    "user_id": 1234,
    "latitude": 51.5205,
    "longitude": 0.091
}

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 2 days ago
  • 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

Attackers want your data and they're getting it from your API [PHP UK]

By Tim Bond

Attackers want your data and they're getting it from your API [PHP UK]

PHP UK Conference - 16 February, 2023

  • 93