My problem:
I need, basic authentication over HTTP (client can't afford HTTPS). So I don't worry if communication is not encrypted. I just want to prevent some user from sniffing and using the password (site only used to upload photos and those photos are public.).
Toolbox of what I have at my disposal:
Javascript
PHP
Sha512.js
The SHA algorithm is the same in both PHP and JS:
The proof:(?)
<?php
$password= "password";
echo hash('sha512',$password);
//outputs: b109f3bbbc244eb82441917ed06d618b9008dd09b3befd1b5e07394c706a8bb980b1d7785e5976ec049b46df5f1326af5a2ea6d103fd07c95385ffab0cacbc86
?>
While in JS (all my files are encoded in utf8)
document.getElementById("hiddenField").value
= JS.sha512("password");
//outputs b109f3bbbc244eb82441917ed06d618b9008dd09b3befd1b5e07394c706a8bb980b1d7785e5976ec049b46df5f1326af5a2ea6d103fd07c95385ffab0cacbc86
However I cannot simply send the same hash on every connection, else anyone can sniff it and send it to connect.
So my idea was to use password_hash() function as salt generator.
The salt is public, the hash of (password+salt) is public, but password is private and never sent as clear text: the server will compute (hopefully) the same hash as the one in JS from the client and verify that both hashes match.
The problem is that regardless of what I do, I'm unable to get the same output when I hash the output of that function(password_hash). It seems to be something related to encoding.
I want to use password_hash() because it already keeps into account a lot of security stuff:
Javascript:
document.getElementById("hiddenField").value
= JS.sha512("password" + document.getElementById("publicToken").value);
I put the "password_hash" content into another hidden form field that I call "publicToken". Regardless of what I do I'm unable to get the hash match:
<?php
$salt = ut8_encode(password_hash("another_password")); //doesn't work either
In the end, what do I have to do to get a correctly encoded salt?
<?php
$salt = //... one time usage salt.. but what to put here?
I realize your client cannot afford a standard HTTPS certificate, but honestly, even a free SSL certificate is likely to be far better than what ever you can concoct here.
In this situation, all you are doing is making the browser-side hash the user's password, and all one has to do to get in is send a matching hash. If you decide to do this, you definitely need to hash the password again on the server side, but it is still no replacement for SSL.
More on it here: https://crackstation.net/hashing-security.htm
Without public key cryptography and a way to verify the identity of the server (in other words, HTTPS), the unfortunate truth is that there is simply no way to secure the communication to an acceptable level. I would not even advise trying, for fear of getting a false sense of security. No matter how much you hash and salt, it will only be minimally better than sending the plaintext password and trivial to break.
If your client cannot afford a certificate, I would recommend taking a look at StartSSL. Their basic level certificates are completely free; I believe they're valid for 1 year with unlimited renewal.
Another project worth looking at is Let's Encrypt. They've trying to make the process of getting a certificate much simpler and more accessible, so they've developed a way to completely automate the process of issuing (free) certificates. The service is not live yet, unfortunately; they plan to start issuing certificates this summer. Quoting their page:
Anyone who has gone through the trouble of setting up a secure website
knows what a hassle getting a certificate can be. Let’s Encrypt
automates away all this pain and lets site operators turn on HTTPS
with a single click or shell command.
When Let’s Encrypt launches in mid-2015, enabling HTTPS for your site
will be as easy as installing a small piece of certificate management
software on the server:
$ sudo apt-get install lets-encrypt
$ lets-encrypt example.com
That’s all there is to it! https://example.com is immediately live.
The Let’s Encrypt management software will:
Automatically prove to the Let’s Encrypt CA that you control the website
Obtain a browser-trusted certificate and set it up on your web server
Keep track of when your certificate is going to expire, and automatically renew it
Help you revoke the certificate if that ever becomes necessary.
No validation emails, no complicated configuration editing, no expired
certificates breaking your website. And of course, because Let’s
Encrypt provides certificates for free, no need to arrange payment.
Related
I was reading some topics about security and how hackers can look at the request you send to the backend to figure out how your system works but I did not find any good solution to avoid this.
So I was wondering what would you do in your app (here an iphone app) to make sure that hackers cannot see the content of the request your sending to the backend.
example http://myserver.com/api.php/login&pwd=test&username=pwd,
how to hide this so that no one can see the content.
I was thinking of different solutions:
1) encrypt the pwd and the username (not ideal as hacker can still see the post function of the server you are sending the request to)
2) use SSL request (I think this is only interesting to secure the connection to the server, meaning if the hacker is using his phone to connect to the server he should be able to see the request he is sending and so see the full URL)
3) change my backend so that all the request are sent to the same post function with an encrypted message. Finally the backend would decrypt and dispatch the message to the right function. This could work as the hacker would only see the url I am sending my request but would not have any information on what I am sending.
example: http://myserver.com/api.php/receiver&message=415gre6168sg4rg4e61g6r8g
"415gre6168sg4rg4e61g6r8g" could be decrypted as:
"login#pwd#username" and so I would be able to send this to the right function
But I am sure some of you have encounter similar issues and have better suggestions, would be interested to see what you would do,
Thanks
Any encryption you add is an extra effort for the hackers.
But in terms of what concerns to Apple use SSL connection should be enought based on iOS and the new IT - Security.
You can read more about the security polices used/recommended by Apple on iOS Security Guide
I want to create a helpdesk project following this great tutorial : http://blog.jetbrains.com/youtrack/2014/02/using-youtrack-as-a-help-desk/
I want to set the parameters of my mailbox using a Gmail adress but I don't know how to obtain a SSL key from Gmail.
Without it, I have "Connection timed out" error. I know where to add the SSL key in Youtrack, but I need a file (JKS or PKCS12 format).
My settings:
Protocol:IMAPS
Host:imap.gmail.com
Port:993
Login:mylogin
Password:mypassword
Select SSL key: nothing
Connection timeout:60
Socket timeout:60
Please help :)
Here how to obtain Gmail trusted root keys (from Google PKI FAQ):
Google may decide to have its intermediate signed by another root at any point in time, so you should have an update mechanism in place for the trusted roots you ship with your product. If you are developing code intended to connect to a Google property, we recommend you include a wide set of trustworthy roots. We made an example available as a PEM file here.
PEM file provided can be manually converted to PKCS12 with, for instance, OpenSSL tool.
I suspect, however, that installing a cert won't solve the issue. "Select SSL key" likely stands for client (i.e. YouTrack) certificate, which is not required by Gmail. Please check the following:
If IMAP is enabled in your GMail account
this recipe to make sure Gmail is not blocking new client application explicitly
I've been comparing a tool called Coffee Cup Website Access Mangaer, which generates htpaswrd files and assists in multi user management, against cPanel's password protection functionality.
With the cPanel functionality, when accessing the directory I receive a browser warning "Warning this server is requesting your username and password be sent in an insecure manner..." because the passwords are sent in plain text and vunerable to pack sniffing.
But with credentials created with the coffee cup product I get no such warning. It is hashing the passwords, but presumably it's vulnerable in the same way as cPanel passwords.
#User Password File - 05/01/2012 15:14:56
username:$1$sa$Wo.g/ovtw8B//SAgNBbFP1
username:$1$sa$mSD/s4oNRerHapqlNkL321
I had always assumed cPanel was just creating htpaswrd files just like this program, and can find no information as to what the difference between the two might be.
Any thoughts appreciated as always.
As long as you use HTTP and not HTTPS, the password will be sent in plain text at some point. I don't know what authentication shceme does cPanel use, but maybe cPanel is defaulting to http while the other option isn't, which would explain the difference.
I am trying to create a fairly simple User Authentification system using FLEX and AMFPHP, but I have a question about security.
Most examples I see send plain text usernames/passwords to a php file, which encrypts them, and sends them on to the database to either be checked or saved... am I missing something or is sending your username/password in plaintext a chance for a hacker to incercept the call and extract the information from your request? Would the request from FLEX be interceptable? or is it done serverside "behind closed doors"?
Yes you're right. Hash the password on the client and sends it to the server after that.
Alternatively, you could just force an HTTPS connection for your login page. That way, the password will be encrypted on the wire to the PHP server, but still available in plaintext to PHP so it can manage the hashing.
You can hash the password on the client and sends it to the server, but you must be aware that there are persons who can find out your hashing algorithm on client. If you try to foul a novice the hashing thing might work. But if you consider that the hacker is not some rookie, I think you should not even bother with the hash and use directly HTTPS.
Loading another swf nested in the previous do not resolve your problem. The browsers no not protect efficiently the files cached in the memory, and the hacker still can find the file you try to hide.
I am trying to use hashing for a test case in tomcat-users.xml. (I plan on implementing a subclass of one of the Realm classes to do the real authentication with auditing, logging, etc.) I ran the command
$TOMCAT_HOME/bin/digest.sh -a sha secret
and got the result 'secret:e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4'. I pasted this into the
<user password="e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4" roles="test" username="tester"/>
line. I added the appropriate magic words to my web.xml to use DIGEST authentication for the servlet (role = test), but when I try logging in, I get a 401 error.
I "watched" the transactions with wireshark, and it seems the browser is sending all of the right responses.
Am I doing this right? It seems to me that the digest authentication will send back MD5("username:realm:password"), so there is no way for tomcat to compare the value stored in the tomcat-users.xml file with the value sent by the browser, since it would require either "unhashing" the password value from tomcat-users.xml or "username:realm:password".
Should I be storing the hash of "username:realm:password" instead?
Boy, that was a DUE (dumb user error)!
I should have read the tomcat docs more carefully:
If using digested passwords with DIGEST authentication, the cleartext used to generate the digest is different. In the examples above {cleartext-password} must be replaced with {username}:{realm}:{cleartext-password}. For example, in a development environment this might take the form testUser:localhost:8080:testPassword.
Exactly the last part of my own question :-).