I have a client that initiates calls through a proxy that requires authentication.
The proxy sends a challenge to the client and the client responds with the credentials.
Is it possible to respond to the challenge without the password in cleartext?
The point is that I don't think storing the password in cleartext on the client is a good idea, especially in this case, since anyone that knows the password would be able to make calls using the account of another person.
I know that storing the hash of a password is okay on the authenticating side (the proxy in this example), but I never saw such thing on client side.
Thanks, Mickael
Generally, it won't be in clear text because the challenge will state MD5, e.g. (from RFC 3261):
Proxy-Authenticate: Digest realm="atlanta.com",
domain="sip:ss1.carrier.com", qop="auth",
nonce="f84f1cec41e6cbe5aea9c8e88d359",
opaque="", stale=FALSE, algorithm=MD5
If it doesn't say MD5, that's an issue with your proxy.
If you know the realm, you can store the first stage of the response with password as an MD5 hash, along with the username (use of nonce comes later). Otherwise you'd have to use a reversible form of encryption locally for it.
Related
I've been reading and trying to comprehend the differences in browser side security. From what I gather, SSL is used to keep people from sniffing the traffic you send to the server. This allows you to send a password to a server in clear text...right? As long as you are in an SSL encrypted session you don't have to worry about hashing the password first or anything weird, just send it straight to the server along with the username. After the user authenticates you send them back a JWT and then all future requests to the server should include this JWT assuming they are trying to access a secured area. This allows the server to not even have to check the password, all the server does is verify the signature and that's all the server cares about. As long as the signature is verified you give the client whatever info they are requesting. Have I missed something?
You are correct. "This allows the server not to even have to check the password." Why would you have to check a password on each request?
A JWT is a means of verifying authentication. It is generated upon a successful authentication request and hence forth passed with each request to let the server know this user is authenticated.
It can be used to store arbitrary values such as user_id or api_key but they are not very secure so don't store any valuable information here.
Be wary though, if a plain JWT is intercepted by a third party, it can assume this user's session and possible data.
SSL is a lower level form of security, encrypting every request from and to the server to prevent interception and retains integrity.
SSL is achieved by (purchasing) an SSL certificate and installing it on your server. Basically an SSL certificate is a small data file that binds a cryptographic key to an 'organisation'. Once installed succesfully, HTTPS requests (on port 443 by default) are possible.
I am asking myself. What is the best way to send personal information from your iOS device to the server.
At this moment I encrypt the password in the app ( sha1 salt password pepper ) then I send post data using from iOS to the server.
What is the best way to protect the user and secure for any MITM attacks. Is my way secure enough?
UPDATE:
I added the SSL certificate. To make sure the user only has to login once I store a key generated when the user registered. I fetch them when the user logins for the first time. In oombination with the username and user id. Is this a good way? Only jailbroken users can read it and have risk.
Hashing the password on the client side will help prevent the password itself from being detected in eavesdropping, but it really doesn't provide any security on its own, as the credential then becomes the hashed version of the password, not the original password itself. An eavesdropper could just grab the hashed version, and then send the hash themselves.
By far the easiest solution is to simply use SSL/TLS. Since you mentioned 'post', that means you're probably using HTTP. Instead, you could just connect via HTTPS and post the data, exactly the same as you're doing already. Long as the certificate is checked for validity (I believe the iOS framework already does such by default), then the connection should be largely secured.
That should be good enough for most situations. There are some more complicated and involved techniques you can use to harden further, but SSL/TLS does a massive amount on its own.
I want to be able to set up a web application to automatically (i.e. on a cron run) send a POST request to a remote website. The remote website requires a username/password combination to be sent as part of the POST data. I want the web application to be able to make the POST requests of the remote website without requiring the user to provide the password to be sent with the POST data, each time the request is made.
It seems to me that the only way to do this is to store passwords directly in the database, so that the cron run can execute a POST request that includes the password as part of its POST data. Without storing the password in some form in the database, it seems it would be impossible to provide it in the POST data, unless the user provides it each time the request is made.
Question 1: Am I mistaken and somehow overlooking something logical?
Question 2: Assuming I have to store the passwords in the database, what is the safest procedure for doing so? (MD5 and similar one-way encryption clearly will not work because I have to send an unencrypted password in the POST request.)
Thank you for your help!
a. if you don't know the password... you can't authenticate, that's the idea of a password !
b. if you need to know the password - you need to save it in a decryptable way - hence - less secured.
c. if you own the site, you can use a cookie with a very long timeout value, but - you still need to authenticate at least once.
d. unless you're guarding money / rocket science, you need to encrypt the password and store it in the DB and decrypt it every time before use, at least you are guarded from DB theft.
e. make sure you're authenticating over secure channel (as https) so the password will no be sent as clear text.
One good solution is probably to use SSL (i.e. HTTPS). You can create a certificate authority on the server side, then have this certificate authority sign a client certificate that you generate. Make sure the HTTP server is configured to trust the newly created certificate authority.
Once this is done, you should install the certificate on the client side. The client must present the certificate when talking to the HTTP server. You have to configure the HTTP server to require a trusted certificate when POSTing to your secure URLs.
Awesome example of how to do this with Apache HTTPD is posted right here!
The document I linked doesn't describe how to set up the certificate authority and create self-signed certificates, but there are tons of examples out there, for example here.
This is a good solution because:
no passwords are stored in the clear
if the private key of the client's certificate is stolen or compromised, you can revoke it on the server side
The key here is that the client is providing its credentials to the server, which is the opposite of what is usually done in a browser context. You can also have the client trust your newly created certificate authority so that it knows it's talking to the right server and not a man in the middle.
Given that you have to send the password in clear-text and do it repeatedly without user-interaction you'll need to store and retrieve the same from a data-store (file/database/memory).
What you really need to consider is the last-line-of-security of the password store.
Whether you encrypt it or not doesn't matter. The person/program with access to the data or the cipher key will be able to read that password.
Sort this issue out, document it - (this becomes your security policy for the app) and then implement it.
Security is only a level of difficulty you implement to lessen a risk.
Fortunately, Tumblr now implements OAuth, which solves this problem.
I would like to use the HTTPS to secure the communication between my client and the server. The first encrypted communication will be used to authenticate the user - i.e. checking his/her user name and password.
After the user credentials will be successfully checked by server I would like to start getting some data in subsequent requests. BUT how the server will determine that the subsequent request is send by the user, whose credentials were already checked?
Since the TCP connection might be closed between login and subsequent HTTPS requests, (I think) this means that the SSL context must be released by the server, so with the new GET request, the new TCP connection must be established and the new SSL(TLS) handshake must be done (i.e. new shared password for the encryption must be exchanged by both sides, etc.)
For this I think server needs to send back to the client in 200 OK response for the initial authentication request some randomly generated nonce (which is valid for a certain time), which I will include in every subsequent request, so the server will be able to detect, based on this randomly generated nonce, which user name is behind the request and check that this user is already logged in. Is my understanding correct?
Thanks a lot for the reply
BR
STeN
The simplest method is to require all communication to go via HTTPS (so the data is confidential; nobody other than the client and the server can see it) and to use simple username and password on every request inside that secure connection. This is dead simple to do in practice (the username and password actually go over the connection as an HTTP header, which is OK here because we're using HTTPS) and the server can check every time that the user is allowed. You don't need to worry about the SSL handshakes; that's the SSL/HTTPS layer's responsibility (and that's why HTTPS/SSL is nice).
Alternatively, the login can be done with any method and generate some kind of magic number (e.g., a UUID or a cryptographic hash of a random number and the user's name) that is stored in a session cookie. Subsequent requests can just check that the magic number is one that it recognizes from session start (and that not too much time has passed since it was issued); logout just becomes forgetting the magic number on the server side (and asking the client to forget too). It's a bit more work to implement this, but still isn't hard and there are libraries for server-side to handle the donkey work.
The first option is particularly good for where you're writing something to be used by other programs, as it is really easy to implement. The second option is better where the client is a web browser as it gives users more control over when their browser is authorized (program APIs don't tend to need that sort of thing). Whenever the client is going to be a browser, you need to take care to armor against other types of attack too (e.g., various types of request forgery) but that's pretty much independent of everything else.
Inventing custom authentication mechanism in your case is very risky - it's easy to make a mistake that will let lots of wrong doing. So the right approach, as for me, would be to use HTTPS and pass user credentials with each request.
I have a website that requires a user to authenticate themselves with a user name and password. I would like to use SSL, but I don't have an SSL certificate. But I do something else that I think is okay.
My site is primarily AJAX based and requires JavaScript, otherwise nothing will work.
When the user tries to login, I query the database using AJAX to look for a salt for that user name, if none is found a random salt is returned (to keep people from knowing if there is a user with that user name or not). Then, using a MD5 function for JavaScript, I hash and salt the password 4K times (like Linux does when it uses MD5 for it's password hashing) client side, then I pass that hash to the server in plain text. This hash will then be hashed a few more times and presented to be checked with what's in the database.
Is this secure? If not, how can I secure it without forking over the cash for an SSL cert for a mostly internal website?
No. It's not secure. A man-in-the-middle can snoop the hashed value and present it to you later, falsely authenticating himself.
To authenticate someone, you have to prove that they know a secret. Anything passed over an unencrypted channel is not a secret.
Use SSL. You can get certificates for free that are accepted by Firefox, and you can give IE users instructions for adding a new CA to their trusted roots. Certificates that are accepted by all browsers out of the box are cheap, I think $30 per year.
The best options are:
Use a certificate signed by StartCom (free). Supported natively by recent versions of Firefox and Safari. Users with IE can add the CA to their list of trusted roots.
Use a self-signed certificate and distribute it to your users to add in their browsers.
As others mention, your solution is not secure. It offers no improvement over sending the password in cleartext to the server. The major reasons:
Anything sent from the client in clear text and directly used to authenticate will be susceptible to man-in-the-middle and eavesdropping attacks. In your suggested solution, if you know the hashed password, you can log in. Sending the password as a hash makes no difference.
After authenticating, the data is still sent in plaintext, so it is easy to sniff.
MD5 is full of holes
You could make your own SSL certificate for free, it wouldn't be trusted by general users but you can trust it.
By using JavaScript and a transport layer that is not encrypt, you open the possibility of someone grabbing that hash you send to your server, not to mention give an exact blueprint of how you are hashing the password/username.
It really depends on how important security is for that application. If it is very important drop the Ajax, and pick up a SSL certificate and use the HTTPS layer.
Your solution is open to replay attacks. Try Digest Authentication (RFC 2617) directly between the browser and web server.