crypto functions on PicoLisp
I’m not sure what the relevance is?
It sounds to me like “the desired out come [sic] of a very short URL” needs to be examined: What is so wrong about a long URL? Google use them, and Apple use them. As a content-identifier, a URL should (conceptually) be a hash of its content and accessor, and so very compressed hashes for mostly public information (like on Twtitter) are absolutely acceptable. URLs can get quite large these days, and long URLs may scare people giving them pause before sending them to others. For all these reasons and more, I’d really like to see this point justified further.
However even given that, there’s other strange advice in here as well, like “Do not use obfuscated URLs as a backdoor.” which is silly. A long, hard-to-guess URL is absolutely more secure than a short, easy-to-remember (and frequently-typed) password.
And the proposed protection against timing attacks is troubling in the face of a much simpler solution: Find the max lookup time, and sleep up to it. Add some random fuzz to protect against jitter.
A long, hard-to-guess URL is absolutely more secure than a short, easy-to-remember (and frequently-typed) password.
This is false. The problem is that you’re only considering the raw entropy, but not all of the other technical implications - because a URL is not considered sensitive information, it may be retained by proxies, in access logs, browser history, desktop session data, and so on.
It may be sent over a message bus like DBus, or through custom IPC protocols to other applications on the system. Browser extensions may even send this URL elsewhere for purposes like malware scans, because they don’t expect the URL to essentially contain a password. And so on - the possibilities are endless.
This would be a good moment to invoke this article. Deviating from the assumptions under which something is designed, is generally a bad idea because of pitfalls like this.
a URL is not considered sensitive information,
And you a password is? That’s so cute.
Should I address you? Or the person working the sock puppet?
It may be sent over a message bus like DBus, or through custom IPC protocols to other applications on the system.
That’s no different than any keychain or password manager.
Browser extensions may even send this URL elsewhere for purposes like malware scans
No, they don’t. But it’s not like they’re smart about security, it’s that they’re smart about the privacy backlash. Software that works that way is illegal in Germany and Switzerland, and about to be made illegal (GDPR) in the rest of Europe.
If you know of a browser extension that does this, you should have it reported.
And so on - the possibilities are endless.
No. They’re really not.
Meanwhile, the very real risk of someone having to remember “yet another password” writes it down with all their other passwords – know an attacker knows by searching for that password which file contains all of the other goodies. Yum.
Or someone decides to change the password. Or reuse it. Or copy/paste it and accidentally paste it into the wrong place.
We have too many passwords and I get it: we think we want to “make things secure” instead of authenticating and confirming authorisation to resources. But that’s just caused by too many cargo-cult programmers who find one blog post they agree with and forget how to think for themselves.
It sounds to me like “the desired out come [sic] of a very short URL” needs to be examined: What is so wrong about a long URL?
SMS. You only get 160 characters, and you want as short of a URL as possible. This is the sort of constraint I’ve had to work around for clients in the past.
That depends on whether or not you allow weak passwords.
Do not use sleep to mitigate timing attacks. It might seem tempting, but it doesn’t work. You either use too short of a delay (and your random fuzz becomes useless with enough samples) or too long of a delay (and expose your server to easier DoS attacks). A Goldilocks strategy won’t work either: the goalposts will move over time, and you’ll need to figure out where/how to calibrate the values for the delays. You’re better off solving the real problem.
160 characters is plenty for authenticated secret-key encryption.
Do not use sleep to mitigate timing attacks.
Yes, do. And in fact read the article you just linked to where it suggests exactly my mitigation suggestion: “Make the operation take a minimum time (clamping)”. It suggests a weaknesses to local users and some handwaving about security by obscurity, but no real actual problems with it.
[too long of a delay] and expose your server to easier DoS attacks
Saying “easier” is intellectually dishonest. If someone can DoS your cpu idle, then they can certainly DoS you when your cpu is warm. Process and network utilisation remains almost exactly the same, and in all practical ways of measuring it, you’re introducing no new attacks.
The weak password is the one that someone has to write down in an accessible place, but by all means: put your money where your mouth is and find my secret url.
Just stop using passwords.
Yes, but not “a custom message + the URL”, which is what my past clients wanted.
The DoS comes in when you have idle connections being used (and using memory) for needlessly long periods of time, which allows an attacker to send more requests than the server can fulfill which blocks legitimate traffic.
Having a long sleep on the server side makes that easier.
I wouldn’t be so quick to call something intellectually dishonest, because all that does is hamper understanding and make future interactions needlessly adversarial.
Two messages are cheap.
Anyway, I try to avoid making things harder for myself since I’m trying to save my customers their money.
for needlessly long periods of time, … I wouldn’t be so quick to call something intellectually dishonest, because all that does is hamper understanding and make future interactions needlessly adversarial.
You keep saying “long”. Be specific. Give timings: This is usec and nsec territory. An attacker that can overload you taking T+100 usec but not T usec doesn’t exist.
If you generate 9 raw bytes from a cryptographically secure pseudorandom number generator, then base64 the result, you will end up with a 12 character identifier (72 bits of possible values).
If you generate 9 raw bytes and base64 the result, the number of possible values is not increased by running base64 (although the prose could be read to implies it would).
Furthermore, this record is completely randomly generated and has nothing to do with the rest of the data stored in your database. There is no pattern to be found. (The closest relevant buzz-word here is a “zero knowledge”.)
The closest relevant buzz-word should be “Message Authorization Code”, because that’s how you would do this securely. It would also make the timing attack a non-issue.
Zero knowledge encryption has nothing to do with this (and I’ll resist the urge to make the oh-so-tempting pun about the author because it’s entirely unfair).
The 9 bytes offer 2^72 possibilities. The base64 transformation is just for safe storage.
Did you mean “Message Authentication Code”? Or am I missing one of the linguistic atrocities from bizdev?
Zero knowledge isn’t encryption, it’s authentication. :)
I assume you mean “so it’s valid in a URL param” (which IMO is worth mentioning given the intended audience)
I did mean “Message Authentication Code”, yes. There’s no reason to allow clients to tamper with these.
Prepared statements resist SQL injection, but are not immune to injection, and I always break out in hives when people describe their complete SQL injection security strategy as “we use prepared statements”.
There are roughly two kinds of SQL injection that are possible when prepared statements are used in a PHP application.
Neither are relevant to our codebase.
If there’s a third that I’m not aware of, I promise you most PHP developers aren’t either, and should be made aware.
This depends on your database, doesn’t it? There are versions of MySQL where you can’t even parameterize a LIMIT. There are databases that can’t parameterize column names for search queries with selectable columns. It can be hard to build IN queries. There are lots of little exceptions.
It’s the confidence that “parameterized queries means no SQL injection” that scares me. We still find SQLI in applications despite the fact that most teams now pretty reliably parameterize queries.
Allowing end users to supply column names implicitly invites injection, and a strict whitelist is the sane solution here. The linked post in that section explains the caveats in detail.
It sounds to me like “we aren’t actually using prepared statements for this query” is the culprit, however.
[Comment removed by author]
In PHP’s PDO case, there’s only a corner case with emulated prepared statements that I’m aware of.
This is a fine post, but I’m surprised how much more attention it got than the totally ignored post about the invalid curve attack (which I would guess inspired this post). “We want in depth technical articles. No, no, not that technical. Too deep, too deep, pull up.”
You mean this one? If so, I bet the word “adobe” made a lot of people not click it.
yeah, which is a shame.
Yeah, not only was that that was far more innovative research than anything I’ve blogged about to date, it was one of the inspirations for this post.
As an attempt to mitigate this, I’m going to update my post to emphasize that attack and get more eyes on theirs. It’s good work.
Reprising and reformatting something I wrote on that other site about this:
The problem with JWT/JOSE is that it’s too complicated for what it does. It’s a meta-standard capturing basically all of cryptography which wasn’t written by or with cryptographers. Crypto vulnerabilities usually occur in the joinery of a protocol. JWT was written to maximize the amount of joinery.
Negotiation: Good modern crypto constructions don’t do complicated negotiation or algorithm selection. Look at Trevor Perrin’s Noise protocol, which is the transport for Signal. Noise is instantiated statically with specific algorithms. If you’re talking to a Chapoly Noise implementation, you cannot with a header convince it to switch to AES-GCM, let alone “alg:none”. The ability to negotiate different ciphers dynamically is an own-goal. The ability to negotiate to no crypto, or (almost worse) to inferior crypto, is disqualifying.
Defaults: A good security protocol has good defaults. But JWT doesn’t even get non-replayability right; it’s implicit, and there’s more than one way to do it.
Inband Signaling: Application data is mixed with metadata (any attribute not in the JOSE header is in the same namespace as the application’s data). Anything that can possibly go wrong, JWT wants to make sure will go wrong.
Complexity: It’s 2017 and they still managed to drag all of X.509 into the thing, and they indirect through URLs. Some day some serverside library will implement JWK URL indirection, and we’ll have managed to reconstitute an old inexplicably bad XML attack.
Needless Public Key: For that matter, something crypto people understand that I don’t think the JWT people do: public key crypto isn’t better than symmetric key crypto. It’s certainly not a good default: if you don’t absolutely need public key constructions, you shouldn’t use them. They’re multiplicatively more complex and dangerous than symmetric key constructions. But just in this thread someone pointed out a library — auth0’s — that apparently defaults to public key JWT. That’s because JWT practically begs you to find an excuse to use public key crypto.
These words occur in a JWT tutorial (I think, but am not sure, it’s auth0’s):
“For this reason encrypted JWTs are sometimes nested: an encrypted JWT serves as the container for a signed JWT. This way you get the benefits of both.”
There are implementations that default to compressing plaintext before encrypting.
There’s a reason crypto people table flip instead of writing detailed critiques of this protocol. It’s a bad protocol. You look at this and think, for what? To avoid the effort of encrypting a JSON blob with libsodium and base64ing the output? Burn it with fire.
I have a related but somewhat OT question. In one of the articles linked to by the article , they say this:
32 bytes of entropy from /dev/urandom hashed with sha256 is sufficient for generating session identifiers.
What purpose does the hash serve here besides transforming the original random number into a different random number? Surely the only reason to use hashing in session ID generation is if there’s no good RNG available in which case one might do something like hash(IP, username, user_agent, server_secret) to generate a unique token? (And in the presence of server-side session storage there’d be no point to including the secret in the hash because its presence in the session table would prove its validity.)
hash(IP, username, user_agent, server_secret)
Yeah, if urandom is actually good, then hashing it serves no real purpose. (In fact if you want to get mathematical, it can only decrease the randomness, but luckily by an absolutely negligible amount). Certain kinds of less-than-great randomness can be improved by hashing (as a form of whitening), but no good urandom deserves to be treated that way.
The reason for that is PHP is weird. PHP hashes session entropy with MD5 by default. Setting it to SHA256 just minimizes the entropy reduction by this step. There is no “don’t hash, just use urandom” configuration directive possible (unless you’re rolling your own session management code, in which case, please just use random_bytes()).
This is no longer the case in PHP 7.1.0, but that blog post is nearly two years old.
Thanks for that very thorough dissection of JWT. Are there web app frameworks/stacks that do have helpfully secure and well-engineered defaults that you’d recommend?
The post itself offers a suggestion (at the bottom): use libsodium.
The author refers to Fernet as a JWT alternative. https://github.com/fernet/spec/blob/master/Spec.md
However, Fernet is not nearly as comprehensive as JOSE and does not appear to be a suitable alternative.
Hah, it seems the article changed a few times, and not just the title…
And comments on https://datatracker.ietf.org/wg/cose/documents/ ?