I am building my own game panel and it required the user to introduce into the database the user and password of their linux server. This will allow the game panel manage their servers. My problem now is this:
When the user introduces his linux user and password it is stored in plain text into database and then it is retrieved in the PHP script. However, if the database ever gets breached the hackers will be able to breach their servers as well and I want to avoid that at all costs.
At the moment I am using register and login system in which I implemented password_hash($password, PASSWORD_BCRYPT) and password_verify. I tried to use the method to my problem but it required user input in order to match the stored password with it.
All I need is to store an user and password into database in the most secure what that when a hacker manages to breach my database all the data there will be useless to him.
I am a newbie PHP web developer working with Javascript and BASH. I am still a newbie in these to fields as well. So if you can offer my newbie-friendly answers I would more than thankful to you. (as my first question was answered within hours I am positive I will find a solution to this one as well)
I'm getting informed on data encryption in these days as well, especially to implement the "Privacy by design" concept legally required by the GDPR (The EU General Data Protection Regulation).
Using PHP and MySQL there are two main ways you can encrypt your data, getting it ready to be stored into your DB:
Using MySQL functions AES_ENCRYPT / AES_DECRYPT
Using OpenSSL functions in PHP, in particular openssl_encrypt and openssl_decrypt (it provides, among others, an AES-256-CBC encryption). To know how to use it, you can have a look directly at the examples in the functions' documentation or check out this answer on StackExchange.
What I suggest you, if you have the opportunity, is to use Laravel and its encrypter, which provides all you need to easy encrypt your data using OpenSSL with AES-256-CBC.
Related
This question already has answers here:
Opinions about authentication between application and database tiers
(2 answers)
Closed 4 years ago.
We are creating PHP/MySQL web application.
On one side:
I have my PHP developer that believes creating a table with users/passwords/permissions to give or deny access to some parts of the final application.
On the other side of the equation, my DB expert wants to use the database directly to create users/passwords/permissions.
For the DB option, I think we need to create a separate web service in front of MySQL, for this to work? or do I give users direct access to the DB?
What would make the best way to do this?
How does well stablish php/mysql apps work, like Dupral or Joomla?
Yes this is a question about design best practices, but I need to find out the best practices for PHP/MySQL development. Is MySQL supposed to manage web users, or just one DB user and the rest on the app level.
Go with the PHP route.
Whether you create the logins through PHP or directly through MySQL, they'll still end up in your MySQL database. There are a few differences between the two approaches though. The main point being that if you go the PHP route, your users will be able to create their logins themselves (which means picking out their passwords themselves). If you go the database route, your users will have to have passwords allocated to them.
In MySQL, it's possible to use something like SHA() to securely hash a password (with a salt), though as far as I'm aware you're unable to pick a more secure encryption algorithm in MySQL. SHA-256 / SHA-512 will almost certainly suffice for your needs, though you may want something a bit more secure.
With PHP, you have access to methods like password_hash() and password_verify(), which can be used alongside alongside an algorithm like PASSWORD_BCRYPT or PASSWORD_ARGON2I (which is much more secure than the standard SHA-256 or SHA-512).
Finally, you have to consider what should happen in the event of a database breach (which there are roughly 30,000 of every day). As previously stated, the encrypted password is stored in the database in either case. If you create logins through MySQL, you'll likely also be exposing the method of encryption (possibly along with any salts used). If you build the logins through PHP, an attacker would need full shell access to your website in order to be able to work out how you encrypted your passwords.
Most importantly, never give users access to your database. In fact, I would recommend ensuring that your main database user role only has the required privileges to interact with the data (likely SELECT, INSERT, UPDATE) and using a separate user with CREATE privileges for creation of the users.
After researching some hours about the topic of securing stored data I am a little bit confused of what is the best way to go now.
I have a databank for my (SSL) website where I am the only one that has access to it (hackers not counted). The login data is stored in a configuration file outside of the document root. In the database I have stuff like names and adresses from my clients and I am now worried that I need to implement all the security measures put forward by cryptography experts like in this answer (How do you Encrypt and Decrypt a PHP String?) or as asked here (Storing sensitive data securely in a database).
Since neither in my PDO/SQL and PHP seminars nor in regular posts here on stackoverflow I see these encryption and authentication methods being used or more specifically e.g. the keys when explaining PDO and PHP commands like INSERT INTO ... etc. I am unsure if it is now necessary to deploy encryption and authentication measures on every entry in my databank (is it even possible to do this afterwards?). The safety measures I have been informed about in the tutorials and articles are to use PDO's prepared statements.
If encryption and authentication is what I have to do, which is probably the case: Would it not be the most convenient and fastest way to simply use password_verify() and password_hash() for every sensitive data entry like it is done for passwords?
EDIT password_verify() and password_hash() are hashing (not encryption) methods, meaning that the data is irretrievably mangled and can only be confirmed but not read.
There are different types of database encryption, and depending on what data you want to protect, and why, you will do different things.
1) Database level encryption / Transparent data encryption
This is where your RDBMS encrypts everything for you at a file level. This means if anyone has access to the hard drive, or back-up media, they should not be able to access the data. See here for how to do it with MySQL: https://dev.mysql.com/doc/refman/5.7/en/innodb-tablespace-encryption.html (note this is not a PCI compiant solution, you'll need MySQL Enterprise Edition or another Enterprise database, or further security measures for that).
Note this does not protect your data if your application is compromised.
2) Field level encryption
You can encrypt data to be stored in any field you like. Here's a good answer that deals with that: https://stackoverflow.com/a/10945097/
The drawback of field level encryption is that you can't then query across the data. In each case you'll need to pull the data into your application, and then decrypt it one field at a time.
Note this does not protect your data if your application is compromised.
Note also the difference between 'encryption' and 'hashing' (password_verify and password_hash are about hashing)...encryption lets you secure data, store it and retrieve it. Hashing by definition does not let you retrieve the data.
In all cases the most important thing is to secure your application. Encryption of the underlying data is very much a secondary concern.
Since your web server (presumably) will have to have access to the data, it's somewhat useless to encrypt it at rest when the web server can (will have to be able to) decrypt it. Why? Because the web server is often the weak link. If an attacker can get access to it, they can do anything it can do, including decrypting the data.
Encrypting data at rest is only useful to prevent backchannel leaks, like improperly handled backups (which you're doing, right, right?) which dump the data in plaintext to a file which then inadvertently gets lost somewhere. To prevent that you should use whatever at-rest encryption your database offers transparent to the client; i.e. it's not something you should burden the application logic with if it's not integral to your application, it's something the database should worry about.
password_hash is a hash, it doesn't encrypt data, it irretrievably mangles it so it's impossible to get the original back from it. It's great for storing credentials which you need to confirm but not read; it's useless for anything else.
The main security points are to isolate your database server "physically", i.e. to not grant any access to it from anything but the web server; be very restrictive and specific about that. That then means the weak spots are at those ingress points like your web server. Ensure your web server is locked down as much as possible, exposes as little attack surface as possible (no unnecessary open ports or running services) and that your application code running on it doesn't allow any exploits (yes, that's the hard part that takes knowledge and discipline).
You can further tighten it down by segregating access to the database with different accounts which have different permission levels; i.e. some accounts only have read access to certain tables while others have read/write access to other tables. If you can split up your web server(s) into separate roles which all only need specific limited access, this further enhances security by avoiding vulnerabilities in one part enabling exploits in another.
I have a website which is a front end to a MySQL database. This data is also exposed via a web service (fur use in Android application).
Currently I am maintaining the data via PHPMyAdmin but this is cumbersome and not that "pretty".
I want to create an /admin module where I log in (against values in a PHP Varialbe or a MySQL table) and once logged in I can edit,delete,add data.
Questions:
Is it acceptable in terms of security to compare entered credentials against static variables? There will only be one user so I feel like it is overhead to create a table for members.
Any guidelines on going down this route?
I don't see any reason why you couldn't do it this way, assuming you will always have just the one user. The main consideration would be if someone somehow got a look at your code, they would see the stored password. So, you could store it using password_hash to generate a one way hash, and then verify it with password_verify. Here's how I might do it:
Using password_hash(), generate a hash:
// copy the hash output, then delete this code
echo password_hash("thepassword", PASSWORD_DEFAULT);
Then, in your code, store the hash:
// paste hash here
$passwordKey = '$2y$10$j33UPA7gNxSOBsXQcyquLOZRuO6X8k8hZOb1RA79iN8gLlqp9eIPO';
Then run password_verify() to check the user input:
if (password_verify($userInput, $passwordKey))
echo "correct";
else echo "incorrect";
Demo: http://3v4l.org/PknTI
consider looking at this manual for encryption methods with php. My gut instinct is to make a user table, or at least a table with just the encrypted password in it, rather than just checking the variable against a value.
That being said, if you don't think anyone will really even consider trying to fool around with the system and get past it, you probably don't need to be this cautious. I've built a few front-ends as well as back-ends to communicate somewhat friendly with a database, and I've never experienced a considerable amount pressure on the security.
Hope this helps, if you have any questions about how I've designed the ones I've made, feel free to email me at spencer#codeshrub.com
If phpmyadmin is installed at your server localy, than it is NOT securely at all
You can use any MySQL client that supports ssh connection. E.g. Sequel Pro for Mac or HeidiSQL for WIN.
Also, you can use basic HTTP Authentication for you admin script. But, since it's very simple it's not protect you from bruteforce or password leaking, etc.
Anyway, if you prefer security you need to make your own authentication in PHP, You can use this package for example. It is simple and has many security features
I am using a Postgres 9.3 database as a back-end for a web application. I use PHP 5.5.7 to connect to the database and return JSON for the front-end AJAX calls.
I'm trying to decide on where to put the user authentication logic.
I am not a security expert; however, I am familiar with PHP's new password_*() functions and I have a strong grasp of what is going on under the hood. I am also familiar with the Postgres Extension pgcrypto and the associated crypt() function.
My question is, does it make sense to use PHP or Postgres to hash passwords?
I was curious as to how these functions differ, so I made a password hash in PHP and then gave it to Postgres to see if Postgres uses the same algorithm. Given the same parameters, Postgres returned a different result when compared to PHP (not unexpected, but with noting).
PHP
password_hash('password', PASSWORD_BCRYPT, ["cost" => 15]);
output: $2y$15$o8JufrnVXoob2NKiEGx6.uI4O2D4VcaAmY7WtNq5zPFiJow4KohGu
Postgres
SELECT '$2y$15$o8JufrnVXoob2NKiEGx6.uI4O2D4VcaAmY7WtNq5zPFiJow4KohGu' = crypt('password', '$2y$15$o8JufrnVXoob2NKiEGx6.uI4O2D4VcaAmY7WtNq5zPFiJow4KohGu')
output: false
PHP vs. Postgres
Given that these processes are different, I wonder if one is better then the other? Is one more, or less, secure?
Some other thoughts:
I currently have all logic stored in the database (in views, functions, constraints, etc.) so if I ever need to use a different front-end I don't have to worry about missing logic. Calculating password hashes in PHP would effectively require all requests to pass through PHP to access the database.
On the other hand, putting the logic in the database would allow me the flexibility to use other connection options; however, all of the Postgres queries are logged. I can't disable the logs because of the WAL used in replication. This seems like a big security hole.
Am I on the right track here? What am I missing?
EDIT
I just looked at another message thread and found some more information.
Putting the logic in Postgres would require the database to processes and perform the hash operation. This would be a bad thing for other users and batch jobs that need those resources.
Not only would the hash slow down normal operations, it would make the whole system more vulnerable to DOS attacks.
Our simple web servers with load balancing would address both issues...
Again, am I on the right track here? What else am I missing?
For the difference between versions 2y and 2a, see this thread and the various links within it:
https://security.stackexchange.com/questions/20541/insecure-versions-of-crypt-hashes
My understanding is there was a problem with the 2a implementation in PHP until v.5.3.8, though only for strings that contained non-ascii chars. PgCrypto, as you noted, doesn't "speak" 2y for some reason, and I'd assume it suffers so such problem. (Perhaps report this as a bug?)
Apart from the points raised in the latter, you nailed the main security difference between the two in your question: systematically hashing the password within the database is convenient but implies that you send it to your database in clear text, where it can (and will) be logged — or snooped at outright, if your DB connection is not encrypted.
In an ideal world, you'd hash the password in the client app using javascript before it's even sent to PHP. The next best thing is to send it using SSL to PHP, then hash it using PHP before sending it to the DB.
Aside: I'm pretty certain that PHP's crypt can generate a (secure) 2a version hash if you need interoperability for some reason.
I am looking for a way to insert encrypted passwords into a database (MySQL) that I can decrypt later. I've done research and I've came to the conclusion that bcrypt would be the more secure way to store passwords, but then I can't get them back, and it's important that I know their passwords in case I need to login to their system (I don't want to rely on IP authentication).
http://php.net/manual/es/function.mcrypt-cbc.php has some good examples of using a library for encryption on both PHP and PERL, but PERL requires an additional library and PHP needs to be a certain version.
I am looking for a solution that has ability to run on PERL and PHP natively (no additional libraries) with versions that atleast a year old. No PHP 5.3 functions or anything of the like.
The system only has 100 or so users, so there isn't a huge risk of someone even getting access to the database, but just incase I want some kind of protection. If need be, I would be OK with having to add a library to PERL, but I can't really be picky with a PHP library or require PHP version higher than 5.0
If you're using MySQL you may want to look into using mysql functions such AES_ENCRYPT/AES_DECRYPT:
http://dev.mysql.com/doc/refman/5.1/en/encryption-functions.html
Using a standard hashing function (e.g. one of the sha versions) does mean that you can't get the password back but it doesn't mean you can't log in to their system.
Just update the password hash in the database with a known one (e.g. update user set password = sha1('password') etc), log in, then update the password back to the old hash. You're in, and their password is back to how it was.
If you're encrypting and decrypting, then the keys will need to be on the server; if you're compromised, the attacker will have access to the keys as well, so you might as well leave the passwords unencrypted if you're not going to hash them.
Just hash the passwords using SHA256 or SHA512. It should be enough. Now, you said you want to know their passwords so you can login into their account. You, as the administrator, should have the ability to login as the user without knowing their passwords.
If you need to login as the user then I am guessing you need to change something? Well, an administrator should be able to change users data without having to be logged in as them...
So I can only say fix your system.