Solved

hide database login credentials from print_r, var_dump, reflection, etc.

Posted on 2012-12-28
6
491 Views
Last Modified: 2012-12-28
Hi all,

Using WordPress as an example may help clarify my question.

If someone gains access to the server where the WordPress installation is located, they can upload a simple file to find out the login credentials for the installation's database.

simple file example:
<?php
require_once 'wp-load.php';
global $wpdb;
var_dump($wpdb);
?>

Open in new window


By uploading that file and calling it in a web browser I can see the dbuser, dbpass, dbhost, etc. properties of $wpdb.

How can one use a class that handles all database tasks and hide these properties from outsiders, or at least make them much more difficult to find out?  I've thought of holding the values in a separate class that gets called from the main class but the var dump would clue a snooper in as to what class to next run the var_dump on, so that doesn't seem effective unless you were to put the credentials many, many classes deep in a chain.

Thanks!
0
Comment
Question by:foxymoron7
  • 4
  • 2
6 Comments
 
LVL 109

Accepted Solution

by:
Ray Paseur earned 500 total points
ID: 38727973
Here is the central issue:
If someone gains access to the server where the WordPress installation is located, they can upload ...
If you're willing to permit that, you will have a serious security risk.  If you can't prevent that, you might want to get a different hosting company.

There are some things you can do that might help, such as storing these values in a script that is outside of the web root.  But ultimately, if you allow others to place scripts on your server you cannot be 100% safe.

I have never tested it, but it seems possible that you could unset() these values after they are used.
0
 
LVL 1

Author Comment

by:foxymoron7
ID: 38728033
Thanks Ray_Paseur,
Let's go with the assumption that one doesn't allow access to the server beyond any uploads that a cms or web application allows (pics, media files, etc) that would be placed in a folder on the server.  My skill set in the area of security is pretty weak so I always work under the assumption that any server can be accessed by someone that is skilled enough.  I'm confident in the overall security of my hosting provider so I'm asking more in a "what if, possibly, someday..." way.

If I store the values in a config file that is placed outside of the public server folders and called by the script, the values become accessible to a var_dump of the class once they are called and used by the class, correct?

But if I understand you correctly, I may be able to unset those properties after a connection is made to the database and that connection is stored as a property of the class object?  Using the $wpdb object from the initial example:

 $wpdb->dbh holds the connection resource and now the $wpdb object no longer needs to store the credentials used to create the connection and they can be unset after a simple test of the $wpdb->dbh property returns true?

Thank you.
0
 
LVL 109

Expert Comment

by:Ray Paseur
ID: 38728058
I think that is correct.  I will try it and let you know what happens.
0
Master Your Team's Linux and Cloud Stack!

The average business loses $13.5M per year to ineffective training (per 1,000 employees). Keep ahead of the competition and combine in-person quality with online cost and flexibility by training with Linux Academy.

 
LVL 109

Expert Comment

by:Ray Paseur
ID: 38728073
This tested out the way we want.
http://www.laprbass.com/RAY_mysql_CREATE_TEMPORARY_TABLE.php

Check the moving parts in lines 12-13, 37-41.  The rest is just the test structure.

<?php // RAY_mysql_CREATE_TEMPORARY_TABLE.php
error_reporting(E_ALL);
echo "<pre>";


// CONNECTION AND SELECTION VARIABLES FOR THE DATABASE
$db_host = "localhost"; // PROBABLY THIS IS OK
$db_name = "??";        // GET THESE FROM YOUR HOSTING COMPANY
$db_user = "??";
$db_word = "??";

// LIVE DATABASE CREDENTIALS ABOVE WEB ROOT
require_once('../db_info.php');


// OPEN A CONNECTION TO THE DATA BASE SERVER
// MAN PAGE: http://php.net/manual/en/function.mysql-connect.php
if (!$db_connection = mysql_connect("$db_host", "$db_user", "$db_word"))
{
    $errmsg = mysql_errno() . ' ' . mysql_error();
    echo "<br/>NO DB CONNECTION: ";
    echo "<br/> $errmsg <br/>";
}

// SELECT THE MYSQL DATA BASE
// MAN PAGE: http://php.net/manual/en/function.mysql-select-db.php
if (!$db_sel = mysql_select_db($db_name, $db_connection))
{
    $errmsg = mysql_errno() . ' ' . mysql_error();
    echo "<br/>NO DB SELECTION: ";
    echo "<br/> $errmsg <br/>";
    die('NO DATA BASE');
}
// IF WE GOT THIS FAR WE CAN DO QUERIES


// REMOVE THE VARIABLES THAT HOLD THE CREDENTIALS
unset($db_host, $db_name, $db_user, $db_word);

// PROVE THEY ARE NOT THERE ANY MORE
var_dump($db_host, $db_name, $db_user, $db_word);


// CREATING A TABLE
$sql = "CREATE TEMPORARY TABLE my_table (
        _key INT         NOT NULL AUTO_INCREMENT,
        name VARCHAR(24) NOT NULL DEFAULT '',
        PRIMARY KEY(_key)  )";
$res = mysql_query($sql);

// IF mysql_query() RETURNS FALSE, GET THE ERROR REASONS
if (!$res)
{
    $errmsg = mysql_errno() . ' ' . mysql_error();
    echo "<br/>QUERY FAIL: ";
    echo "<br/>$sql <br/>";
    die($errmsg);
}



// ESCAPING A DATA FIELD FOR USE IN MYSQL QUERIES
// MAN PAGE: http://php.net/manual/en/function.mysql-real-escape-string.php
// CREATE AN ARRAY OF NAMES
$names[] = mysql_real_escape_string("Williams");
$names[] = mysql_real_escape_string("Paseur");
$names[] = mysql_real_escape_string("O'Reilly");
$names[] = mysql_real_escape_string("Paseur");
$names[] = mysql_real_escape_string("Paseur");



// MAKING AN INSERT QUERY, USING THE ESCAPED STRINGS AND TESTING THE RESULTS
foreach ($names as $name)
{
    $sql = "INSERT INTO my_table ( name ) VALUES ( '$name' )";
    $res = mysql_query($sql);

    // IF mysql_query() RETURNS FALSE, GET THE ERROR REASONS
    if (!$res)
    {
        $errmsg = mysql_errno() . ' ' . mysql_error();
        echo "<br/>QUERY FAIL: ";
        echo "<br/>$sql <br/>";
        die($errmsg);
    }
} // IF WE GET THIS FAR, THE INSERT QUERIES ALL SUCCEEDED



// GET THE AUTO_INCREMENT ID OF THE LAST RECORD WE INSERTED
// MAN PAGE: http://php.net/manual/en/function.mysql-insert-id.php
$_key  = mysql_insert_id($db_connection);

echo PHP_EOL . "LAST KEY: $_key AND NAME WITH ESCAPE STRING INCLUDED: $name";
echo PHP_EOL;



// MAKING A SELECT QUERY AND TESTING THE RESULTS
$sql = "SELECT * FROM my_table ORDER BY name ASC";
$res = mysql_query($sql);

// IF mysql_query() RETURNS FALSE, GET THE ERROR REASONS
if (!$res)
{
    $errmsg = mysql_errno() . ' ' . mysql_error();
    echo "<br/>QUERY FAIL: ";
    echo "<br/>$sql <br/>";
    die($errmsg);
} // IF WE GET THIS FAR, THE QUERY SUCCEEDED AND WE HAVE A RESOURCE-ID IN $res SO WE CAN NOW USE $res IN OTHER MYSQL FUNCTIONS



// ITERATE OVER THE RESULTS SET TO SHOW WHAT WE SELECTED
while ($row = mysql_fetch_assoc($res))
{
    var_dump($row);
}

Open in new window

HTH, ~Ray
0
 
LVL 1

Author Closing Comment

by:foxymoron7
ID: 38728082
Thanks Ray_Paseur!

I ran a quick test of unsetting the values and the object remains usable for querying.  For my purposes keeping a live connection resource for the life of the object is not problem but I expect it may become one for high volume/traffic sites.  So viewers of this solution may want to explore that side of the solution further.

Thank you!
0
 
LVL 109

Expert Comment

by:Ray Paseur
ID: 38728138
I think you might be able to unset the values inside the object.  There was no object in my test, but if you consider the variable scope both outside and inside the object, you will see that there are two copies of the variable.  Both copies would need to be nullified.

Thanks for the points, and thanks for using EE, ~Ray
0

Featured Post

Efficient way to get backups off site to Azure

This user guide provides instructions on how to deploy and configure both a StoneFly Scale Out NAS Enterprise Cloud Drive virtual machine and Veeam Cloud Connect in the Microsoft Azure Cloud.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Creating and Managing Databases with phpMyAdmin in cPanel.
This article discusses four methods for overlaying images in a container on a web page
Learn how to match and substitute tagged data using PHP regular expressions. Demonstrated on Windows 7, but also applies to other operating systems. Demonstrated technique applies to PHP (all versions) and Firefox, but very similar techniques will w…
In this fourth video of the Xpdf series, we discuss and demonstrate the PDFinfo utility, which retrieves the contents of a PDF's Info Dictionary, as well as some other information, including the page count. We show how to isolate the page count in a…

773 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question