A new project requires a simple panel (page) for admin and staff members that:
Preferably will not use SSL or any digital ceritification stuff, a simple login from via http will just be fine.
has basic authentication which allows only admin to login as admin, and any staff member as of the group "staff". Ideally, the "credentials(username-hashedpassword pair)" will be stored in MySQL.
is simple to configure if there is a package, or the strategy is simple to code.
somewhere (PHP session?) somehow (include a script at the beginning of each page to check user group before doing anything?), it will detect any invalid user attempt to access protected page and redirect him/her to the login form.
while still keeps high quality in security, something I worry about the most.
Frankly I have little knowledge about Internet security, and how modern CMS such as WordPress/Joomla handle this.
I only have one thing in my mind: that I need to use a salt to hash the password (SHA1?) to make sure any hacker who gets the username and password pair across the net cannot use that to log into the system. And that is what the client wants to make sure.
But I am really not sure where to start, any ideas?
The use of HTTPS is an absolute requirement, and must be used for the entire life of the session. Keep in mind that session id's are used to authenticate browsers and if an attacker can obtain one (sniffing or xss), then he doesn't need a username/password. This is laid out by The OWASP Top 10 2010 A3 Broken Authentication and Session Management. If you want to implement secure session you must read that link.
md4,md5 sh0 and sha1 are all a broken message digest functions and can never be used for passwords. Any member of the sha-2 family is a good choice, sha256 is very large and is a great choice for passwords.
You should absolutely never transfer a password hash across the network or spill it to a user/attacker. If you are sending a hash to the server to authenticate then you have introduced a very serious vulnerability into your system. Using sql injection the password hash can be obtained from the database, then this hash can be simply replayed to authenticate, bypassing the need to crack the password hash. This is as if you are storing passwords in clear text.
Use the $_SESSION superglobal and session_start() to maintain your session state, never re-invent the wheal. The default PHP session handler is secure and will do what you need.
session_start();
if(!$_SESSION['logged_in']){
die("Authentication required!");
}
Also make sure to implement CSRF protection into your system. Using CSRF an attacker can access the administrative panel by forcing your browser to send requests. Make sure to test your application for XSS this is a good free xss scanner, again xss can be used to hijack an authenticated session by using XHR or by obtaining the value of document.cookie. It is also a good idea to test for SQL Injection and other vulnerabilities, wapiti will do the trick.
Not using SSL would leave a pretty substantial hole in the whole system as it is pretty easy to sniff network traffic
This has been much discussed on SO already, here are some of the useful links:
Developing a secure PHP login and authentication strategy
Login without HTTPS, how to secure?
Secure Login in PHP
Related
I'm currently trying to create user authorization that follows:
The definitive guide to form-based website authentication
I already implemented crsf tokens, passwords are encrypted in database etc. Now I need to add some encryption to data being send at user sign-in (can't use SSL).
I've been looking for some some good solution but I've found only:
http://unitstep.net/blog/2008/03/29/a-challenge-response-ajax-php-login-system/
I'm not security expert so I don't want to write such system by myself (but I guess I have to).
Do you know any class / lib that provides challenge-response feature?
Data must be hashed at client side before sending to server - isn't that unsafe by definition?
After reading the article at unitstep.net, it does seem interesting.
The challenge is a cryptographic nonce, which means is only sent once to the client and after successful login, it is invalidated, so if someone were sniffing the connection and they received the challenge and the response, it wouldn't work since next time around it will be different. As far as the login credentials are concerned, someone sniffing the connection will not feasibly be able to hack your login information by using the data sent during login.
However, when not using an encrypted connection, there are other downfalls. A few I can think of are:
If a hacker got the challenge and your response, they could perform a dictionary/brute force attack on it to retrieve your password. If poor (fast) cryptography is used and a simple password is used, this may be done relatively quickly, so make sure to use a slow algorithm or use many rounds if it is a fast one to achieve a slowing effect.
This method does not provide authentication, which could lead to a man-in-the-middle attack.
Since it is done client-side, you have no control over the password strength. For all you know, they could be using an empty string.
A hacker can sniff what the user is doing while logged in
Your site would be far more vulnerable to session hijacking
Even though your login credentials are safe in themselves (since they are never transmitted), the next challenge is always stored ahead of time in the database in plain text.
Valid SSL certificates are not expensive. Doing a quick search for "cheap ssl certificates" found a few matches under $10/year (about the cost of your domain name). This is definitely the way to go if you can.
Now, to answer your actual question:
Do you know any class / lib that provides challenge-response feature?
No, sorry.
Data must be hashed at client side before sending to server - isn't
that unsafe by definition?
I don't see how this would be unsafe. I have seen a few websites implement browser-side certificate logins (such as http://www.startssl.com and Webmin also has the same feature). A certificate pair is calculated by the browser and the public key sent to the server for authentication.
Edit 2016:
If you're looking for completely free SSL certificates I highly recommend https://letsencrypt.org/. I currently use them for about 10 domains without problem and have the certificates automatically renew using a simple cron job, so now I basically never have to worry about certificates again. They also accept donations which I would encourage anyone using them to do, especially since they are saving you ~$10/year per domain.
I am building a sign up page for user to sign up as a member, and am wondering how to keep the user's password secure if I have no ssl-server.
The only way I can imagine is to md5 encrypt the user's password before sending back to server for storing, and next time while in login page, the password input will be md5 with a dynamic secret seed before sending back to the server to autheticate if the user is a member.
Is it a good idea? Any good suggestion? Do I have other option?
Thanks a lot for any good idea.
The problem is that you need some kind of shared secret between client and server that a possible eavesdropper does not know to be able to encrypt it. As the eavesdropper can also listen to all traffic between client and server beforehand, you have some kind of a chicken and egg situation.
Only way out: use public/private key encryption. The client encrypts the password with the public key of the server and then sends it. The only one who might open it is the owner of the private key, presumably your server.
Have a look at http://www.jcryption.org, it might do what you want.
First, it's worth trying to protect passwords even if the assets you're protecting do not require a high security approach - since too many people use the same password for different sites - however for a secure, public facing system there is no substitute for SSL.
It is possible to do this - if you hash the submitted password with a challenge from the server. And you've already got a suitable challenge available in the form of the PHP session id (although you need to ensure that you're not susceptible to session fixation, and there are also some security constraints around allowing the session cookie to be read from Javascript).
This of course depends on having an un-hashed password on the server to create a comparison value from. And this is a definite no-no.
So....you store the password hashed with a known salt (S1) on the server. When someone wants to login you send them a session id (S2) and S1 and they send back:
md5(S2 . md5(S1 .password));
There are javascript implementations of md5.
Md5 is approaching the end of usefulness as a secure cipher - however for the puproses stated here it should be adequate.
I guess you don't really need to decrypt it, as people normally only store the password hash in the database. (unless you want to know/harvest their password).
A common way is to has the password and send only the hash.
I'll suggest you to pass "salt" from the server side to the form, and hash the password and the salt together to make it more random.
To be really secure, you'll have to implement/find a public key encryption algorithm implemented in javascript. Using any symmetric key encryption would still be vulnerable to man in the middle attack as your key has to be transferred to the client side.
The real fix for this problem is to use real SSL/HTTPS connection.
Rationale:
If the content that is available after logging in is worth protecting, the whole session must be protected, not just the user password.
If the content is not worth protecting why require logging in at all?
Note that you do not need to use paid SSL certificate to get the benefits of SSL. You may sign your own (see http://www.debian-administration.org/articles/284 for an example). However, recent versions of Firefox have made use of self signed certificates a pain in the ass unless the user is ready to install you as CA. (By some weird logic Firefox displays much less alarming dialog for adding a new CA than adding an exception for a singler server that uses self signed certificate. This is really bad because accepting a new CA accepts all certificates that will be signed by that CA in the future!)
However, if you insist on not using real SSL, you may implement encryption with JavaScript: http://www.hanewin.net/encrypt/ or http://www.jcryption.org/ - be warned though that this requires a lot of work and the end result may end up nearly as protected as SSL if implemented correctly in every little detail. The end result will never be as safe as SSL because you have to transfer the JS script to the visitor's user agent (browser) without encryption and as a result, the visitor may end up running JavaScript selected by the attacker (the attacker can execute Man-in-the-Middle attack because otherwise you don't need any protection to the user password, either).
Certificate Authorities(CAs)'s Public keys stored in web browser is the only thing that prevents SSL/TSL to be not vulnerable to man in the middle attack. So, there is no way to protection these solutions.
All of these solutions are vulnerable to man in the middle attack.
Note that Mallory (Malicious active attacker) can replace his public key in the page.
You should be using SSL(the rest is NOT that secure) to do authentication and luckily you can by using open-source OpenID just like stackoverflow.com does. You can for example read why Stackoverflow.com has switched to OpenID by reading this article(good read).
There is a very user-friendly OpenID library available from LightOpenID. I have created a little library "Openid for PHP with an user-friendly way to select an OpenID thanks openid-selector and LightOpenID" available at github. I also have put a demo on my webhosting available at http://westerveld.name/php-openid/
I'm making an Ajax login system and i wonder if this is secure
Post the username and the password with ajax
Check the login server side, if valid, return the new session id and the user id in a JSON string
Get the JSON with javascript then create the session's cookies "session_id" and "user_id"
Call the page where the logged user is redirected with AJAX
Thanks
Secure for 08/15 website: yes
Secure for online banking: no
The method you use is equivalent to an unencrypted everyday login <form>. Albeit you should really not rely on a "user_id" cookie. Rather save the verified user_id in the session store only.
Also you might try to simply return the session cookie on the JSON result for the AJAX call. It usually sticks to all further HTTP requests, so you don't need (3) to set the cookie via Javascript additionally.
Creating a secure login system is HARD. I would just like to name a few things that could go wrong(bite you in the ass):
unsecure connection(http instead of https).
XSS
CSRF
SQL-injection
unencrypted passwords or simple md5 vulnerable to rainbow table attack.
There a lot of free secure login systems(created by security experts) which you should use instead, for example:
facebook connect
google friend connect
twitter single sign on
openid
I think it could be secure when use post in step 1. already ciphered password and little bit ciphered username, to avoid simple attacks.
Like send(base64_encode(username),md5(password));
And another word, you should check valid session id on server-side, not on client-side in app.
You cannot let client-side script (which could be altered by adv. user) to check session validity.
It's like creating nice and secure API, you have to check everything on server and don't let any dangerous (setting/deleting/creating methods, etc..) opened wordlwide.
I can think of several problems with this idea, in direct order of importance (least to most):
1) Your site won't work for those with JS disabled.
2) Your site may not show the in-browser yellow toolbar to notify the user that SSL/HTTPS is enabled. (Depends on implementation).
3) The user_id parameter is not required client side, and probably not a good idea either. Authentication tokens are almost always just a single identifier, and that's all that is required to prove a user is logged in.
4) It's usually bad practice to write your own authentication capabilities. I know you are not replicating the back-end (which is a very bad idea), but most frameworks already automate the front-end authentication for you and do a good job at it. Use those frameworks, cause they have been tested and are secure. Also, a lot of the time the framework will help you (eg. make it easier to switch authentication providers).
I would like to make a simple user login/registration system using PHP and mysql. I don't need to get any information beyond what is necessary for the user to log in and out. I want to make sure that the system is secure.
The way that I currently understand how it should work is:
Registration
User enters their email address and password and confirmation password.
The PHP script makes sure the passwords match and that the email is a valid address and is not already in the database.
It hashes the password along with a random salt and stores the salt and resulting hashed password in the database. (Is php's md5 function suitable for this? I am not quite sure how this part works.)
Store an email confirmation code in the database and send the given email address a link back to the website that contains that code for verification?
Login
User input their email address and password.
The server looks up the email in the database and retrieves the salt. Then hashes the salt with the password the user just provided to see if it matches the one in the database.
How do I make the session persist after login. With a PHP session? A cookie? What should get stored in the cookie for remembering the user between visits?
I basically would just like some verification that the process I am describing is an accurate and secure way of doing user registration/login. Also, what are some good tutorials with more information.
Is php's md5 function suitable for this?
MD5 is no longer considered secure; consider using PHP's newer built-in password hashing with the bcrypt algorithm which has variable computational complexity: PHP password_hash() and password_verify().
How do I make the session persist after login. With a php session? A cookie? What should get stored in the cookie for remembering the user between visits?
Ideally, you would use a PHP session to maintain state during a single visit, and if you would like to have a "remember my login" option, you would use a cookie that contains enough information to authenticate a returning user and restart a new session. There's a good article from 2004 on best practices regarding login cookies here: Persistent Login Cookie Best Practice. You might also be interested in a more modern (2015) solution to securely implementing "remember me" checkboxes.
Apart from these, I think whatever you have described is fine.
A few notes on some missing considerations:
PHP sessions typically already use cookies: the session ID is stored as one.
Sessions can be hijacked; you should also take steps to reduce the possibility (start by reading "PHP: Preventing Session Hijacking with token stored as a cookie?" and "What is the best way to prevent session hijacking?").
Related to hijacking is fixing, where an attacker picks the session ID. There are two ways of combatting this: set session.use_only_cookies (the default in PHP >= 5.3) and change the session ID when a user logs in with session_regenerate_id.
Also see the question "PHP Session Security" and article "PHP Security Guide: Sessions".
if you want a ready made solution
User Cake in php5
pretty much secure .. and stable.
Since Login systems are such an integral part of a website, you're screwed if it gets hacked. Unless you're doing this for educational purposes, I recommend finding a system that was created by someone that has experience in the field. You'll sleep soundly at night.
An example of a solid pre-built login system is tank auth, it's written for the Code Igniter framework. You might want to look at how this guy designed the system to get ideas on what's important if you decide to write your own.
Also just a note from experience, it takes more time to write a login system from scratch than it does to learn the code igniter framework and install tank auth.
Here's a recommendation: consider using a readily available framework that inherently provides such functionality. they are tried and tested. have a look at Kohana. It has an Auth module which takes care authentication.
I have a PHP script that runs as a CGI program and the HTTP Authenticate header gets eaten and spit out. So I would like to implement some kind of FORM based authentication. As an added constraint, there is no database so no session data can be stored.
I am very open to having a master username and password. I just need to protect the application from an intruder who doesn't know these credentials.
So how would you implement this?
Cookies?
I could present the form and if it validates, I can send back a cookie that is a hash of the IP address come secret code. Then I can prevent pages from rendering unless the thing decrypts correctly. But I have no idea how to implement that in PHP.
A few ways you could do this.
htaccess -- have your webserver handle securing the pages in question (not exactly cgi form based though).
Use cookies and some sort of hashing algorithm (md5 is good enough) to store the passwords in a flat file where each line in the file is username:passwordhash. Make sure to salt your hashes for extra security vs rainbow tables. (This method is a bit naive... be very careful with security if you go this route)
use something like a sqlite database just to handle authentication. Sqlite is compact and simple enough that it may still meet your needs even if you don't want a big db backend.
Theoretically, you could also store session data in a flat file, even if you can't have a database.
Do you really need a form? No matter what you do, you're limited by the username and password being known. If they know that, they get your magic cookie that lets them. You want to prevent them seeing the pages if they don't know the secret, and basic authorization does that, is easy to set up, and doesn't require a lot of work on your part.
Do you really need to see the Authorization header if the web server takes care of the access control for you?
Also, if you're providing the application to a known list of people (rather than the public), you can provide web-server-based access on other factors, such as incoming IP address, client certificates, and many other things that are a matter of configuration rather than programming. If you explained your security constraints, we might be able to offer a better solution.
Good luck, :)
If you're currently using Authenticate, then you may already have an htpasswd file. If you would like to continue using that file, but switch to using FORM based authentication rather than via the Authenticate header, you can use a PHP script to use the same htpasswd file and use sessions to maintain the authentication status.
A quick Google search for php htpasswd reveals this page with a PHP function to check credentials against an htpasswd. You could integrate it (assuming you have sessions set to autostart) with some code like this:
// At the top of your 'private' page(s):
if($_SESSION['authenticated'] !== TRUE) {
header('Location: /login.php');
die();
}
// the target of the POST form from login.php
if(http_authenticate($_POST['username'], $_POST['password']))
$_SESSION['authenticated'] = TRUE;
... About salt, add the username in your hash salt will prevent someone who knows your salt and have access to your password file to write a rainbow table and crack number of your users's password.