I am interested to know what is considered more secure out of
include $_SERVER['DOCUMENT_ROOT'] . '/config/special.php';
and
include '../config/special.php';
I see a lot of answers on Stack Overflow and elsewhere on the web that say to store data outside the document root. I have also seen a lot of tutorials that say to include a file in php do something like
include $_SERVER['DOCUMENT_ROOT'] . '/config/special.php';
Would it be ok to do the above if you change the permissions on the folder to something like drwxr-x-wx so you get forbidden if you are trying to access the path in the url (or is this still considered a risk) or would it be better to move my config above my root folder like the below.
include '../config/special.php';
The answer is: "how secure is the rest of your server"?
If you forbid access to the directory from Apache remote calls, you've solved half of the issue regardless of where you store your files. However, this isn't the silver bullet of security. If it was, people would know about it! (I proved this where I work a month ago - one of the lead devs thought that storing stuff in a non-webroot subfolder would make everything secure. Little did he know about the file explorer that he built, and more importantly, how it could take ../ as a parameter and work accordingly... 30s later, database got dumped - on a dev environment).
The key to security is to harden everything. If you allow users to read files, make sure to ban the .. and ... operators, and anything related to it, to prevent them from traversing up the directory chain. Prevent outside users from reading the file (.htaccess with Apache), and that should deter most people.
Depending on how you sanitize the up-one and up-two chains, however, you might end up with more issues. Take the example of my co-worker again: after the dump, he decided to operate these replacements:
.. => .
... => .
(Order is important)
Little did he know about me putting in .... . First regexp would turn this into .., second regexp would do nothing. Bingo, database got dumped. Again.
On a broader more succinct note if you are looking for a straight forward answer to your PHP question.
None of the above are or are not secure. Simply including a file is a normal and warranted action in any PHP application and security would not be effected by any of the above methods.
If you want to read more about security I suggest reading more about how to ensure your server / application is secure.
Perhaps this could be a nice read.
http://www.ibm.com/developerworks/opensource/library/os-php-secure-apps/index.html
Related
I'm trying to connect to my database, but I changed my database's root password in the interest of security. However, in order to connect to the database and use PDO, I apparently have to pass my password in the php, which obviously is not good for security:
$hsdbc = new PDO('mysql:dbname=hs database;host=127.0.0.1;charset=utf8', 'root','passwordgoeshere');
$hsdbc->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$hsdbc->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
Am I being stupid and that because it's PHP no-one but the person who views the actual file will be able to see the password, or is there some way to do it without passing the password in the file.
Generally speaking it's not bad practice to have connection strings in files that are not user facing. If you don't want to have your personal password in the php file, then you can create a new mysql user for php.
You can also restrict the user's IP address in MySQL to the server hosting your php scripts. This way if a nefarious person browsing the web somehow was able to see the database password, they would have more difficulty accessing it.
People are not able to just go and read into your files. They should be safe on the place where you host it. They are only able to get into to files if they are able to get into the place when you host your stuff. Which should not be possible if they don't have the info to get there.(which should only be known to you).
This is not just for PDO. but also my mysql and mysqli to do it like this
Going to extend SupSon (SC2 Select fan?)'s answer:
PHP itself is server coded language.
There are only 3 ways (maybe more if someone want to add to it) that code can be shown to an outside user:
By having an unsecure .htaccess file that shows php file as text
file (then you should move servers at that point because normally
this doesn't happen)
Somehow your operating on debug mode and something in your page
triggers this mode and you get a whole bunch of PHP code gets shown
FTP/SSH access to your .php file (then you have more than a PDO
problem in your hands)
So if one of these cases is happening, coding into a .php file your username/password won't be a breach in security.
I have seen websites that expose PHP code, when the Apache type handler for PHP becomes unconfigured by accident. Then the code in .php files is displayed instead of executed. There's also an Apache type handler to display PHP source deliberately, though this is not usually configured.
To avoid this vulnerability, it's a good practice to put your sensitive PHP code outside your htdocs directory. Instead, put in your htdocs directory a minimal PHP script that loads the rest of the code using include() or require().
An alternative is to put your MySQL credentials in a config file instead of PHP code at all. For example, the file format used by /etc/my.cnf and $HOME/.my.cnf is readable by the PHP function parse_ini_file(). It's easy to store your MySQL password outside of your code this way.
For example, read user and password from the [mysql] or [client] sections of /etc/my.cnf:
$ini = parse_ini_file("/etc/my.cnf", true);
if (array_key_exists("mysql", $ini)) {
$connect_opts = array_merge($connect_opts, $ini["mysql"]);
} else if (array_key_exists("client", $ini)) {
$connect_opts = array_merge($connect_opts, $ini["client"]);
}
$pdo = new PDO($dsn, $connect_opts["user"], $connect_opts["password"]);
Yes it seems insecure at first, but once you get the hang of it and know how to manage your files to minimize potential security breaches, you can minimize the risks associated with having passwords stored in plain text in potentially publicly exposed spaces. Yet AFAIK PDO doesn't even let you form a connection without supplying a password. The solutions are a combination of what everyone has said and then some. Here's my quick guide for what I do.
Separate SQL users for separate purposes (minimizes damage from SQL injection or hacked accounts):
There should be a PHP-specific user for each table you need to access. That user will be granted only enough rights to handle as much of that table that he needs to, if it doesn't need to delete then don't grant it delete. If it doesn't need to select then don't grant it select. It seems fussy but very quickly you'll have a copy-paste template to make the users, give them the right(s) they need, and document it. If there's a joined table, you'll want to also grant the user access to that table also, naturally.
-- a single user account for a specific purpose:
CREATE USER 'usermanager'#'localhost' IDENTIFIED BY '5765FDJk545j4kl3';
-- You might not want to give access to all three here:
GRANT SELECT, UPDATE, INSERT ON db.users to 'usermanager'#'localhost';
The purpose of this is so that if you have a bug in your code that lets people SQL inject, they won't be able to cause any harm beyond the scope of what that role can do.
Stupid mistake can reveal PHP code and files if left in-directory, move them out:
Never mind revealing the source code, even just trying to access php files "out of order" can be destructive.
Move as many files to an out-of-scope directory as possible. Then call them like so:
require_once('../lib/sql_connectors.php');
This should escape your html / webdir and you should hopefully be able to store all sorts of fun stuff outside the scope of what a stupid admin mistake could reveal.
You can even have a php file that gets pictures and videos from outside your webdir, that's how streaming sites protect their resources and also conduct php-based authentication to file access. To learn how to do that you'll want to look up assigning your own etag headers to make sure browsers cache your php-retrieved files otherwise you'll have a very busy server, here's a short introduction.
Block wrongful access to PHP that are left in-directory:
All of your in-directory PHP files can be protected by checking that the $_SERVER['REQUEST_URI'] isn't itself. If it is, you can have a function called show404() that loads the 404.php page and dies there or just directly call your 404.php with an include. That way, even if you have hackers trying to brute force your php files they'll never see them because they'll get 404 errors (fools the bots) and they'll see the 404 page (fools the humans).
I avoid using .php in any publicly visible paths, to do that, I make rewrite rules in my .htaccess files that look like this:
RewriteEngine On
RewriteRule ^login$ login.php [L,QSA]
The L makes it stop running other rules.
The QSA preserves the $_GET tags.
The first lines of code for every file (consider prepending) could be:
// they should be connecting via a redirect, not directly:
$fileName = basename(__FILE__);
if ($_SERVER['REQUEST_URI'] === '/' . $fileName) {
error_log('Security Warning: [' . $_SERVER['REMOTE_ADDR'] . '] might be trying to scrape for PHP code. URI: [' . $_SERVER['REQUEST_URI'] . ']');
include('404.php'); // should point to your 404 ErrorDocument
exit();
}
// redirect to actual file
include('../hidden/php/' . $fileName);
In this example, assuming you have the redirect in your .htaccess, a login.php with the code above, and a login.php in your hidden directory, the user would experience the following two scenarios: attempt to connect to '/login' and see the hidden '/login.php' page; attempt to connect to the visible '/login.php' directly and get a 404 error.
Those are the 3 big things, lots of small limited accounts to minimize damage in case of security failure, keep all possible files outside the web directory, and make all in-directory php files produce an error letting only non-php links access them.
Ok I get a script from: http://abeautifulsite.net/blog/2008/03/jquery-file-tree/
Its a directory listing script. I am having troubles with it. It works out of the box no problems per say other than the put fact that it goes way back into the system structure then I am allowed to even see some how.
The person that made the script has this one line that throws me off and I can't make heads of tales of it per say.
file_exists($root . $_POST['dir'])
I've never seen $root in that context before. Nor is it defined anywhere in the script from what I can tell. So is that a valid thing? If not can anyone tell me how I can use this script beneficially to just displaying directories starting at a specific directory. The document I point to with the above link shows an example, but it doesn't seem to mean anything to the scripts workings.
On the other hand if someone knows of a canned script thats very similar in nature I'd be happy to give that a look too. But I'd really like to edit this one to work the way I want it to work so any help would be appreciated.
an example of how far its going back can be found at http://domainsvault.com/tree/
I say its going far back because I don't even have access to those directories through my ftp.. its a shared system.. hostgator..
*EDIT* Thanks Everyone for the input, this essentially what I was afraid of hearing. It was hopped that we could skip reinventing the wheel by using this concept. But its appearing more so than not that its basically a bricked concept and far from worth using and attempting to tamper with. It'd likely be a lot more easy for me to build something from scratch than have to deal with this. This was just one of those canned scripts you find it looks ascetically pleasing to the eye, and you hope for the best. Didn't turn out to be the case, thanks again all.
file_exists($root . $_POST['dir'])
Run away.
This connector script does no checking on what paths you pass to it, so it's perfectly possible to escape the root (which, yes, you're supposed to set manually) and browse any files on your server that the web user has access to.
Also, it fails to do URL-escaping, and mangles Unicode through inadvisable use of htmlentities. This will make files with various punctuation or non-ASCII characters in fail.
This is a shonky and insecure script. Do not deploy it.
$root is a user-defined variable. It should be defined somewhere in the script - it may be a global. The script can still work if the variable doesn't exist (it might have been deleted in a previous code refactor), in that case you should just delete the variable from the line you copied here.
I think $root means $_SERVER[ 'DOCUMENT_ROOT']
you can defined as
$root=$_SERVER[ 'DOCUMENT_ROOT']
at the beginning
I've been told that it is unsecure to make database connections inside a PHP includes. For example If I have a login page and add an "include('process.php')" at the top of the page that has a database connection, is that unsecure?
For example If I have a login page and add an "include('process.php')" at the top of the page that has a database connection, is that unsecure?
No.
Maybe the person who told you this was talking about something else - like including a file using a dynamic value coming from a GET parameter, or using remote http:// includes, or as #AlienWebguy mentions, having the password include inside the web root. But using includes in itself is not insecure.
It's only insecure if you are storing your passwords literally in your PHP files. They should be declared outside of the web root. That being said, the lack of security is not due to the use of the include() function.
In and of itself, no, it is not insecure. How it's implemented inside the include is of course a different story.
That's the way I've always done it. I make sure that the include is in a different directory that has open permisions and that the directory your writing in has locked permisions. Hopefully that makes sense.
This question is way too broad to get a good answer from anyone. Short answer is no, there's nothing inherently insecure about including a file that connects to a database. However, if you write code that isn't written properly, then yes it may be insecure to do this.
Since using "include('process.php')" is exactly the same as pasting 'process.php' into the code of the other file, that should not be, per se, a security issue. The insecurity could be in your code, not in the fact the you use the "include". In fact, it could maybe improve the safety of your code, due the reuse.
I am trying to trace the flow of execution in some legacy code. We have a report being accessed with
http://site.com/?nq=showreport&action=view
This is the puzzle:
in index.php there is no $_GET['nq'] or $_GET['action'] (and no
$_REQUEST either),
index.php, or any sources it includes, do not include showreport.php,
in .htaccess there is no url-rewriting
yet, showreport.php gets executed.
I have access to cPanel (but no apache config file) on the server and this is live code I cannot take any liberty with.
What could be making this happen? Where should I look?
Update
Funny thing - sent the client a link to this question in a status update to keep him in the loop; minutes latter all access was revoked and client informed me that the project is cancelled. I believe I have taken enough care not to leave any traces to where the code actually is ...
I am relieved this has been taken off me now, but I am also itching to know what it was!
Thank you everybody for your time and help.
There are "a hundreds" ways to parse a URL - in various layers (system, httpd server, CGI script). So it's not possible to answer your question specifically with the information you have got provided.
You leave a quite distinct hint "legacy code". I assume what you mean is, you don't want to fully read the code, understand it even that much to locate the piece of the application in question that is parsing that parameter.
It would be good however if you leave some hints "how legacy" that code is: Age, PHP version targeted etc. This can help.
It was not always that $_GET was used to access these values (same is true for $_REQUEST, they are cousins).
Let's take a look in the PHP 3 manual Mirror:
HTTP_GET_VARS
An associative array of variables passed to the current script via the HTTP GET method.
Is the script making use of this array probably? That's just a guess, this was a valid method to access these parameter for quite some time.
Anyway, this must not be what you search for. There was this often misunderstood and mis-used (literally abused) feature called register globals PHP Manual in PHP. So you might just be searching for $nq.
Next to that, there's always the request uri and apache / environment / cgi variables. See the link to the PHP 3 manual above it lists many of those. Compare this with the current manual to get a broad understanding.
In any case, you might have grep or a multi file search available (Eclipse has a nice build in one if you need to inspect legacy code inside some IDE).
So in the end of the day you might just look for a string like nq, 'nq', "nq" or $nq. Then check what this search brings up. String based search is a good entry into a codebase you don't know at all.
I’d install xdebug and use its function trace to look piece by piece what it is doing.
EDIT:
Okay, just an idea, but... Maybe your application is some kind of include hell like application I’m sometimes forced to mess at work? One file includes another, it includes another and that includes original file again... So maybe your index file includes some file that eventually causes this file to get included?
Another EDIT:
Or, sometimes application devs didn’t know what is a $_GET variable and parsed the urls themselves -> doing manual includes based to based urls.
I don't know how it works, but I know that Wordpress/Silverstipe is using is own url-rewriting to parse url to find posts/tags/etc. So the url parsing maybe done in a PHP script.
Check your config files (php.ini and .htaccess), you may have auto_prepend_file set.
check your crontab, [sorry I don't know where you would find it in cpanel]
- does the script fire at a specific time or can you see it definitely fires only when you request a specific page?
-sean
EDIT:
If crontab is out, take a look at index.php [and it's includes] and look for code that either loops over the url parameters without specifically noting "nq" and anything that might be parsing the query string [probably something like: $_SERVER['QUERY_STRING'] ]
-sean
You should give debug_backtrace() (or debug_print_backtrace() a try. The output is similar to the output of an Exception-stacktrace, thus it should help you to find out, what is called when and from where. If you don't have the possibility to run the application on a local development system, make sure, that nobody else can see the output
Are you sure that you are looking at the right config or server? If you go the url above you get an error page that seems to indicate that the server is actually a microsoft iis server and not an apache one.
I try to read Claroline source code to learn from their coding.
In index.php file, at the first line of code, they write
unset($includePath); // prevent hacking
You can see full claroline source code from here.
They commented that the line is used to prevent hacking..
I have no idea why should they unset $includePath while the variable is never defined before that line..
What is the purpose of that line of code do actually, and what hacking type that they means?
I have not looked at the source myself, but a bit of searches gives the following kind of security advisory :
Claroline mambo.inc.php and postnuke.inc.php "includePath" file include
Note that this relies on register_globals being enabled, which :
is not the default : it's been disabled by default for a very long time (since PHP 4.2.0)
is bad practice (unsafe ^^ as it allows anyone to inject variables into the PHP scripts ; which is why this one, in this case, is unset "to prevent hacking" )
The variable might not be set in code before that point, but if register_globals is turned on, it could be set in the URL by a malicious user.
It sounds like you're mostly looking for educational info, so here's a wee explanation of what register_globals used to do ... why it was there ... and why it's not any more (and you should never turn it on).
Variables come in via the $_GET and $_POST (or $_REQUEST) arrays ... what register_globals did, was make programming easier, by taking all the elements of these arrays, and putting them in the global namespace - i.e., making "regular" global variables out of them - so $_GET['includes'] could very easily be referenced simply as $includes.
This was in the happy days of the intarweb when the internet hadn't proliferated nearly as much as it has now, the technology wasn't so well know, there were fewer people who knew how to hack sites, and no one was writing worms that would automatically hack sites.
It was terribly insecure - because if a lazy programmer hadn't bothered to initialize all variables properly (e.g., checking if $includes is set, and then using it, before it's properly initialized), any of these improperly initialized variables could be set to whatever a hacker wanted. PHP was fairly new then, and many hobbyists were writing code - frequently also doing things like forgetting to properly escape variables in SQL queries. So one security flaw was usually easy to follow up with another one, allowing a hacker (or automated script) to gain deeper and deeper levels of access.
Around 2001 or so, people began very seriously warning about the consequences of register_globals - so this is a rather old issue, but it's still good to be on the lookout, especially with applications that don't have a solid reputation for security.
héhé it's a long story.
In fact in early "naive" version of claroline, Security was not really a target ;-)
$includePath was compute in init to buil all others paths of claroline.
With servers configured with register global=on, it's was a very easy way to hack.
ie : include($includePath."/lib/pager.lib.php");
This simple line was a "patch".
as require '../../../../inc/claro_init_global.inc.php';is included in all.
Conclusion : Claroline is an old code started in php4, with script writed for php3, secure (now) but old. The style is not a good inspiration for "modern" code :-)
Secure claroline was a great adventure -) Mathieu has done most of correction.
I remeber they work more than one month to be comptabile with register global off (I mean it 7y ago)