I am playing around with Mojolicious and see session cookies have strang look:
mojolicious=eyJleHBpcmVzIjoxNjY3MDUyNTEzLCJ1c2VyIjoic2ViYXN0aWFuIn1aWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlo---8ec2dbb1e9eeb295f610826487a011f3516106cb8a814530e73212a1e6a10d8f
Do you know what these "WlpaWlpaWlpaWlpaWlpaWlpa..." mean?
I see the signature is ok, data is ok, but WlpaWlpaWlpaWlpaWlpaWlpa...
In base64 this is ZZZZZZ... Where they have come from?
I have only this code to set up session:
$self->session(user => 'sebastian');
I am playing with it on the clean project.
Protocol: HTTP (no SSL)
Mojolicious 9.28.
This behaviour was added to Mojolicious in Pull Request #1791. The padding is intended to make it more difficult to brute-force the application secret that's used to sign secure cookies such as the session cookie. The choice of the padding character Z and the length of the padding seems arbitrarily chosen.
I think that this padding is almost entirely pointless as a security measure. As it is added in a deterministic manner it cannot make brute force attacks more difficult. As implemented, it's not even helpful to include the padding in the cookie, since the HMAC signature calculation can re-add the padding when necessary. In contrast, padding from a CSPRNG, without reusing padding patterns during the application's lifetime, would probably achieve the desired effect. Compare the concept of a salt for password hashes.
That you stumbled over this undocumented behaviour indicates a number of aspects:
Mojolicious is fairly fast moving, and doesn't always keep detailed documentation about all features.
Mojolicious tries to support reasonable security measures by default.
These security measures may or may not actually work.
If you want to secure your application secret against brute force attacks, it's important to create a strong cryptographically secure secret of suitable length (at the very least 128 bits of entropy). Ideally, your application would also regularly rotate secrets. Mojolicious supports having multiple active secrets, so that adding a new secret will not invalidate existing sessions.
Related
I'm trying to wrap my head around RESTful practices as I attempt to implement my own REST API, and that said, there's a fair bit that's confusing me.
One of the resources I've come across is the REST Cookbook for logging in, and while I understand how a nonce works for HMAC authentication, I'm hung up on one of the caveats listed towards the bottom of the page:
Using nonces can improve your security, but you MUST store and compare nonces server-side.
Now, the original dissertation on the REST architecture asserts the following about statelessness:
5.1.3 Stateless
We next add a constraint to the client-server interaction: communication must be stateless in nature, as in the client-stateless-server (CSS) style of Section 3.4.3 (Figure 5-3), such that each request from client to server must contain all of the information necessary to understand the request, and cannot take advantage of any stored context on the server. Session state is therefore kept entirely on the client.
This constraint has popularly disallowed old DHTML webapp methods of maintaining authentication (e.g. a cookie containing a "session ID" hash that identifies a user's subsequent requests). If a server needs to remember which nonce values have been used, isn't that technically maintaining state much like a session ID? If a legitimate client loses state, how can it generate a valid nonce when the server shouldn't be storing, let alone disclosing, stateful information?
I get a feeling I'm seeing something wrong, missing a piece of the puzzle, or misinterpreting something in this method, but I can't figure out what for the life of me...
I wonder if it is possible to have an easy authentication method that is restful, fast and provides a litte security.
SSL is not an option, because I can't rely on a valid SSL Certificate on the server of clients. Also HMAC is not really possible because the body of the request should be signed, when used properly, but in my case that body could be a large file. Further should the authentication be possible with JavaScript/AJAX.
I thought about something really simple. What's the problem with that one:
HEADER: X-Authentication: timestamp:username:sha256(timestamp:password)
The server knows the users password and could check the hash, the timestamp is used to only allow request that took place e.g. 10 seconds before. The replay window would be extremly small, and there are no sessions on the serverside.
If the hash is cracked the attacker knows the password and has unlimited access.
Alternative would be to use
HEADER: X-Authentication: timestamp:username:HMAC(password, 'timestamp+request-method+verb')
What's the way to go? I'm not a security pro, maybe storing the session on the server would be better (but not RESTful)?
I built a random hash algorithm that does what you need, it's called jAuthenticate.
You can download it from: https://github.com/thomasoeser/jAuthenticate
You can see how it works here: http://furiousgryphon.com/jauthenticatedemo.html
The reason it's a strong algorithm (in my opinion) is that I'm using a random number to influence the hash but I'm sending an obfuscated number with the hash.
Each hash is single use only.
Have a look, it's free open source (MIT).
HTTP authentication is extensible so you can invent your own mechanism (obviously at your own risk!). See https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-p7-auth-20 for details.
Don't bother inventing your own new X- header. Using the existing Authorization header with your scheme is a better option.
e.g.
Authorization: kruemel-auth timestamp:HMAC(password, 'timestamp+request-method+verb')
Ideally new schemes will be registered with IANA along with a specification. A registry is being setup to track auth schemes that have been developed. See http://tools.ietf.org/id/draft-ietf-httpbis-authscheme-registrations-03.html
I don't mind so much about pirating etcetera, but I want to ensure that the backend (Rails based) isn't open to automated services that could DOS it etc. Therefore I'd like to simply ensure that all access to the backend (which will be a few REST queries to GET and PUT data) will be via a valid iPhone application, and not some script running on a machine.
I want to avoid the use of accounts so that the user experience is seamless.
My first intention is to hash the UDID and a secret together, and provide that (and the UDID) over a HTTPS connection to the server. This will either allow an authenticated session to be created or return an error.
If eavesdropped, then an attacker could take the hash and replay it, leaving this scheme open to replay attacks. However shouldn't the HTTPS connection protect me against eavesdropping?
Thanks!
Like bpapa says, it can be spoofed, but then, like you say, you aren't worried about that so much as anybody coming along and just sending a thousand requests to your server in a row, and your server having to process each one.
Your idea of the hash is a good start. From there, you could also append the current timestamp to the pre-hashed value, and send that along as well. If the given timestamp is more than 1 day different from the server's current time, disallow access. This stops replay attacks for more than a day later anyway.
Another option would be to use a nonce. Anybody can request a nonce from your server, but then the device has to append that to the pre-hash data before sending the hash to the server. Generated nonces would have to be stored, or, could simply be the server's current timestamp. The device then has to append the server's timestamp instead of its own timestamp to the pre-hashed data, allowing for a much shorter period than a full day for a replay attack to occur.
Use SSL with client certificate. Have a private key in your client and issue a certificate for it, and your web server can require this client cert to be present in order for the sessions to proceed.
I can't give code details for Rails, but architecture-wise it's the most secure thing to do, even though might be a bit overkill. SSL with certificates is a standard industry solution and libraries exist for both the iPhone/client end and server end, so you don't have to invent anything or implement much, just get them to work nicely together.
You could also consider HMAC, like HMAC-SHA1, which is basically a standardization of the hashes stuff that other people here talk about. If you added nonces to it, you'd also be safe against replay attack. For an idea about how to implement HMAC-SHA1 with nonces, you could look at OAuth protocol (not the whole flow, but just how they tie nonce and other parameters together into an authenticated request).
There is no way to ensure it, since it can be spoofed.
If you really want to go this route (honestly, unless you're doing something really super mission critical here you are probably wasting your time), you could pass along the iPhone device token. Or maybe hash it and then pass it along. Of course, you have no way to validate it on the Server Side or anything, but if a bad guy really wants to take you down, here is roadblock #1 that he will have to deal with first.
Here is what I got for a webapp login scheme.
Present in database would be two salts and hmac(hmac(password, salt1), salt2).
When the user go on the login page, he gets salt1.
If he has javascript activated, instead of sending the plaintext password, it would send hmac(password, salt1).
If he does not have javascript, the plaintext password is sent.
So, on the serverside, when getting a login request, we'd first check what is sent (passwordSent) against hmac(passwordSent, salt2). If it does not work, we'd try hmac(hmac(passwordSent, salt1), salt2).
Someone getting access to the database should not be able to login with the password hashes and I don't think (but I may be wrong) that multiples hmacs diminish the hash resistance.
Do any good crypto expert see any obvious error I may have done ?
This looks a little like security through obscurity, what is the point of using javascript to hash the password on the client side if you still accept plain text password from the client?
You didn't mention if this was over https, if you aren't using https then you may as well have no passwords at all. If you aren't running https then any MITM can see the salt you are sending as well as the javascript used to hash the original password so you have nothing gained.
As for your concern about the possibility of hmac collisions between two salts, that is probably very unlikely (depending on your hash algorithm) and how secure you keep your salt values. Even with MD5 that has had some collision attacks discovered and has a set of rainbow tables, you will be ok if you keep your salt very very safe.
Please, everybody, please stop trying
to implement custom crypto systems
unless you have a background in
cryptography. You will screw it up.
--Aaronaught
Well said!
Sounds pretty far-fetched to me. If the objective of this is to prevent a "man-in-the-middle" attack by virtue of the plaintext password being sent over HTTP, then use SSL.
Hashing on the client side accomplishes nothing; unless the salt is actually a nonce/OTP, and not stored in the database, then a man in the middle can simply look at the hash sent by the original client and pass that along to the server. The server won't know the difference.
If this is supposed to make it harder to crack if someone gets hold of the database, it won't. If the hashing function is cheap, like MD5, this won't be any more difficult to crack than one salt and one hash (in fact it's actually weaker, since hashing is a lossy function). And if you use a strong hashing function like bcrypt, it's already good enough.
Please, everybody, please stop trying to implement custom crypto systems unless you have a background in cryptography. You will screw it up.
Probably obvious to you already, but you're effectively letting people log in with two different passwords in that setup.
If you want to give people the option of sending their passwords with encryption, I wouldn't tie that to anything strictly client-side, and just force HTTPS, as Harley already implied.
You might want to look at HTTP Digest authentication. That is a standardized protocol which avoid clear text password in any case.
I am developing an iPhone app together with web services. The iPhone app will use GET or POST to retrieve data from the web services such as http://www.myserver.com/api/top10songs.json to get data for top ten songs for example.
There is no user account and password for the iPhone app. What is the best practice to ensure that only my iPhone app have access to the web API http://www.myserver.com/api/top10songs.json? iPhone SDK's UIDevice uniqueueIdentifier is not sufficient as anyone can fake the device id as parameter making the API call using wget, curl or web browsers.
The web services API will not be published. The data of the web services is not secret and private, I just want to prevent abuse as there are also API to write some data to the server such as usage log.
What you can do is get a secret key that only you know, Include that in an md5 hashed signature, typically you can structure signatures as a s tring of your parameters a nd values and the secret appended at the end, then take the md5 hash of that...Do this both in your client and service side and match the signature string, only if the signatures match do you get granted access...Since t he secret is only present i n the signature it w ill be hard to reverse engineer and crack..
Here's an expansion on Daniel's suggestion.
Have some shared secret that the server and client know. Say some long random string.
Then, when the client connects, have the client generate another random string, append that to the end of the shared string, then calculate the MD5 hash.
Send both the randomly generated string and the hash as parameters in the request. The server knows the secret string, so it can generate a hash of its own and make sure it matches the one it received from the client.
It's not completely secure, as someone could decompile your app to determine the secret string, but it's probably the best you'll get without a lot of extra work.
Use some form of digital signatures in your request. While it's rather hard to make this completely tamper proof (as is anything with regard to security). It's not that hard to get it 'good enough' to prevent most abuse.
Of course this highly depends on the sensitivity of the data, if your data transactions involve million dollar transactions, you'll want it a lot more secure than some simple usage statistic logging (if it's hard enough to tamper and it will gain little to no gain to the attacker except piss you of, it's safe to assume people won't bother...)
I asked an Apple security engineer about this at WWDC and he said that there is no unassailable way to accomplish this. The best you can do is to make it not worth the effort involved.
I also asked him about possibly using push notifications as a means of doing this and he thought it was a very good idea. The basic idea is that the first access would trigger a push notification in your server that would be sent to the user's iPhone. Since your application is open, it would call into the application:didReceiveRemoteNotification: method and deliver a payload of your own choosing. If you make that payload a nonce, then your application can send the nonce on the next request and you've completed the circle.
You can store the UDID after that and discard any requests bearing unverified UDIDs. As far as brute-force guessing of necessary parameters, you should be implementing a rate-limiting algorithm no matter what.
A very cheap way to do this could be getting the iPhone software to send extra data with the query, such as a long password string so that someone can't access the feed.
Someone could reverse engineer what you have done or listen to data sent over the network to discover the password and if bandwidth limitations are the reason for doing this, then a simple password should be good enough.
Of course this method has it's problems and certificate based authentication will actually be secure, although it will be harder to code.
The most secure solution is probably a digital signature on the request. You can keep a secret key inside the iPhone app, and use it to sign the requests, which you can then verify on the server side. This avoids sending the key/password to the server, which would allow someone to capture it with a network sniffer.
A simple solution might be just to use HTTPS - keeping the contents of your messages secure despite the presence of potential eavesdroppers is the whole point of HTTPS. I'm not sure if you can do self-signed certificates with the standard NSURLConnection stuff, but if you have a server-side certificate, you're at least protected from eavesdropping. And it's a lot less code for you to write (actually, none).
I suppose if you use HTTPS as your only security, then you're potentially open to someone guessing the URL. If that's a concern, adding just about any kind of parameter validation to the web service will take care of that.
The problem with most if not all solutions here is that they are rather prone to breaking once you add proxies in the mix. If a proxy connects to your webservice, is that OK? After all, it is probably doing so on behalf of an iPhone somewhere - perhaps in China? And if it's OK for a proxy to impersonate an iPhone, then how do you determine which impersonations are OK?
Have some kind of key that changes every 5 minutes based on an algorithm which uses the current time (GMT). Always allow the last two keys in. This isn't perfect, of course, but it keeps the target moving, and you can combine it with other strategies and tactics.
I assume you just want to dissuade use of your service. Obviously you haven't set up your app to be secure.