If I have a http server with various HTML pages and various PHP (or other) scripts, then If I try to view the code (as in Chrome's View source tool) then the PHP code is not shown, which is just as well. I want to know how secure from prying eyes is the code? Would a password hardcoded into the script be safe?
The only time your PHP code could become exposed is if the script somehow becomes treated as "not-PHP" and gets served up as raw text. If your server configuration is correct, then the code is 'safe' from web-based leakage.
That being said, it is best to put critical information that should remain private (usersnames/passwords, config variables, database DSNs, etc...) in a separate file that's kept OUTSIDE of the site's document root. That way, even if PHP becomes corrupted/disabled on the server, all a user would see is
<?php
include('critical_data_here.php');
?>
and not
<?php
$username = 'root';
$password = 'password';
$lotto_ticket_worth_50million = 'under the left couch cushion at 221B Baker Street';
?>
It's never 100% safe to keep passwords, especially on your server.
If you have to keep passwords in script - keep them in files, which placed not in public directory (can not be accessed by user in browser).
<?php
$password = "password";
?>
is save until you've got PHP module loaded.
<span>$password = "password";</span>
is not secure and will not work
Related
I’m looking for a best-practice on storing database credentials for use with PDO.
My DB is stored on GoDaddy, and has a couple of hundred users (maybe).
I recently converted from using mysql_* to PDO and after much Googling for an answer I’ve come to the conclusion that no clear, concise method exists.
Currently I use a config.inc file that stores the credentials as;
<?php
$strHostName = “10.10.10.10”;
$strDbName = “dbname”;
$strUserName = “dbuser”;
$strPassword = “xxx***xxx”;
?>
I do the following in my code;
<?
….stufff
require_once(‘config.inc’);
$db_found = new PDO("mysql:host=$strHostName;dbname=$strDbName;charset=utf8", $strUserName, $strPassword, array(PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
…lots more stuff
?>
This works fine but I’m concerned about the security of the config.inc file. Is there a preferred method to do this?
Thanks…
I'm not sure how this works really as I haven't tried it, but learned about it the other day so I thought I'd share.
With GoDaddy you can point your primary domain name at a sub-directory, therefore creating a new document root before it, so to speak.
For example, create a new directory called 'application' in your root directory, upload your application's files there and point your domain there (You may need to remove the domain name first and then add it again with the specified directory). You can then include files - your database credentials for example - from before your new document root, which is now not available to the public but available to your application.
NEW STRUCTURE
DB Credentials:
/home/www/html/someSite/dbCredentials.php
Your Website (where primary domain is now pointed):
/home/www/html/someSite/application/index.php
EXAMPLE:
In dbCredentials.php add your credentials:
<?php
$strHostName = “10.10.10.10”;
$strDbName = “dbname”;
$strUserName = “dbuser”;
$strPassword = “xxx***xxx”;
?>
On your web page, include the file and use variables as normal:
<?php
require_once ('/home/www/html/someSite/dbCredentials.php');
$db_found = new PDO("mysql:host=$strHostName..........);
?>
SOURCE:
http://support.godaddy.com/help/article/4175/specifying-a-new-default-document-root-on-your-hosting-account?pc_split_value=4&countrysite=uk
If you try it, let me know how it goes.
Make sure the password is stored in a file that is either not readable, or accessible from the web.
Storing the password in a .php file is considered safe because you can not see the contents of a .php file from the web (only it's output).
You can also store the file outside of the webroot, which makes the file wholly inaccessible from the web.
Another solution is to use the native webserver ignore rules. Files that start with a . like .password are hidden on some webservers. Specifically Apache hides all files that start with .ht. These depend on webserver vendor though so be cautious.
Storing the password in config.inc runs the risk of accidentally exposing the contents when it's in a web-accessible folder.
You don't need to worry about someone gaining access to your server and reading the password from the file because you'll have bigger problems: they have access to your server :)
You could also place the password as an environment variable on your hosting server and use getenv from your php application to read the password.
Is it necessary to unset my password variable for my MySQL database.
Currently, my code for my "dbpwd.php" is like this:
# database setup
$dbserver = "localhost";
$db_usrname = "blah";
$db_pwd = "blahblahblah";
$dbname = "blah";
but I was thinking.... is this a securtly concern.. because anyone can just do this:
<?php
include 'http://www.mywebsite.com/dbpwd.php';
echo $db_usrname;
echo $db_pwd;
?>
Wouldn't that give them full access to my stuff... so is it good practice to unset variables that are sensitive at the end of your php code? or is there something that I am missing?
Edit to clarify...
In this situation listed above... they would be using their own php server (not mine), and using include from there php file to get information from my server.
If someone attempts to perform a remote include via allow_url_fopen to your script, remember that from your server's point of view that is a regular HTTP request. A properly configured server would then execute the PHP code, rather than send it down as source. So what they would receive, assuming your database configuration file produces no output, would be a blank document. They would not see or have access to your variables.
The result is the same as if you pointed your web browser to http://www.mywebsite.com/dbpwd.php. You would see a blank page.
As I mentioned though, this relies on your web server being properly configured to execute PHP code (which it should be if your code runs when requested otherwise). It is always recommended though, to place sensitive files outside the server's document root to avoid this issue should your server ever become incorrectly configured.
To answer the other part of your question, you do not need to unset any variables. PHP will clean them up when they are no longer needed, and they are not a danger to your security.
imho closing the database connection is quite enough and you do not need to unset those variables.
Also as Michael Berkowski pointed out - you need to put db connection files outside of document root.
In tutrorials for Connecting to MySQL with PHP you see something similar to the below.
$pdo = new PDO('mysql:host=localhost;dbname=mydb', 'myuser','mypassword');
I have a connection working this way on my localhost but for putting it live what do you do about the password? Do you just leave it as plain text like that in your php file? Or is there a more secure way to handle this?
Nobody can see your connection string if they look at the source, it can only be seen by looking at your raw code. I would also have it inside a separate file, and include the file on your page. This also helps if you need to change the password, as you won't have to edit every page that uses a connection - you'll only need to edit the one file.
Alternatively, you can have a connection string in an include file and place it outside of document root. This stops people getting to this file using a browser or if they attack your FTP. This will help security of your plain-text passwords, but is still accessible if somebody gets/has access to your local directories. To do this, you may need to configure a PHP configuration variable, open_basedir, which allows your script to talk to a file outside of root. This all depends on if you have access to a folder behind root of course, and if you can change that configuration variable.
Other than that, there's not much that can be done.
Include File Example:
Create a file called conn.php and store your connection in there.
$dbConn = mysql_connect($host, $user, $pass);
mysql_select_db("dbName", $dbConn);
On the page that needs the connection, include the conn.php file like so:
<?php
include("conn.php");
if (!dbConn) {
die('Sorry, our database did not load. Please try again later.');
exit();
}
$result = mysql_query("...");
?>
An end user will never be able to see the text inside a PHP script. They only see what is output by the code. You can put passwords like that in, as long as you never do something like:
$mySecretPassIs='TheBoogeyManCometh';
echo $mySecretPassIs;
Having said that, it is often easier to put your connection details in a script, include it as you need from the various pages and off you go. The benefit is that if you change passwords or the like, you only have to change it in one place, and you can keep these included files in one safe place.
There really is no way around it. Just put that line in a mysql_connect.php file and include() it, so it's not on your source pages.
This way, even if someone is looking at your source, the password won't be immediately available.
Make sure your database permissions only allow that user certain privileges on the database, so even if the password is compromised, they only can modify things in that one database.
I tried coding in the following way for one of the website over a localhost. say localhost/abc:
<?php
session_start();
$_SESSION['name']=$row['name']
?>
The output was good. but when the same code was used for another webpage over the same localhost say localhost/xyz. Then there was ambiguity between names. As if I need to distinguish between the sessions for xyz and abc.
So I tried this:
<?php
session_id(226);
session_name(veer);
session_start();
.
.
.//connection with database and all
.
$_SESSION['name']=$row['name'];
echo($_SESSION['name']);
?>
When another machine logged in over the same server then the session I created was accessible by that machine for same webpage.
Is there any solution. Or how to distinguish between two sessions.?
To put it in simple terms... you are accessing same memory area of server when you access two different sites on same web server using the same browser instance. Thus
http://localhost/xyz and http://localhost/abc are referring to the same site localhost and thus you will not start another session by session_start() but instead resume it. You can alternatively create virtual hosts as Jon said but for the sake of testing which I guess you are, just use different browsers.
Also, you cannot share session over different machines normally, so I think that's your logical mistake. Alternatively try
session_start();
echo (session_id());
on the top of the page and see if you are starting or resuming the same session which I think you are not. I think your page is storing same data in different sessions which you are mistaken as same session.
Use session_regenerate_id(); method in the second file(xyz).
this?
<?php
session_start();
if (!isset($_SESSION['xyz'])) { $_SESSION['xyz'] = array(); }
$_SESSION['xyz']['name'] = $row['name'];
?>
sometimes instead of doing the above i just prefix my session keys
example: $_SESSION['xyz_name'];
I did that after i realized that my CPanel has been used some sessions of its own
that caused a conflict to mine.
Requests from the same user agent to the same web server will share the same session, barring explicit configuration that depends on your exact server setup.
Normally this problem is avoided because the "other webpage" would actually be on another domain entirely, so the session cookie (and by extension the session data) would not be shared. This is also what you should do if you want to run separate applications independently on localhost: set up separate virtual hosts on separate internal domains.
You could also solve the problem purely in code by not using $_SESSION directly to store your data but a subkey based on some differentiating factor such as $_SESSION['SCRIPT_NAME']. A very simple example:
$sessionKey = "default";
if (strpos($_SESSION['SCRIPT_NAME'], "dir1/")) {
$sessionKey = "dir1";
}
else if (strpos($_SESSION['SCRIPT_NAME'], "dir2/")) {
$sessionKey = "dir2";
}
$_SESSION[$sessionKey]['mydata'] = 'foo';
However this last one is a really inelegant solution which I would not recommend.
I'm setting up a simple web-based code editor using CodeMirror to help students learn basic HTML, CSS, and JavaScript.
I want the students to be able to save their code, so it is visible in a stand-alone browser window with its own link that can be shared with friends and family to show off their work (i.e. mydomain.com/users/their-username/test.html).
I currently have the following PHP, but I know my use of $content is not secure at all:
if ($_POST['type'] == 'save') {
$content = stripslashes($_POST['code']);
$username = addslashes(strip_tags($_POST['username']))); //i.e. markrummel
$filename = addslashes(strip_tags($_POST['filename']))); //i.e. test, index
$ext = addslashes(strip_tags($_POST['filetype']))); //i.e. html, css, js
$path = '/users/' . $username . '/';
$URL = $path . $filename . '.' . $ext;
file_put_contents($URL, $content);
}
In most cases $content should be safe HTML, CSS, or JavaScript, like: <p>My name is Mark</p>, but I want to be prepared in case something malicious is put into the code editor to be saved.
Any suggestions on how I can securely save and display their code? Is there a way to quarantine/sandbox each user's folder from other user folders and the rest of the website?
Maybe there is no secure way to do this and I shouldn't allow anyone I don't trust to save code to my server, but if there is a safe way to do this...that would be great for this project! If not, I'll figure something else out.
Thank you for any help or insight you can offer! -Mark
addslashes and stripslashes do nothing for you here at all. I'm not sure what you are trying to do with them but slashing a string is not a useful form of encoding for filename handling or really any context you are likely to meet in a webapp.
strip_tags is also of no use for anything to do with filenames; it removes HTML from a string (but even then not really in a good enough way to use as a guard properly against HTML injection).
$URL = $path . $filename . '.' . $ext;
file_put_contents($URL, $content);
Yeah, this is seriously unsafe. By putting .. segments in the username or filename, an attacker can store files outside the root path. With complete control of the filename including extension that can include executable files like .php or other sensitive files like .htaccess. (Even if $ext were limited to known-good values, depending on OS your server is running under, it may also be possible to evade that extension appending.)
Whilst it is possible to sanitise filenames by limiting the characters that can be used in them, it's harder than you think to make that watertight when you might be running on eg. a Windows server. It's almost always better to generate filenames yourself (eg using a unique integer ID instead of an attacker-supplied filename) for storage on your local filesystem. You can always use rewrites to make the files appear to have a different address.
In most cases $content should be safe HTML, CSS, or JavaScript
Are you sure that's safe then?
If you serve some user-supplied scripting from inside your domain, it can control everything any of your users does within the site. It could override or fake any user-level security controls you have, upload files under other users' names and so on.
You can try to sanitise submitted HTML to make it use only safe tags, but that's hard to get right, and of no use if you want to permit users to run CSS/JS!
Is there a way to quarantine/sandbox each user's folder from other user folders and the rest of the website?
Yes. Serve each area from a different hostname. eg. put the main site on http://www.example.com/ with sandboxes at http://tom.users.example.com/, http://dick.users.example.com/ and so on.
This prevents direct cross-site scripting. To ensure sandbox sites cannot read cookies from the main site, make sure it is not also running on example.com (redirect it to www.example.com).
This isn't quite a complete sandbox. If you need to ensure sandbox sites cannot write cookies to other sites (potentially breaking them by stopping their own cookies working then you have no choice but to run each sandbox in its own full domain. And if you have to guard against Java plugin URL connections, each sandbox needs its own IP address. This gets costly quick! But these are less serious attacks.