Solved

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

Posted on 2012-12-28
6
497 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 2
6 Comments
 
LVL 110

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 110

Expert Comment

by:Ray Paseur
ID: 38728058
I think that is correct.  I will try it and let you know what happens.
0
NEW Veeam Agent for Microsoft Windows

Backup and recover physical and cloud-based servers and workstations, as well as endpoint devices that belong to remote users. Avoid downtime and data loss quickly and easily for Windows-based physical or public cloud-based workloads!

 
LVL 110

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 110

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

The Ultimate Checklist to Optimize Your Website

Websites are getting bigger and complicated by the day. Video, images, custom fonts are all great for showcasing your product/service. But the price to pay in terms of reduced page load times and ultimately, decreased sales, can lead to some difficult decisions about what to cut.

Question has a verified solution.

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

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…
Since pre-biblical times, humans have sought ways to keep secrets, and share the secrets selectively.  This article explores the ways PHP can be used to hide and encrypt information.
Learn the basics of modules and packages in Python. Every Python file is a module, ending in the suffix: .py: Modules are a collection of functions and variables.: Packages are a collection of modules.: Module functions and variables are accessed us…
In a recent question (https://www.experts-exchange.com/questions/29004105/Run-AutoHotkey-script-directly-from-Notepad.html) here at Experts Exchange, a member asked how to run an AutoHotkey script (.AHK) directly from Notepad++ (aka NPP). This video…

717 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