Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Cover image for We Need To Talk About API Security
Adam Nathaniel Davis
Adam Nathaniel Davis

Posted on • Edited on

     

We Need To Talk About API Security

The first thing we need to establish is that I amNOT any kind of "security expert". If you've been programming for long enough, you can't help but be exposed to security issues. Solid programmers should always be thinking about potential security loopholes. And eventually, you touch enough security-related bugs that you end up thinking that youknow something about the field.

But the simple fact is that security is its own unique field in IT. For good reason. There's sooooo much to learn with regard to security that it's truly its own discipline. You can't be, say, the best React devand the best security expert. At some point... you have to choose.

So, with those caveats out of the way, I still think we need to have a little "security chat". Because I've seen some things, in just the last year-or-two of dev, that have made me really nervous. And those scary things have been centered on APIs.


Alt Text

Not Always A Net-Good

If you've ever been tasked with integrating with some third-party system, the first thing you probably asked was, "Where's the API?" In the worst-case scenario, therewas no API. But far too often, there was an API... sorta. There were a few exposed endpoints / methods / whatever. There were a few ways to do basic tasks. But when you reached the point of trying to buildtrue integration, all too often, the "API" was sorely lacking.

For this reason, APIs usually fall into three distinct categories:

  1. There isNO API. And we curse the programmers who originally created this monstrosity.
  2. There is...some sorta API. It allows you to dosome things. But it also provides no interface for most of the critical features we need to implement. And we curse the programmers who originally created this monstrosity.
  3. There is a true, "full" API. Most-or-all of the features we must implement are already accounted for in the API. And we rejoice in the streets.


But I'm here to tell you: Option #3 isn't always the panacea that it appears to be on the surface. We get so frustrated by systems that lack APIs, or by systems with insufficient APIs, that we assume anything resembling a "full" API must be, unquestionably, an undeniablegood.


Alt Text

Common Pitfalls

I've run into some pitfalls lately that make me very nervous about the systems that our institutions are putting into place. I'm gonna reiterate that I'mNOT a security expert. And I know that security experts could probably extend this article by 10,000 words (or more). But even from my quaint little perch as someone who's "just" a programmer, here are some of the headaches that I've been battling recently:

Manual Updating of Derived Values
Let's imagine that you're writing a football ("soccer", for us Americans) management system. And in that system, you can track a goalkeeper'ssave rate. The "save rate"should be a simple formula that'sderived fromsaves / shotsOnGoal.

But then imagine that you've created the following endpoint in your API:

PUT /v1/player/{playerId}

And finally, let's assume that this endpoint accepts aplayer objectthat includes the 'save rate' value. Do you see the problem with that logic??save rate shouldn't bemanually set. It should becalculated, based on that player's total number of saves, divided by that player's total shots on goal. But I've seen too many APIs where I'm given an endpoint that allows me to update "save rate"directly.

Maybe that's a bit too esoteric (or farcical) for you. So allow me to give you a more real-life example:

Last year, I did security consulting for a bank - a bank withphysical locations - all throughout Texas. I was specifically helping them with theirphysical access system. In other words, I was working on the software that would determine when a particular door was open, or who was allowed to go through that door. I think you'll agree with me that such things are quite importantin a bank, right??

I was working with a vendor's software that allowed you to create an infinite number of rules that would, ultimately, determine whether a door was open at a given time, or whether a given person was allowed through at that time. But the problem I ran into was that, no matter how much time I spent crafting those rules, there was still a REST endpoint that would manually overrideALL of those rules with a simple POST/PUT. Even if every rule in the system said, "LOCK THIS DOOR!!!", you could still do aPUT to the proper endpoint that wouldunlock that door, disregarding every other rule in the system.

For some, the knee-jerk reaction is to say:

Well... If you had the required APIkey to update that door's status, then youshould be able to unlock that door, whenever you want.


But this (simplistic) mindset overlooks the fact that the vendor's base system was intricately designed toforce you to manage all of the appropriate rules. Except... you could bypass the whole system if you just managed to get ahold of the right key.

Many programmers would scoff at such a "weakness". They'd claim that it's nottheir problem if the key falls into the wrong hands.

But I assure you that the client (the bank in Texas) was not satisfied with such an answer. In fact, Iillustrated for them how I could snag their API key -in a mere matter of hours - and proceed to open every door in every one of their locations. Suffice it to say that they were not thrilled.

The point here is not that you can't expose critical functions in your API. But if some value should only ever becalculated through a separate series of rules, then don't expose a method that will allow any-old-programmer to set that value manually, irrespective of those rules.

API Users With God Rights
I wish I was joking - but I've seenthis scenario too many times: The application has an intricate set of roles / rights / permissions defined on the front end. But if you manage to get an API key, that keyalways comes withgod rights.

Think about that. Your app creates finely-delineated rightson the front end. But once someone gets an API key to interact with iton the back end, they can do whatever the hell they want.

I'm not trying to claim that you should never allow an API user with "god rights". But that should never bethe default. And if the app provides fine-grained user controls on the front end, you should almost always be accounting for the same thing on the back end.

I saw this recently with a hardware compliance management system. The client had a very pressing need to illustrate thatall of their users were compliant with government regulations. But their API afforded onlyone access method - access via "god rights". This meant that anyone tasked withbuilding the system also had all of the rights they needed to hide their own non-compliance (if they so chose).


Leaky Interfaces
I also recently found a scenario where the API seemed to be fairly "robust" - except...

By using the API, I was able to infer critical detailsabout the underlying database that stored the API's values. In other words, accessing the API gave me the critical info that I needed to hackdirectly into the database.

Obviously, if you've given me the data I need to crack your underlying data store, then any "security" you slap onto the API layer is rather pointless. With this data in-hand, I actually illustrated for a client how I could change all of their base data without ever officiallyhacking the API itself.


Alt Text

Endless Holes

I know that this is just the tip of the security iceberg. And I know that real "security types" could add sooooo much more to such an article. But I wanted to point out a few of these horrific (and silly) flaws because it seems that I've been running into them with ever-greater frequency in the last year-or-two.

IMHO, there's a common theme that API developers tend to view the API as just an extension of the application'sinternal logic.

They wouldn't create a form field in the app's UI that allowed the user to manually set the value forsaveRate, irrespective of the values forsaves andshotsOnGoal. But they'll create a REST endpoint that allows you toPUT a manual value forsaveRate - even if it doesn't mesh with the other values.

They wouldn't expose their database schema on the frontend. But they'll create a REST endpoint that basically represents a full schema diagram - complete with credentials that match those of the API user.

Too often, we design APIs to be inherentlytrusting of the API user - because the API user is a "technical" user. In other words, the API user is more like "us" - the programmers - than like the end users. But this scenario shouldn't make us moretrusting. It should make us morewary.

Top comments(9)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss
CollapseExpand
 
wclayferguson profile image
Clay Ferguson
Software Developer. Creator of https://quanta.wiki
  • Location
    Dallas, TX
  • Work
    Software Engineer
  • Joined
• Edited on• Edited

You are right that lots of web security protocols just use a "God Rights" key that allows any REST call to do anything. The more appropriate way is to have any "caller" of the remote service be required to have an RSA PKE key such that every call is done with some 'identity', and to each of these identities the system knows which privileges are allowed (which buildings are controllable, what things are able to be deleted, etc).

Of course going along with this architecture you can have the requester be required to do a PKE based digital signature of the request (to send along with the request, like in an HTTP header) so that the server side can also be certain the request did indeed originate from who it's supposed to have.

Having HTTPS makessome of this redundant, so the real key thing I'm saying here is:
1) Don't use tokens with God Rights
2) Make each user/role have the minimal privileges that it's required to have so that there's no way it can go rogue even if hacked.

CollapseExpand
 
bytebodger profile image
Adam Nathaniel Davis
React acolyte, jack-of-all-(programming)trades, full-stack developer
  • Email
  • Location
    New Orleans, LA
  • Work
    Frontend Software Engineer
  • Joined

Totally agree.

CollapseExpand
 
kallmanation profile image
Nathan Kallman
Husband; Father; Software Engineer; Gamer; Tinkerer; Writing about code on DEV.
  • Location
    Columbus, OH
  • Education
    B.S. Computer Engineering
  • Work
    Engineering Manager at Root Insurance
  • Joined

Yes! Too many developers see web APIs as another interface between areas of the code little different to a function call or an object.

A Web API doesn'tsupport the front-end, itis the front-end (at least when it comes to security and logical control).

We must assume that if itcan be done, at some point itwill be done... if something is behaviorally important, the mechanisms of the API should actually enforce the behavior, not just allow the behavior.

CollapseExpand
 
bytebodger profile image
Adam Nathaniel Davis
React acolyte, jack-of-all-(programming)trades, full-stack developer
  • Email
  • Location
    New Orleans, LA
  • Work
    Frontend Software Engineer
  • Joined

Exactly!

CollapseExpand
 
michaelphipps profile image
Phippsy
I like beer.I like whiskey more.
  • Location
    Australia
  • Work
    Fullstack Developer at Phippsy Tech
  • Joined

There are times I will say there is a security flaw in an endpoint, and my business partner will say "but chances of that are low, I'm not worried. Push it.".

CollapseExpand
 
bytebodger profile image
Adam Nathaniel Davis
React acolyte, jack-of-all-(programming)trades, full-stack developer
  • Email
  • Location
    New Orleans, LA
  • Work
    Frontend Software Engineer
  • Joined

SMH. So true, but still... SMH.

CollapseExpand
 
_khaledfarah profile image
Khaled Farah
  • Location
    Dubai
  • Work
    Software engineer at NOW Money
  • Joined

Hi Adam,

Great article. I was hoping if you could demonstrate more by adding technical examples.

CollapseExpand
 
bytebodger profile image
Adam Nathaniel Davis
React acolyte, jack-of-all-(programming)trades, full-stack developer
  • Email
  • Location
    New Orleans, LA
  • Work
    Frontend Software Engineer
  • Joined
• Edited on• Edited

It's more of a concept than a technical example. But to try to be a little more specific, I've recently been working on a system that manages compliance on individual machines. "Compliance" is a concept that isderived from many different factors. If the device doesn't have updated antivirus files, or if it's outside its acceptable geographic area, or if it's not encrypted, or ifmany other factors - it'snoncompliant.

But when you look at the API for the software, there's aPUT /v1/device/{id} endpoint that allows you to update -directly - the "compliant"true/false value. But that makes no sense. You shouldn't be able to justset a device to be "compliant". It should becalculated to be compliant (or non-compliant) based on all the other factors.

CollapseExpand
 
ben profile image
Ben Halpern
A Canadian software developer who thinks he’s funny.
  • Email
  • Location
    NY
  • Education
    Mount Allison University
  • Pronouns
    He/him
  • Work
    Co-founder at Forem
  • Joined

Loving this series

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

React acolyte, jack-of-all-(programming)trades, full-stack developer
  • Location
    New Orleans, LA
  • Work
    Frontend Software Engineer
  • Joined

More fromAdam Nathaniel Davis

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp