5 ms·
API Security Checklist for developers
- drdaeman 9y ago> Always try to exchange for code not tokens (don't allow response_type=token). There is absolutely nothing wrong with the implicit flow if the application (including in-browser ones) is requesting the token for itself (and not for some server or any third party). In case of a standalone app that would be just an extra meaningless step. There is a slight difference in presence/absence of refresh token, though, but that would make implicit flow more secure (because, if standard-compliant, there won't be any refresh tokens at all), not less. In case of a browser, the token would end up in the browser's history, but given that a) if browser itself is compromised game is already over, and b) that it's not possible for other parties to access the history (besides some guesswork that doesn't work for tokens), paired with a fact that c) such tokens should be short-lived, it's not a big deal. > User own resource id should be avoided. Use /me/orders instead of /user/654321/orders This has absolutely nothing to do with security. TBH, I don't see any issue if /me/ would be a redirect or an alias for /user/654321/. That may make perfect sense if a conceptual purity is desirable ("for each object there is one and only one URL - the canonical one"), with its pros and cons. > Don't use auto increment id's use UUID instead. Similarly, that barely has anything to do with security. One just has to understand that sequential IDs are trivially enumerable (and an obvious consequence of this fact - that API consumers would be able to enumerate all the resources or, at the very least, estimate their cardinality). And as for the security - it should've probably said UUIDv4, because if one accidentally uses e.g. UUIDv1 their IDs would lose the unguessability.
- tptacek 9y agoThere's some OK stuff here, but the list on the whole isn't very coherent. If this is a guide specifically for "APIs" that are driven almost entirely from browser Javascript SPA's, it makes sense. Otherwise, a lot of these recommendations are a little weak; for instance, most of the HTTP option headers this list recommends won't be honored by typical HTTP clients. Further, the list succumbs to the cardinal sin of software security advice: "validate input so you don't have X, Y, and Z vulnerabilities". Simply describing X, Y, and Z vulnerabilities provides the same level of advice for developers (that is to say: not much). What developers really need is advice about how to structure their programs to foreclose on the possibility of having those bugs. For instance: rather than sprinkling authentication checks on every endpoint, have the handlers of all endpoints inherit from a base class that performs the check automatically. Stuff like that. Finally: don't use JWT. JWT terrifies me, and it terrifies all the crypto engineers I know. As a security standard, it is a series of own-goals foreseeable even 10 years ago based on the history of crypto standard vulnerabilities. Almost every application I've seen that uses JWT would be better off with simple bearer tokens. JWT might be the one case in all of practical computing where you might be better off rolling your own crypto token standard than adopting the existing standard.
- antoaravinth 9y ago>> Finally: don't use JWT. JWT terrifies me, and it terrifies all the crypto engineers I know. As a security standard, it is a series of own-goals foreseeable even 10 years ago based on the history of crypto standard vulnerabilities. Almost every application I've seen that uses JWT would be better off with simple bearer tokens. This is really surprising to me. I use Play! framework and the whole play framework community suggests to use JWT for authentications as Play! doesn't support sessions out of the box. Is it just JWT itself is bad or how developers use it is bad? Just a noob question.
- wolf550e 9y agoIt is a standard for crypto created by non-crypto people. It is bad, don't use it. Using it correctly is harder than rolling your own stupid simple bearer token, which is very rare for standards. Using stateful authentication is even simpler. Using django or something like that is even simpler.
- cperciva 9y agohave the handlers of all endpoints inherit from a base class that performs the check automatically I disagree. Much better to have a single endpoint which does nothing except validate opaque requests and passes them upstream. No good ever comes from having crypto code mixed up with non-crypto code.
- tptacek 9y agoI'm not talking about crypto --- really, it was an offhand comment about what real advice about structuring code for security looks like, compared to "validate inputs so you don't have XSS" --- and whatever you're proposing is probably something I'd agree with.
- andrewstuart2 9y agoDo you have any further info on why you so strongly recommend against JWT? My MO has been to know and understand the standard, what it provides (e.g. signed assertions a la SAML, albeit easier on the eyes) and what it does not (e.g. encrypted body without adding your own JWE), and to use it accordingly. This is probably the first I've heard from someone I know is more than just some random HN commenter that JWT is not recommended.
- tiffanyh 9y agoI don't bookmark many links but here's [1] a good one for all to keep on a similar topic. It's a SO article on security for web transactions. [1] https://stackoverflow.com/questions/549/the-definitive-guide-to-form-based-website-authentication https://stackoverflow.com/questions/549/the-definitive-guide...
- moxious 9y agoNo amount of checklisting and best practices substitutes for hiring someone smart to break your stuff and tell you how they did it. You can check all the boxes and still get pwned. You can learn and run automated tools for 6 months and end up knowing 1/3rd of what a great pentester knows. If you want to know you can resist an attack from an adversary, you need an adversary. If you want to know that you followed best practices so as to achieve CYA when something bad happens, that's a different story. But honestly the security picture is so depressing. Most people are saved only because they don't have an active or competent adversary. The defender must get 1,000 things right, the attacker only needs you to mess up one thing. And then, even when the defender gets everything right, a user inside the organization clicks a bad PDF and now your API is taking fully authenticated requests from an attacker. Good luck with that. Security, what a situation.
- lucb1e 9y ago> No amount of checklisting and best practices substitutes for hiring someone smart to break your stuff and tell you how they did it. Which is not to say that it doesn't help. As a pen tester, I'd much rather they tick all the boxes and save money because now I don't have to report all the low hanging fruit (which is fun the first two times you pwn an application but gets boring quickly -- I'd rather have something interesting to test).
- raesene9 9y agoIf the main input to the security of your application comes from having a penetration test, you're going to have a bad time. There's no mystery to what an app. security tester does really, and getting the basics of app. sec right early in the development lifecycle is probably the most important piece of having a good solid app. Sure get a tester in at the end to poke it and find edge cases and weird security bugs, but for a new app. getting someone in the early phases of development to provide security architecture advice is probably more important.
- philip1209 9y ago> User own resource id should be avoided. Use /me/orders instead of /user/654321/orders Can somebody explain this?
- ben_jones 9y agoI believe its because its a more explicit indication that the route MUST have access control logic etc baked in.
- lvh 9y agoIt also conveniently makes a CSRF vulnerability easier to exploit. And, as soon as there's more than one of something (e.g. say a family/corp account with an administrator that can do something for different users), it falls apart.
- tofflos 9y agoI think this is an interesting security consideration but I would prefer implicit identity for the following reasons: If the API is meant to be consumed by machines then it's unlikely that CSRF would be a threat. CSRF controls are more likely to be provided out of the box by a framework. Authorization controls are often tightly coupled to the business domain and are less likely to be usable out of the box. If you need to support a scenario where administrators perform tasks on behalf of other users, then I would suggest evaluating whether a sudo-like mechanism could be viable solution.
- s_m_t 9y agowhat happens if I type in /user/654322/orders instead of /user/654321/orders? Did I just access someone else's account?
- icebraining 9y agoYes, if you're a supervisor or parent account or something like that. Preventing flexibility at the URL level rather than performing proper authentication strikes me as a poor decision.
- Kiro 9y ago> Don't use Basic Auth Why not? If it's an API meant to be consumed by a server I don't see what the problem is.
- ams6110 9y agoWas going to ask the same question. Assuming https of course, what is the matter with basic auth?
- brians 9y agoIt's fragile: leaks the password when TLS is having a bad day, when the server's compromised—say, on more than 1% of days in the last five years. It's fragile to request smuggling attacks too, because the password is not entangled with the request, just next to it. We have lots of mechanisms that do better than both of those: client certs beat the first, and HMAC of the request and key headers with a secret beat both.
- Mandatum 9y agoGenerally you should try to tokenize your auth system. Passing "keys to the kingdom" directly to the API for each API call can cause a lot of grief in the event of a breach of one of your nodes. If you're using a tokenized and access-level controlled system with something like OAuth, the breach is bad - but it's temporary without having to run around trying to change creds over.
- daliwali 9y agoI think that the main issue is the client must send what is essentially the plaintext password on every request, meaning the client also must store the password. It might be short-lived, might not, but is a security risk to keep the password around on the client side for the duration of the session.
- vbsteven 9y agoI like to use Basic Auth for API's with clientid/secret pairs. So it's not the user password and individual credentials can be revoked while it's much simpler to implement than full OAuth If I'm not mistaken Twilio does this too for their API
- kpcyrd 9y agoI've filed a pull request to include a CSP technique I've started adding on some of my apis: https://github.com/shieldfy/API-Security-Checklist/pull/5 https://github.com/shieldfy/API-Security-Checklist/pull/5
- ikeboy 9y agoSo I'm developing a simple SAAS with little to no private info and where failure isn't critical. For initial release I build a page that uses html buttons and basic javascript to GET pages, passes a key as a parameter, and uses web.py on the backend. It seems like it would be a lot of work to implement the suggestions here. At what point does it make sense?
- EGreg 9y agoThere is a lot more you can do. For example you can sign session IDs or API tokens when you issue them. That way you can check them and refuse requests that present invalid tokens without doing any I/O.
- PetahNZ 9y agoJWT does that.
- bodhi 9y agoWhat are peoples thoughts on using TLS client certificates for authentication? Given we're talking about APIs, we avoid many of the UX problems, but it feels like taking on a different set of problems than just using a bearer token. It does provide baked in solutions for things like revocation and expiry though.
- fanf2 9y agoSeriously problematic for browsers - see Garrett Wollman's article linked below, and follow the link to his previous "defence" which has a good roundup of problems https://blog.bimajority.org/2016/05/02/an-update-on-the-https-client-certificate-issue/ https://blog.bimajority.org/2016/05/02/an-update-on-the-http...
- hdhzy 9y agoClient certificates don't work in http2. If you use due diligence and store them in secure hardware then they could be a lot more secure than bearer tokens (cannot be exported) but I guess most people would just store a PKCS#12 file on disk and that'd make them as secure as a bearer token. On the other hand some companies use them even for browser clients for passwordless authentication.
- Mandatum 9y agoIt's a pain in the arse for everyone involved. Adding another management layer to the stack isn't my idea of maintainability, and I'm inclined to agree with you on your point that it introduces a new set of problems. TLS client certs are nice if everyone knows what they're doing, but in a lot of orgs that just isn't the case.
- tofflos 9y agoI'm not that familiar with TLS client certificates so I'm not qualified to say, but if you consider other developers as your users, then the UX problem remains. Web developers in general are more familiar with other forms of authentication so unless you have a strong reason for picking TLS client certificates I would suggest picking something else. In other words: I would be more likely to try out an API if it was based on Basic Authentication. ;-)
- ViktorasM 9y agoNot a security topic, but POST is not necessarily "create" and PUT is not necessarily "update".
- Mandatum 9y agoAnd API's aren't necessarily REST. But this "checklist" is very clearly geared towards a "standard" set of REST APIs. So what's your point, that there are edge-cases in RESTful design?
- baybal2 9y agoThe guy forgets the main thing here: length, type and range checks! I'm finding issues like API servers hanging/crashing due to overly long or malformed headers all the time when I work on front-end projects. Programming in a language with automatic range and type checks does not mean that you can forego vigilance even with the most mundane overflow scenarios: lots of stuff is being handled outside of the "safe" realm or by outside libraries.