Solved

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

Posted on 2012-12-28
6
482 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 108

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 108

Expert Comment

by:Ray Paseur
ID: 38728058
I think that is correct.  I will try it and let you know what happens.
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 108

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 108

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

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Suggested Solutions

These days socially coordinated efforts have turned into a critical requirement for enterprises.
Nothing in an HTTP request can be trusted, including HTTP headers and form data.  A form token is a tool that can be used to guard against request forgeries (CSRF).  This article shows an improved approach to form tokens, making it more difficult to…
The viewer will learn how to count occurrences of each item in an array.
The viewer will learn the basics of jQuery, including how to invoke it on a web page. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery.: (CODE)

758 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

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now