Sign in to follow this  
Omaha

Password Submission

Recommended Posts

Omaha    100
Although I won't be storing credit card numbers or home addresses or anything, eventually I'm going to get around to implementing a registration system on my website where users can sign up with a handle and then use this to add to a comments section for each post or a forum or whatnot. In the past what I've done is stored the information in a table, simply enough. Omitting other columns, the three basic ones were Username, Email, and Password. For security I did not store the password itself of course, but rather the MD5 checksum thereof. In this way anyone who DID get to the database wouldn't get password information of use. (Unless MD5 has been cracked, which I haven't heard of.) However, I question the right way to validate passwords. What I have done in the past is had an HTML form with a Username and Password text input, which then passes that information via POST to a script that submits a query along the lines of SELECT COUNT FROM Users WHERE Username='(what he typed)' AND Password=MD5('(what else he typed)')) But I question if the transition from one page to the next, where the username and password are being sent via POST from one script to the next is safe. It's a simple pipe between processes, but I wonder if that's exploitable. Additionally, if I did want to eliminate that issue and thus just send the MD5 sum through POST instead of the password itself, how I could transform the form input before send it through output. I have done something remotely similar in the past where the form that is used to add content to the site has a submit button that actually invokes a javascript function that checks to see if a "safety" checkbox has been checked (to prevent my frequent arm spasms from posting half a headline) and then submits or informs the user that the safety is turned off (or on, depending on how you look at it, I guess) and returns harmlessly. I don't think javascript has an inbuilt MD5 transformation. Being a big fan of procedurally generated content, all of my pages are done in PHP, and knowing that it's a preprocessor I don't think there would be a way to route the output through the PHP MD5 function during submission... would another scripting language fill this gap, or am I just addressing a non-issue? Like I said, there is nothing extremely sensitive (or rather will be, I haven't gotten that far yet, still setting up site infrastructure) in the user database but I'd like people to know that their passwords are secure, and the POST submission is the only place I see where it is being sent in its raw format and was curious if this is A: a hole and B: if it can be plugged.

Share this post


Link to post
Share on other sites
Michalson    1657
Congradulations, you've defeated your own security measure.

First, your language for describing the transmission seems shaky. You describe the script sending POST data to the next script. PHP/ASP and other server side scripting languages are server side. When the client requests the page, the script is executed on the server, and only the resulting HTML is sent. The POST is generated entirely by the clients web browser. In fact someone could just as easily create an HTML file on their local computer that posted data to your site (or manually post it via a program or telnet). There is no pipe between the two script processes, they are independent of each other (the closest you get is ASP.NET, which uses a lot of behind the scenes stuff to let you create web pages with the same event driven logic as applications).

Your fear of interception is technically valid. If someone can sniff the TCP stream opened from the clients web browser to your web server to send the form data, they can steal the password (however this requires that they somehow insert themselves in the middle. The only reasonable way this can be done is if they control the server you are going through, or you are on a hub with them and as such they get copies of all your packets). However your solution, encrypting the form data prior to sending it, makes no sense, and actually reduces your level of security (since it defeats MD5 protection of the database).

To help you understand, lets say you have a clubhouse. To enter the clubhouse, you must stand outside the door and say the secret phrase ("no girls allowed"). Now you have identified one possible attack - someone could sit in the bushes and overhear the secret phrase. Your solution however is to simply have the person say an encrypted form of the phrase. The person in the bush can still hear this encrypted version, and since the doorman is now listening for the encrypted version, it's exactly the same as if there was no encryption at all (the encrypted password now *is* the password).

Share this post


Link to post
Share on other sites
Unknown User    122
Your best bet is to just use normal MD5 encryption while sending the POST data. Sure, someone on the connection can listen to it, but if the connection is being picked up by another source, then the users computer is already at risk to begin with. So if there computer is at risk to be network sniffed then even if everything you send is all encrypted and super safe, the attacker could simply use a technique such as keylogging to gain the password.

It's up to your users to protect them selves if they want their account secure. You do the server end and let your clients worry about their own security.

Share this post


Link to post
Share on other sites
Michalson    1657
Quote:
Original post by Unknown User
Your best bet is to just use normal MD5 encryption while sending the POST data. Sure, someone on the connection can listen to it, but if the connection is being picked up by another source, then the users computer is already at risk to begin with.


Then what is the point of "encrypting" it in the first place? Since the encryption is meaningless (anyone who sees the "encrypted" data can just submit it themselves for the same effect), why go to all the trouble. It can very easily be done (I could write you a javascript MD5 form page in 5 minutes), but it serves absolutely no useful purpose. It actually has a negative effect - first you are making your site less accessable by messing with scripted form submissions, and second you are defeating your MD5 database protection, since if the server accepts something already MD5 encrypted, the hacker doesn't need to decrypt his stolen database, he can just send the MD5 encrypted passwords he already has.

Share this post


Link to post
Share on other sites
Michalson    1657
To make it a short answer, you have no hope of implimenting a properly secure submission system. You have two options, accept that your security doesn't need to be bank/credit card level (if a hacker is able to create a man in the middle attack just to get a specific users password, they can probably send that person a key logger just as easily) and continue on with a proper MD5 done at the server in order to make the database safe, or you can decide logins have enough financial value that someone could go to the trouble essentially tapping someones internet connection, in which case you need to look at HTTPS (SSL), which uses public key encryption, the only way to completely prevent a man in the middle attack (and please don't try making your own public key encryption system, you might as well perform your own open heart surgery after taking a first aid course)

Share this post


Link to post
Share on other sites
pragma Fury    343
You could use an asymmetric encryption system.

When you build the form in your PHP, place the public key somewhere that can be accessed by script. Encrypt the user's password using the public key before POST-ing it to the server, and then decrypt it using the private key, which only the server has access to. Then check that password against your MD5.

Even being able to look at the generated form and get the public key, it's usless without the password and private key.

Should work, shouldn't it?

First result on Google for "Asymmetric encryption javascript" was a link to a javascript library that supports RC4, AES, CSR and RSA cyphers. In addition to MD5.

Share this post


Link to post
Share on other sites
Will F    1069
Quote:
Original post by Omaha
Unless MD5 has been cracked, which I haven't heard of.


If my understanding of cryptography is correct (which may not be the case), MD5 is still fairly safe to use for nonimportant things, but collisions in it have been found in the past year. Read more at Wikipedia.

If I understand correctly, this means it is not possible to determine a password from a hash, but it is possible to find two passwords that will produce the same hash. However, I don't think this means that given a specific hash, you can find a password that will produce that hash.

Then again, i'm sure someone with a better understanding of the concepts could explain this (or correct me if i'm wrong).

Regardless, in the real world it's not as important. In all likelihood many of your users will use bad passwords (like the word password as their password) - which are very vulnerable to dictionary brute force attacks. So if someone is able to get into the database, it would not be too hard to determine some passwords.

Share this post


Link to post
Share on other sites
Omaha    100
The fact that the passwords are stored in their MD5 form in the database should be able to be public knowledge; otherwise it's just a step away from good old security through obscurity, since it would seem like "I know something you don't know!" safety net.

BUT as someone said, I have to depend on the client to do their part to keep their account secure, and one level up I have to depend on my host to keep the database and his server secure. It's set to ONLY allow local access so only if the query comes from the server itself (hence, my script) should anyone be able to get anything out of it. So while some guy could potentially grab the databsae off the server, figure out what format it's in, and then do a SELECT * FROM Users and then fire at the server something that just rips the Password column out of the query, it shouldn't work--at least if my host is on the level, it shouldn't. So the dependency also goes up the ladder.

My understanding of GET and POST was that they were server side transports, just that GET sends information via the URL and POST sends it via stdin. I base this assumption on the fact that my first experience with GET and POST was with playing with CGI and CGI programs are server side. The user input would go through the webserver and then get piped into the new process. In this case, it would go through the webserver via the generated HTML form and then get sent sort of loopback style to the next page, keeping it on the server. However, yes, when the user fills out the form, everything he types in is being sent verbatim (I assume that there's no native encryption) from his console to the webserver when he hits SUBMIT. So ok, it seems to me that a client-side script that sent not what he typed for password, but rather the encrypted password is what I'd need. Like I said and you agreed, I'm not hosting credit card numbers or social security numbers, so I don't need to call my host and demand that a laser grid and sentry guns be installed in the server room, but I would like people to trust the website, since if they don't, that's just a natural turn off and nobody will register. (Of course since it's a noname website for now, there will be trouble with that to begin with.)

I have no plans on implementing my own encryption scheme, believe me. I have enough trouble trying to come up with a checksum formula for resource management in my game code so that I can definitively say a .WAV file and an .MD3 file don't end up conflicting with one another and the model rendering function ends up trying to draw PCM data. But then again maybe that's just me trying for perfection, I'm sure one of the algorithms I've come up with would work fine without collisions. Ok that's off topic.

Share this post


Link to post
Share on other sites
Monder    993
Quote:
Original post by pragma Fury
You could use an asymmetric encryption system.


Quote:
Original post by Michalson
in which case you need to look at HTTPS (SSL), which uses public key encryption


SSL is asymmetric encryption. It's also not trivial to crack unlike the system you came up with. Even if you're using a public key to encrypt the password client-side it's just like making an MD5 of the password, a hacker just transmits the encrypted version instead which he/she grabs by sniffing packets or whatever.

Share this post


Link to post
Share on other sites
Monder    993
Quote:
I'm sure one of the algorithms I've come up with would work fine without collisions


You do realise than any checksum is bound to have collisions? Otherwise it's actually a compression alogorithm in disguise.

Share this post


Link to post
Share on other sites
Replicon    306
Another thing you should consider, if you want it to be secure, is avoidance of SQL injection. For example, suppose your login code does:

SELECT COUNT FROM Users WHERE Username='(typed)' AND Password=MD5('typed'))

and it logs you in using that, you have a major security issue. If I type in

Username: "some_real_user' --" (without the quotes)

then look at the happens to the SQL:

SELECT COUNT FROM Users WHERE Username='some_real_user' --' AND Password=MD5('typed'))

Anything after the '--' is commented out... so your thing becomes

SELECT COUNT FROM Users WHERE Username='some_real_user'

Uh oh...

What you should do, as a rule, is use Bind variables (or "prepared statements", in the Java world). The way it works is, you put placeholders into your SQL code as so:

SELECT COUNT FROM Users WHERE Username=:userName AND Password=:md5Passwd

(assuming your do your encryption on the client side...whatever)

then, in your code, you populate some data structure (strings or whatever you need in your sql) with what the user types. Then, you don't need to worry about checking for these things. As an added bonus, you only need to compile your SQL statements once, and then just re-use them with different bind variables.

Share this post


Link to post
Share on other sites
Omaha    100
Quote:
You do realise than any checksum is bound to have collisions? Otherwise it's actually a compression alogorithm in disguise.


Allow me to retro-interject "will work without collisions for my purposes." My point about programmers in the same room is proven. :P

Share this post


Link to post
Share on other sites
Omaha    100
Quote:
Original post by Replicon
Another thing you should consider, if you want it to be secure, is avoidance of SQL injection. For example, suppose your login code does:


Interesting, thank you. I'm only a basic SQL guy and this information is new and useful to me!

Share this post


Link to post
Share on other sites
Inmate2993    222
MD5 has been cracked, yes, but not in that they can use an MD5 checksum to get a list of viable passwords, but rather the time it takes to bruteforce a password that generates the same stored hash has been reduced enough that it can be done within a feasible length of time.

Anyways, what your system should do is store the IP address of who logged in (or their whois reverse lookup), and mark them as logged into the database, with a scheduled inactivity logout. That way, they can't be spoofed while they're in the system and between pages.

Also, for some serious security, extent the length of the passwords from 8 to 1024, and tell them that a passphrase is a better idea. The sheer length makes it much harder to crack.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this