7 ms·
The Stack Exchange API used to revoke API keys sent over HTTP (and return an error message), which is my favorite way to handle this.
by zepton 2y ago
The Stack Exchange API used to revoke API keys sent over HTTP (and return an error message), which is my favorite way to handle this.
- znpy 2y agoI've been thinking for about 5 minutes about this comment and what to write but i've come to the conclusion that this is really not the best thing to do, but the correct thing to do. It's not different levels of good or bad... everything else is wrong.
- comex 2y agoOne of the approaches mentioned in the article is to just not listen on port 80. Supposedly that’s equally good because the connection should get aborted before the client has the chance to actually send any API keys. But is that actually true? With TCP Fast Open, a client can send initial TCP data before actually learning whether the port is open. It needs a cookie previously received from the server to do so, but the cookie is not port-specific, so – assuming the server supports Fast Open – the client could have obtained the cookie from a prior connection over HTTPS or any other valid port. That’s the impression I get from reading the RFC, anyway. The RFC does mention that clients should distinguish between different server ports when caching refusals by the server to support Fast Open, but by that point it’s too late; the data may have already been leaked.
- pixl97 2y agoIf someone is in your path they can just fake listen to 80 and intercept, then forward your call to 443. Probably best to listen on 80 and trash the token right then as the majority of the time there won't be a MITM and breaking the application will force the developer to change to https
- jedberg 2y ago> If someone is in your path they can just fake listen to 80 and intercept, then forward your call to 443. They can do that whether or not you are listening on port 80 though.
- rocqua 2y agoThat was OPs point. Not listening on port 80 won't help against an active MitM.
- zeroimpl 2y agoBut listening on port 80 and revoking the key also won’t help either as the active MitM would have been smart enough to internally proxy to port 443 or return some other fake response. The real point is to break the application during development before the first MitM. Either approach does that equally well.
- comex 2y agoBut not listening on port 80 will also usually break the application. Though I suppose the same API key may be used by multiple applications, or multiple copies of an application configured differently. edit: and even if there's only one application, yet for whatever reason it doesn't get taken down despite being broken, revoking the key now still prevents against a MITM later.
- andrewaylett 2y agoIf you're serving web traffic and API traffic on the same domain, which many services are, then not listening on port 80 may not be possible. Even if you do use a different domain, if you're behind a CDN then you probably can't avoid an open port 80. I do keep port 80 closed for those of my services I can do so for, but I don't have anything else that needs port 80 to be open on those IPs. I think Stack Exchange's solution is probably the right one in that case -- and hopefully anyone who hits it will do so with dev keys rather than in production.
- xnorswap 2y agoI always thought it was bad practice to use the same domain for API and non-API traffic. In the browser there'll be a ton of wasted context (cookies) attached to the API request that isn't needed. So it's better to have "api.example.com" and "www.example.com" kept separate, rather than using "www.example.com/api/", where API requests will have inflated headers.
- wichert 2y agoWhat matters is that there is nothing listening on port 80 on the same IP address. That may be hard to control if you are using an environment with shared ingress.
- andrewaylett 2y agoThat very much depends on what's hitting your API and why. If it's browser clients, you might want to worry about headers and cookies -- but with http/2 and http/3 using hpack and qpack you should be able to avoid sending all the data each time. If the clients aren't browsers then the question is moot but there are other reasons to consider. In any case, I'd recommend same-origin requests for browser access to APIs and a separate domain for non-browser access, purely for separation of concerns. That lets you tailor the access rules for your endpoints according to the type of caller you're expecting.
- gbalduzzi 2y agoThe point in the article is that APIs are used by developers, not end users. Returning an error (and/or blocking the port entirely) allows the developer to understand he is using the wrong protocol and fix it. In this scenario, the end user never actually performs an http request, because the protocol was fixed by the service developer.
- cryptonector 2y agoWell, nothing you do on the server side will protect a client willing to use http: when an MITM is present: the client can still connect to the MITIM, give away its credentials, and your server won't know. Still, I agree that this is a very good way to teach your users to not start with http:! And that this is what one should do.
- op00to 2y agoI love this.
- paulddraper 2y agoTechnically correct.
- freehorse 2y agoBest kind of correct.
- Eduard 2y agothat's more secure, but still not bulletproof: A MITM (e.g. a router along a multi-hop route between the victim client and StackExchange) could silently drop the unsafe HTTP requests and maliciously repackage it as an HTTPS request, thereby circumventing the revocation. Also: even if an insecure HTTP request isn't dropped / makes it through to StackExchange's endpoint eventually (and thereby triggering the API key revocation), a MITM with a shorter trip time to SE's servers could race for wrecking havoc until the revocation happens. Nevertheless, SE's revocation tactic contributes positively to a defense in depth strategy.
- Titan2189 2y agoI'd argue your reasoning is incorrect. By the time your service is developed you would have already changed it to https, as during development every time you tried your API keys sent via http got disabled. So an in-the-wild MITM would never get to see your http request
- throw__away7391 2y agoThat's a very good point, I agree. You're always going to run a service at least once.
- fl0ki 2y agoI agree from a developer point of view, but the people configuring and deploying the application aren't always the same people developing it. As a developer I like to make many options available for debugging in various situations, including disabling TLS. This isn't controversial, every Go and Rust library I've ever seen defaults to no TLS, preferring to make it easy rather than required, so reflecting those defaults in the service's configuration is natural and intuitive. I make sure my example configurations are as close to what will be needed in production as possible, including not just TLS but at least one "mutual TLS" validation. I even sync these back from production if it turns out something had to be changed, so the examples in the repository and built artifact are in line with production. Yet I routinely find at least some of these disabled in at least some production deployments, presumably because the operator saw a shortcut and took it. Let's rework Murphy's original law: if there are multiple ways to deploy something and one of those will be a security disaster, someone will do it that way.
- makeitdouble 2y agoWouldn't this open the door to revoking random API keys sent maliciously ?
- Townley 2y agoIf a malicious party has access to the API key, it should be revoked regardless
- bruce511 2y agoOf course. But I think the poster above was referring to just posting random keys to the server. In other words I don't have your key, or any key, but I have "all of them". The correct response to this though is that "there are lots of keys, and valid keys are sparse." In other words the jumper of valid keys that could be invalidated in this way is massively smaller than the list of invalid keys. Think trillions of trillions to 1.
- numpad0 2y agoIt's wrong that clients are authenticated with just the random generated username. But it's also what everyone do.
- ncallaway 2y agoWhich, like, if posting random keys has any realistic plausibility of collision, malicious revoking of keys is the least of your concerns. People could just hit important data fetch endpoints with random keys, until they find one that’s good, and then have a compromised account.
- makeitdouble 2y agoGood point. Presented that way I am seeing more positives to their policies, in particular if a vulnerability was unearthed by the invalidation quirk it's a way better way to find out than any other way.
- 2y ago
- deleted 2y ago[deleted]
- ChrisTorng 2y agoThe client-side library should disable HTTP by default to ensure that raw data never leaves the local environment, thereby avoiding any leakage.
- gpvos 2y agoIt should, but additional server-side mitigations are good for defense in depth. There may be people using a different client-side library, maybe because they use a different programming language.
- ljm 2y agoWhat about things like unencrypted websockets? Or raw TCP/UDP connections?
- rattray 2y ago(I develop client SDKS) It could make sense for first-party SDKs for an API to block http access to the first-party API domain, but that should be unnecessary – typically users would use the default base URL hardcoded in the client library, and only replace it if they're going through some other proxy. When they _do_ go through some other proxy, it's commonly in an internal network of some kind, where http is appropriate and should not be blocked.
- mid-kid 2y agoThis sounds like a great way to cause Denial-of-Service attacks.
- mrmanner 2y agoYou need to actually send them the API key, so not really.
- afiori 2y agoTo do that you need to guess or steal the API keys.
- Thiez 2y agoDenial of service by blocking API keys is really your happy case when someone malevolent has your API keys.
- dirigeant 2y agoIf someone steals API keys and invalidate them by sending HTTP requests instead of using them, you can only thank them.
- beeboobaa3 2y agoUsed to? Did they stop? Did they give a reason why?
- vitiral 2y agoCareful, someone might use that as an API! https://xkcd.com/1172/ https://xkcd.com/1172/
- ajsnigrutin 2y agoI mean... it is a lot easier to do, than to program a procedure to revoke an api key.
- vitiral 2y agoExactly. Easier but actually terrible for security since a MitM can intercept and use the key (and never actually revoke it)