Forum Moderators: coopster

Message Too Old, No Replies

Storing MySQL connection details in separate JSON file - safe?

         

D3mon

10:51 am on Oct 13, 2020 (gmt 0)

10+ Year Member



Having just completed the task of storing and retrieving my MySQL database connection details from a separate JSON file, I've become concerned that, as a plain text file, the JSON could more easily be accessed and viewed.

I have the file (and the folder it is in) protected by .htaccess, but for some reason it makes me nervous. Is it bad practice to store these details in files other than .php?

not2easy

1:14 pm on Oct 13, 2020 (gmt 0)

WebmasterWorld Administrator 10+ Year Member Top Contributors Of The Month



If the .htaccess file that protects it is in the root directory and there is no other .htaccess file within the folder where the script is stored, then it 'should' be safe. Treat it as recommended for WP users' wp-config.php file and set permissions to limit the chances. You could 'double lock' it with file permissions, say, 600 to make it less accessible.

D3mon

1:19 pm on Oct 13, 2020 (gmt 0)

10+ Year Member



That's very reassuring thank you. I'll look into setting the permissions with some testing to avoid rendering it entirely useless to my own scripts.

w3dk

3:23 pm on Oct 13, 2020 (gmt 0)

10+ Year Member Top Contributors Of The Month



It would be better to store the config file "above" (or "outside") the document root, rather than inside the public URL space. You are then not reliant on mod_authz..., .htaccess or extra permissions.

Is it bad practice to store these details in files other than .php?


Not necessarily. The important point is that these settings should be isolated in their own separate file, outside of the main source code. (And outside of version control.)

A potential issue with using a ".php" file is (depending on who is intended to update this file - perhaps a non-developer) is the introduction of bugs/syntax errors. Because the file is simply include()'d it can break the system. A separate config file (JSON, INI, etc.) is parsed by the application - it is easier by default to fail gracefully.

not2easy: If the .htaccess file that protects it is in the root directory and there is no other .htaccess file within the folder where the script is stored, then it 'should' be safe.


I'm curious why you stipulated a .htaccess file in the root directory? It would arguably be preferable to have a separate .htaccess file in the directory you are protecting (with a single "Require all denied" directive), since this should override any directives in the parent .htaccess file.

not2easy

4:44 pm on Oct 13, 2020 (gmt 0)

WebmasterWorld Administrator 10+ Year Member Top Contributors Of The Month



w3dk: I'm curious why you stipulated a .htaccess file in the root directory?
I was not stipulating that a root directory htaccess file would be better (or worse) merely that it would make a difference because the OP mentions
I have the file (and the folder it is in) protected by .htaccess
without mentioning where that .htaccess file was at.

D3mon

5:32 pm on Oct 13, 2020 (gmt 0)

10+ Year Member



Sorry guys, I should have been more clear in case this could benefit others.

I'm in the process of building a simplified CMS/framework/ecommerce to advance my general web tech knowledge (and as an aside, to help out a friend who is starting his own online business after being made redundant during these difficult times.) The primary objectives of this project are speed and simplicity for the less technically accomplished.

Anyhoo, my aim was to move the MySQL config data out of one of my class files (.php) and into a simpler format file (.json) in much the same way that my editor, Visual Studio Code does. Having achieved that goal, I found myself debating where in the folder structure to store this salient information. A non-public folder was a choice but seemed to move me too far away from the 'simplicity' parameter of my project.

Given that the vast majority of my code resides in folders encapsulated in an 'app' folder (placed in the web root), inside the app folder now resides a config folder, which in turn contains a .json file containing the 'crown jewels' as it were.

Thus far then, I have an .htaccess file in the webroot which provides all the necessary functionality I need, but also crucially blocks remote access to itself as follows:

...
<Files .htaccess>
order allow,deny
deny from all
</Files>
...

My project also has a further .htaccess file in the [app] folder, simply containing:

Deny from all
ErrorDocument 500

... which I have assumed has blocked remote access to every file and folder inside [app].

And then inside [app] is the [config] folder, containing my json file and yet another .htaccess file:

Deny from all
ErrorDocument 500

Further to all that, and with thanks to the advice given here, I've managed to set the json file permissions to 600 (removing 'world' read permissions) without crashing the system.

Hopefully now, this should provide some reasonable protection for my (now simpler to edit) sensitive connection details.

Thanks everyone.

w3dk

7:27 pm on Oct 13, 2020 (gmt 0)

10+ Year Member Top Contributors Of The Month




order allow,deny
deny from all


Note that this is for Apache 2.2 (and earlier). Whilst this still "works" on Apache 2.4, it is formerly deprecated (and consequently will be removed altogether in future versions). On Apache 2.4 this should be replaced with the corresponding "Require" directive. ie. "Require all denied".


ErrorDocument 500


What is the intention behind this? This is actually invalid as written and will (ironically) "break" with a 500 response (nothing to do with the fact you are referencing the 500 ErrorDocument, just that the syntax is wholly invalid). Maybe that is the intention (but it's "dangerous" to rely on invalid syntax)? But it also renders the "Deny from all" directive redundant. (?)


The primary objectives of this project are speed and simplicity for the less technically accomplished.


Ok. This is perhaps just personal preference, but I think it's easier to be able to say... "you don't need to change anything in the [app] folder". Anything that is user-editable should be outside the [app] folder. (?)

I'm in the process of building a simplified CMS/framework/ecommerce


Just a thought... an "ecommerce" system is more likely to be on a dedicated server where ".htaccess" files are disabled (for performance and security and because they are not really needed when you have your own server).

It shouldn't really matter if files within [app] are accessed directly and nothing "bad" should happen if they are. However, [app/config] should not be accessible, so directives would need to be added to the server config to prevent this.

Of course, you could hide your JSON config file behind a PHP facade. eg. "config.json.php" which would then contain:


<?php exit() ?>
JSON data here...


Any direct request gets nothing, but you do need to remember to skip the first line of the file when parsing your JSON data.


<Files .htaccess>
order allow,deny
deny from all
</Files>


Aside: I see this code snippet batted around, however, this really "should" be superfluous in .htaccess itself. Any Apache server should already be blocking ".ht*" (to include ".htpasswd" as well) files at the server level - out of the box.

D3mon

8:11 am on Oct 14, 2020 (gmt 0)

10+ Year Member



Top tips! thank you! It's perhaps too easy to take snippets from the 'net and assume they are current/relevant.

The errordocument line was originally: ErrorDocument "nothing here" ... which I felt gave a greater indication that there actually was something there than not. My fudged workaround (as shown) was to attempt to get it to return a more standard 500 error/page and as you say, seemed to work to my unfamiliar eyes.

In all my years as a web developer I've never worked on a dedicated server, only shared hosting. Launching an ecommerce site on an almost zero budget doesn't really fit with the cost of dedicated hosting.

I must find a way of getting rid of the first line of the JSON file. I like that tip a lot. :)

D3mon

4:59 pm on Oct 14, 2020 (gmt 0)

10+ Year Member



Something like this worked for me:


$configFile = file_get_contents('settings.json.php');
$lines = explode("?>", $configFile);
$jsonContent = $lines[1];
$settings = json_decode($jsonContent, True);

extract($settings);

w3dk

12:38 am on Oct 15, 2020 (gmt 0)

10+ Year Member Top Contributors Of The Month



The errordocument line was originally: ErrorDocument "nothing here" ... which I felt gave a greater indication that there actually was something there than not.


That would have also resulted in a 500 error, since it is syntactically invalid. Maybe you meant:


ErrorDocument 403 "nothing here"


Which would have displayed the string "nothing here" when serving a 403 Forbidden (as a result of the "Deny from all" or "Require all denied" directive). But note it would have still been a 403. Personally, I would remove the ErrorDocument directive and let it default to your main ErrorDocument (or 403 Apache default). You could specifically check the URL in your custom error document to serve a custom message for these URLs if required.

To specifically return a "404 Not Found" (or 500 Internal Server Error) you could override the default 403 response. Or specifically trigger a response using a mod_alias "Redirect" or mod_rewrite "RewriteRule" directive, instead of using mod_authz_core. But it's just a smoke screen. And I wouldn't have said a 500 error is really a desirable response here - it's really telling the client that the request did something and broke the server!

For example:


# Unconditional 404 Not Found for all requests
Redirect 404 /

RewriteEngine On
RewriteRule ^ - [R=404]

# Unconditional 500 Internal Server Error for all requests
Redirect 500 /

RewriteEngine On
RewriteRule ^ - [R=500]


You "might" need to implement some exceptions to serve your custom error document.

D3mon

11:04 am on Oct 15, 2020 (gmt 0)

10+ Year Member



Ah yes I see. Thank you again! :)