Where to securely store certs/keys when using PHP/MySQLI/Apache? - php

I have separate web (Apache/PHP) and database (MySQL) servers using mysqli over an SSL connection working nicely. In the ssl_set() function in the database connection library within the framework, I can specify the path to the keys/pem files as long as it's within the docroot. If the files are outside the docroot, I obviously cannot access them, and the connection fails.
What is the most secure method for storing and accessing mysql client ssl keys outside the apache docroot?
Is there a secure use of "ini_set" whereby I can allow that access "on the fly" and then remove that parameter? Or should I use symlinks?
I'm looking for best practices here. I suppose this question isn't limited to cert keys, but I wanted to make sure you knew my specific use case.
Thanks!

I'm looking for best practices here. I suppose this question isn't limited to cert keys, but I wanted to make sure you knew my specific use case.
This problem gets into a the territory where security experts will split hairs over trade-offs against different threat models, so there is no "one right answer" for secure credential management. However, there are a ton of obviously wrong answers.
Chris Cornutt published an article about securing PHP credentials with Docker that I highly recommend reading for background information about the threats and strategies involved in solving credential management.
In general, psecio/secure_dotenv will solve this problem for most users. This is an open source library for managing credentials that stores them encrypted at-rest.
If you need something fancier (or to integrate with a product, e.g. Vault), you may want to ask a security expert to review your designs and implementations.

Related

Why is soap secure? why not HTTPS?

This question stems from a job interview I had. The interviewer asked me about a website I had built.
I was fresh out of school and was still doing a lot of things wrong because I didn't know any better and
had no one to ask. When I laid out the website for my interviewer on the whiteboard he was surprised that
I didn't use a web service to access my database. He suggested that this was not secure
but didn't go into detail. They thought had never occurred
to me to do this as a security measure and I thought I was wrong for not doing it. My code was all one one page.
No MVC, my php connections and all my php/mysql select, inserts, etc were all written in php on the same file
as my html / javascript and everything else (wrong for various reasons but not the topic at the moment).
My page was protected by https and I thought that was enough. Also looking back on it he may not
have known my database was on the localhost. The confusion in the question steams from my lack of knowledge
at the time and now.
So the real question (I guess) should be, did I need to have a webservice like Soap acting
as an in between my database to make my site secure(even though it was a localhost)? My assumption being that
the soap server would do all of the mysql statements and return the values I was interested in. Or alternatively the SAOP Sever would
get the Mysql database to execute mysq functions and the values (which would I think add real security value).
I thought that because I was using server side php and https that I would be secure
(other than things like a mysql injection but I had other things to account for that like mysql_real_escape_string()
and some other stuff).
In Short
My question is would using soap to separate things between the main page file and the file that
actually did the php mysql select statements on a localhost add any security value vs https. Couldn't I just get the php to
connect and then use the Mysql server to execute some mysql functions with the pages protected with https ? Wouldn’t that be secure ?
Aside from me not using an MVC model can you offer some sage advice on the https vs SOAP?
I am trying to do some self-study in php. I am working in another language now mainly writing scripts.
I have a really passion for php and I want to learn but don't know where to reliably turn.
Thanks
You are mixing the concepts of protecting access to your database, and protecting access to your web service.
You must follow best-practices to protect your database, no matter what web service architecture you use (prevent SQL injection, certainly don't expose credentials, physically separate the DB from the web service server via a firewall, etc.).
If your web service is not meant to be available to the general public, you must separately control access to the web service. Both SOAP and REST provide solid mechanisms to do just that.
SOAP itself does not protect access to files on the server. It provides a mechanism to protect access to the web service.
UPDATE
It is a silly notion to require a web service between a website and a database for "security" purposes. A web service should be thought of as an alternative interface for accessing functionality, not as a security layer.
In fact, unless you hide your web service from the public, hackers will just attack the web service rather than (or in addition to) the website. If you do hide it from public view, you have invested quite a bit of Engineering effort for zero benefit.
From an architectural perspective it is wise to separate data access from the user interface (whether or not the layers run on the same or different machines). In the ASP.Net world, the Repository and Unit of Work patterns are quite common. I'm not sure which patterns are commonly used in PHP. Creating a separate web service for only for DB isolation is certainly not such a pattern.

PHP Security information?

Let's say I have a website where
PHP 5.3 is installed
every output is htmlspecialchars()ed.
PDO and prepared statements are the only way to interact with the database
error_reporting() is off
every request is passed to index.php (front controller) and no direct file access is allowed except for index.php via .htaccess
every input is properly escaped (why should I? i use Prepared statements, how could an user input mess up with my code?)
there's no use of evil()
Is it considered safe? What other things could be fixed to improve security? How could you attack it? Hack it? PHP/Server side is possible to improve security?
Check this page : PHP Security Guide. Most attacks are documented. If after implementing these security checks, you're still hacked, there are high chances that the problem doesn't come from your PHP application.
By the way, as #Jacco stated, there is some wrong stuff on the article I linked to.
Use prepared statements instead of mysql_real_escape_string(), but you already did that.
About salting, follow this answer instead : https://stackoverflow.com/a/401684/851498
Finally, checking ['type'] (for file upload) is unsafe since a malicious user can change this value. Instead, see the suggested solution of this link : http://www.acunetix.com/websitesecurity/upload-forms-threat.htm
I remember when I started web developing, I read allot about sanitizing data, creating numerous mysql users with a subset of permissions for specific queries, etc.
It gets you in the mindset of treating security with code, not with the operating system.
What use is all of this if you connect to your console with telnet, or use ftp with authentication?
I guess I should cut to the point. I think modern open source technologies such as php mysql etc have build up allot of security features, which gave me a false sense of security.
The damage you can do through these technologies is negligible compared to hacking into console with a brute force attack. If I were you I would worry much more about geting a proper firewal and only allowing port 80 or the bare minimum of ports you need. If you enable console access I would only allow your desktop IP... etc.
and make sure if you ever send a password, that it is encrypted through ssl
There is no absolute security guarantee, you can add the following to the answers above:
If you allow file uploads, make sure you do mime checking;
Make sure the public cannot upload an unlimited amount of files to
overload and eventually kill your server;
If you own the server make sure there are no other weak gates to your site, you can spend millions making your site bulletproof to any type of attack, but if someone gains access to it through another website hosted on the same server, you're out of luck;
Use a vulnerability scanner like acunetix, skipfish;
If you own the server make sure you stay up to date with the versions of the software running on your server (PHP/Apache/MySQL). Subscribe to get updates from the vendors;
If the budget allows it, you could offer a bounty to someone to find a security hole in a DEV release of your code;
Use a product like the following: https://www.cloudflare.com/features-security
security is a major concern for any product and it can not be achieved by some finger count policies but they are important so everywhere in the code think the negative possibilities and work against them to prevent them.
other thing you have to do
store sensitive data in encrypted formate in db
clean XSS every user input data
It is important to note that "safe" is a context-based term. It highly depends on your needs, and there are companies out there (I'm looking at you Google) who will not even consider installing PHP at all.
If you are working at a big company, I would recommend hiring the services of professionals.I heard from a friend that this company does sec checkups for all the big companies, which seems likely since they are the people that distribute Kali Linux.
https://www.offensive-security.com/offensive-security-solutions/penetration-testing-services/
There can be multiple other issues as well, such as session problems, sensitive information enumeration, authorization and authentication issues, and lot more. Issues like business logic bypass can not be resolved by traditional secure coding guidelines. However, looking at PHP Security Cheat Sheet and OWASP PHP Security Project would be a great help to understand the big picture of security issues.
You can learn more about exploiting PHP security issues and related attack techniques by solving the PHP security challenges by RIPSTech (https://www.ripstech.com/php-security-calendar-2017/) or by reading their writeups of real-world vulnerabilities found in popular PHP apps (https://www.ripstech.com/security-vulnerability-database/)

PHP: Securing database connection credentials

Just to make sure everyone is on the same page these are the credentials I'm talking about...
$user = 'user';// not actual user, not root either
$pass = 'pass';// not actual password
$server = 'localhost';
$database = mysqli_connect($server,$user,$pass,true|false);
So I'm talking about the passwords used to connect to the database, not the passwords in the database (which for clarification I have hashed with salt and pepper).
I have not read anything that I think remotely suggests you can have 100% foolproof security since obviously the server needs to connect to the database and get the content for visitors 24/7; if I am mistaken I would love to hear how this would be possible.
So let's presume a hacker has root access (or if that does not imply access to the PHP code let's just say then have access to all the PHP source code) and they (in this circumstance) desire to access/modify/etc databases. If we can not prevent them should they have access to the PHP source then we want to slow them down as much as possible. I can keep each site/database connection password in separate files (can as in I'm a few weeks from finishing multi-domain support) for each site and not inside of public_html (obviously). I use serialize and unserialize to store certain variables to ensure certain level of fault tolerance for when the database becomes unavailable on shared hosting (preventing site A from looking and acting like site B and vice-versa) as the database can sometimes become unavailable numerous times a day (my database error logs are written to when the SQL service becomes available again and catches these "away" errors). One thought that has crossed my mind is determining a way to store the passwords in one hash and un-hashing them to be used to connect to the database by PHP though I'd like some opinions about this as well please.
If someone has a suggestion from the database perspective (e.g. having the ability to restrict users to SELECT, INSERT, DELETE, UPDATE, etc and not allowing DROP and TRUNCATE as examples) my primary concern is making sure I am SQL neutral as I plan to eventually migrate from MySQL to PostgreSQL (this may or may not be relevant though if it is better to mention it). I currently use phpMyAdmin and cPanel and phpMyAdmin shows the connected user is not the same as the site's database user names so in that regard I can still use certain commands (DROP and TRUNCATE as examples again) with that user and restrict the SITE user permissions unless I am mistaken for some reason?
Is there a way to configure the context of where the connection credentials are accepted? For clarification a hacker with access to the source code would not be accessing the site the same way legitimate users would.
Another idea that crossed my mind is system based encryption, is there a near-universal (as in on every or almost every LAMP web host setup) web-hosting technique where the system can read/write the file through Apache that would introduce a new layer that a hacker would have to determine a way to circumvent?
I am using different passwords for each user of course.
I currently am on shared hosting though hopefully my setup will scale upwards to dedicated hosting eventually.
So what are the thoughts on my security concepts and what other concepts could I try out to make my database connection credentials more secure?
Clarification: I am looking for ideas that I can pursue. If there is disagreement with any of the suggestions please ask for clarification and explain your concern in place of debating a given approach as I may or may not have even considered let alone begun to pursue a given concept. Thanks!
There is little to be gained from trying to slow down an intruder that already has root access to your system. Even if you manage to hide the credentials well enough to discourage them, they already have access to your system and can wreak havoc in a million ways including modifying the code to do whatever they wish.
Your best bet is to focus on preventing the baddies from ever penetrating your outer defenses, worry about the rest only after you've made sure you did everything you can to keep them at the gates.
Having said that, restricting database user accounts to only a certain subset of privileges is definitely not a bad thing to do if your architecture allows it.
As code_burgar says, once your box gives root, it's too late. That being said, I have had to implement additional security mesures on a project I was involved with a while back. The solution to store config files in an encrypted partition so that people with direct access to the machine can't pull the passwords off by connecting the drive to another PC. Of course this was in addition to file system permissions so people can't read the file from inside the OS itself.
Another detail worth bringing up, if you are really paranoid on security:
$user = 'user';// not actual user, not root either
$pass = 'pass';// not actual password
$server = 'localhost';
$database = mysql_connect($server,$user,$pass,true|false);
unset($user, $pass, $server); // Flush from memory.
You can unset the critical variables after use, ensuring they cannot be var_dumped or retrieved from memory.
Good-luck, hope that helps.
You want to approach security in layers. Yes, if an attacker has root access, you're in a very bad place - but that doesn't mean you shouldn't protect yourself against lower levels of penetration. Most of these recommendations may be hard to do on shared hosting...
Assuming you're using a decent hosting provider, and recent versions of LAMP, the effort required to gain root access is substantial - unless you're a very lucrative target, it's not your biggest worry.
I'll assume you harden your server and infrastructure appropriately, and check they're configured correctly. You also need to switch off services you don't need - e.g. if you have an FTP server running, an attacker who can brute force a password doesn't need root to get in.
The first thing you should probably do is make sure that the application code has no vulnerabilities, and that you have a strong password policy. Most "hacks" are not the result of evil geniuses worrying away at your server for months until they have "root" - they are the result of silly mistakes (e.g. SQL injection), or weak password ("admin/admin" anyone?).
Next, you want to make sure that if your webserver is compromised - but not at "root" level - you can prevent the attacker from executing arbitrary SQL scripts. This means restricting the permissions of your web server to "read and execute" if at all possible so they can't upload new PHP files. It also means removing things like CPanel and phpMyAdmin - an attacker who can compromise your production server could compromise those apps, and steal passwords from you (run them on a different server if you need them).
It's definitely worth looking at the way your database permissions are set up - though this can be hard, and may not yield much additional security. At the very least, create a "web user" for each client, and grant that user only "insert, update and delete" on their own database.
I have found a solution for PHP(Linux) On the root create a directory say db and create a class and define all the database connection variables and access methods in a class say DBConnection.php now your website is example.com you are storing your files in public_html directory create a php file under this directory to connect and do all database operations and include DBConnection.php file using following statement
require('../db/DBConnection.php');
this file cannot be accessed using 'www.example.com/db/DBConnection.php'
you can try this on your web site.

How do I verify users of my PHP application?

While installing an application onto a client's server, I would like to make sure that the client (or a future developer for them, etc) does not copy my application and place it on other domains/servers/local servers.
How can I verify that my application is running on the server I installed it on? I do not want any substantial lag in the script every time it runs, so I assume a 'handshake' method is not appropriate.
I was thinking the script could request a PHP page on my own server every time it runs. This could send my server their server info and domain name, which my script can check against a database of accepted clients. If the request is invalid, my server handles the work of emailing me the details so I can follow it up. This should not slow down the client's script as it isn't expecting a response, and will still operate on their 'invalid' server until I can investigate this and follow it up with them personally.
If this is the best method (or if there is better), what PHP call should I be making to request my server's script? file_get_contents, curl and similar seem to always retrieve the response, which I don't need.
UPDATE
Thank you all for your responses. I completely understand that PHP is open source and should be freely available to edit. I should have stated more clearly initially, but my intentions were for this verification method to assist me in finding anyone breaching my license agreement. The application is covered under a license, but I would also like to include this check so that I can monitor an initial misuse of my application.
Hence, somebody may still breach my license and it would most likely go unnoticed, but if I implement this script I have the advantage of any 'lazy robbers' who don't break apart my application and remove the verifier before ripping it.
Does this justify the use of such a script? If so, is cURL my best option?
Any checking code for verification is easily replaced with a return true;. Look at the faq at https://stackoverflow.com/tags/php/info :
Q. Can I protect my PHP code from theft? If so, how?
A. There is no effective technical solution to protect, encode or encrypt PHP source code. There are many products that offer some levels of protection, but all can be broken with time and effort. Your best option is not a technical solution, but a legal solution in the form of a license agreement.
You get a legal agreement and sue everyone.
SaaS is your friend. Host the application on your own secure servers, and charge a license fee for your customers to access it.
imo its worth checking out some joomla extensions that do this. There a few different implementations, some check the domain and validate it before executing, most are encrypted, along with a domain validation. I remember sakic's url sef extension used to do this. There are quite a few more commercial extensions that use the same thing. Apart from that I cant think of another way.Probably another good idea is to have a good license in place and a good lawyer....
Short answer: This can't be done.
Long answer: Whatever protection you put in your code, it can be removed with little difficulty by anyone with some experience in PHP. Even if the code is encoded with something like ionCube or Zend Guard, this too can be decoded with relative ease.
Your only option is to protect your intellectual property by actively pursuing copyright infringers. Even this is not foolproof, as our folks from RIAA and MPAA know very well. In this day and age, I'd say this is not a solvable problem.
You could integrate phone-home behavior into your software but you should probably consult a lawyer to discuss privacy issues about that and to work out privacy guidelines and terms of use for your clients' usage license.
One thing to be careful about is the data you send (and the way you send it, i.e. securely encrypted or not) to identify the client who is illegally using your product because it could potentially be used to compromise your client's infrastructure or for spying on your client.
Regarding your phone-home function, be warned that the client could just locate and remove it, so using a PHP obfuscator or compiler might provide some additional protection against this (though any sufficiently determined PHP developer could probably disable this). Note that your protection will only act as a deterrent aimed to make the cost of circumvention
approach or exceed the cost for legal use.
EDIT:
As poke wrote in the question comment, you could move parts of your code outside the software installed at your client's site to your servers but this may backfire when your servers are unreachable for some reason (e.g. for maintenance).
In the end, I think that customer satisfaction should be valued higher than protecting your software from the customer, i.e. try to avoid protections that are likely to make your customers angry.
You could encode it and hard code a license file that would allow it to only work on the domain it was intended for (e.g. use ioncube or zend to encode a file that checks if the HTTP HOST is the intended domain without doing a handshake). You could then make that file required in all other files (if everything was encoded).

UNIX wrapper in PHP

For a simple web application, I'd like to be able to take advantage of several UNIX features that are stable, have a long history, and are well proven in production, rather than having to write my own code. Take users, for example. Rather than having an entire user, group, permission infrastructure in my webapp, I'd like to be able to simply piggyback on top of the equivalent features of UNIX.
Is there a PHP library that will allow me to register users, log them in, manage permissions, etc. ?
It's really not a good idea to fumble around with the user and permission settings of the actual system that is hosting your site. If you want to protect individual directories of your site, you're better off using .htaccess files. If OTOH you're working with virtual URLs, you'll have a hard time mapping the UNIX directory permissions to them anyway.
Based on your comment to deceze's answer, are you looking for something like PHP's filesystem functions?
Then, there is system and its related functions, which gives access to Unix commands, but I'd recommend other ways of doing things if possible.
Edit: In response to the comments about needing user and group functionality:
Firstly, in case your plan is to let web users have access to the whole file system (or even just their regular log in directories), I just want to advise against that - lots of security concerns (eg. if someone else gets into a user's account, they could delete everything to which they have access).
The little experience I have with handling users in PHP was in some beginner level training. In that class, we had our users in an SQL database and used sessions. We didn't use SSL, but I'd advise some sort of crypto when passing passwords around.
If you're using Apache, it can handle the authentication for you. Other server software can probably do the same, but Apache is all I've ever worked with. I can't address whether Apache can handle sessions itself and don't have the time to research it right now.
If php or your webserver is running with root rights it should be no problem to use this functions.
For security reasons I would strongly recommend to reimplement these things or using any existing php library instead!!
It seems there are standard functions for interfacing with Kerberos or Radius in php.
These both have a long history and are well proven in production, while being separate from the system users.

Categories