MySQL credentials/hosts variables best practices - mysql

I want to know what is the best practice or what is recommended to do when a variables are created for MySQL credentials/host.
define('HOST', 'localhost');
// etc..
mysql_connect(HOST, // etc...
vs
$host = 'localhost';
// etc..
mysql_connect($host, // etc...
For both you can easily check what are the declared variables or constants and maybe can find what are the value easily. I have code that multiple users can share and use.
What is the best way to protect these variables?

Here's few solutions
1) You give each user a user and password and each user has their permissions in the database (only select, or insert ect..). So in your code you simply include a db.config.php so all the variables are set. It does not really matter if the user echo the variables since they use their own.
2) you can give a common username/pass for the database and then encode the file (either using custom encoding, zend optimizer or ioncube and unset the variables. Here's a sample code:
// file mysql_connect.php
$link = mysql_connect("localhost", "mysql_user", "mysql_password")
or die("cannot connect to database : " . mysql_error());
// then this file is encoded so nobody can view it.
3) At some point, someone, somehow will be able to find this information. I would simply recommend to trust your user (assuming these are developers)

At some point in your code you will have to hardcode this kind of information, the important thing is to keep it in only one place to promote maintanability.
However, as you are worried about security I suggest you to check this: Convert PHP file to binary

Related

Connecting to a MySQL database using DBI

I am trying to connect to a MySQL database.
I found this script and I am trying to use it on my PC and web host, but it doesn't show any output.
Please have a look at this code. I am running perl at xampp.
#!C:\xampp\perl\bin\perl.exe
print "Content-type: text/html\n\n";
use DBI;
use strict;
my $driver = "localhost";
my $database = "data";
my $dsn = "DBI:$driver:database = $database";
my $userid = "root";
my $password = "";
my $dbh = DBI->connect($dsn, $userid, $password ) or die $DBI::errstr;
I am using the same database with PHP.
but it doesn't show any output.
Judging by the CGI header you're displaying, I assume that you're running this as a CGI program. In which case, it's no surprised that you're not seeing any output - you're not sending any output.
If you ran it as a command line program (and it's often a good idea to get stuff working on the command line before leaping into CGI programming), then you would see the "Content-Type" header. Alternatively, you could add some output to your program and see if that appears in your browser. Something simple like:
print 'It works!';
I'd also like to add, that CGI looks rather outdated these days and there are far better (by which I mean easier and more powerful) ways to write web applications with Perl. You might like to read CGI::Alternatives to get an idea of what is available.
Update:
I've just seen this question asked on Facebook (please don't cross-post without telling people) and I've noticed that your $driver variable is wrong. If you're connecting to MySQL, then $driver should be "mysql" (so that DBI loads "DBD::mysql").
A DSN for the MySQL driver looks like this
DBI:mysql:database=$database;host=$hostname;port=$port
where the host and port fields are optional. (The database is also optional, but you don't want to leave that out.) There are several more esoteric options too, but they're irrelevant here
But you're supplying
DBI:localhost:database = data
Which doesn't even specify a MySQL connection, so I'm not surprised if it doesn't work! I don't know whether the spaces are legal, but I would leave them out to keep in line with the documentation.
You should change that statement to
my $dsn = "DBI:mysql:database=$database;host=$driver"
You may remove ;host=$driver if you wish (why have you called the host name "driver"?) as localhost is the default. A DSN that specifies just a database name and uses the default for all the other fields may be contracted to just
my $dsn = "DBI:mysql:$database"
It may be easier to just write print statements at first to generate some output. You will want to print a MIME content type header of text/plain instead of text/html. Try print "$DBI::errstr\n" for now instead of die, as the latter writes to stderr which won't appear in your browser
you could add:
if ($dbh) {
print 'connect ok';
} else {
print 'connect failed';
}

Wordpress / codeigniter transfer sql database password

I am on a problem which need a quick solution. I will try to explain it.
I have the table wp_user (from WordPress), where all the members have password encrypted with a wordpress encrypting function. And I have to transfer this table to a new Mysql Database on a new web site working with Codeigniter.
For new members on the new site which works under codeigniter, I use the MD5 function in order to mask password.
But the problem is that the two functions are different, so when an older user try to connect on my new web site, that doesn't work because the passwords don't match ...
So, how I can do for translate the wordpress encrpyting in a normal MD5 password?
Or maybe it's not possible?
Unfortunately you'll have to perform both checks, or just change CI to use the same hashing scheme as WP. That's probably the easier option. If you really want to start using the default CI hashing scheme, you could store both hashes and update the new hash on successful login (when you have the plaintext password).
I'm not familiar with what kind of hashing Wordpress uses for passwords, but I assume that it is secure and irreversible. The hashed passwords cannot be converted to their MD5 equivalent because hashing is a one-way algorithm.
Here is my suggestion for you:
Add a using_md5_flag boolean column to the users table in your new website with default value 0. Copy the passwords over from Wordpress into a column wppassword and also create a column called md5password When users log into the system perform the following code (assumes Datamapper ORM, convert to Active Record if you need to):
$u = new User();
$u->where('username', $this->input->post('username'))->get();
$y = new User();
$y->where('username', $this->input->post('username'));
if($u->using_md5_flag){
/*the flag is 1*/
$y->where('md5password', md5($this->input->post('password')));
$y->get();
if($y->exists()) echo "setting cookie and redirecting to logged in area";
else echo "Wrong credentials!";
}
else{
/*the flag is 0, use wordpress's hashing algorithm (not sure what this is)*/
$y->where('wppassword', wp_hashing_algo($this->input->post('password')));
$y->get();
if($y->exists()){
/*set the using_md5_flag flag so next time they log in it will ignore wp's*/
$y->using_md5_flag = 1;
/*set the new md5 password.*/
$y->md5password = md5($this->input->post('password'));
$y->save();
echo "setting cookie and redirecting to logged in area";
}
else{
echo "Wrong credentials.";
}
}
This code hasn't been tested, I wrote it inside StackOverflow's editor... but It's the method I'd take to perform slow conversion to a more secure hash. Lastly, if you're looking for a really secure hash, check out Bcrypt (phpass), it's more resistant to rainbow table attacks.
Update 1: If you need to use the Phpass library with CodeIgniter, you can find a copy I modified here (I added a constructor). Put this in libraries/Phpass.php You can use the library in your controllers using:
$this->load->library("phpass", array("iteration_count_log2" => 8, "portable_hashes" => FALSE));
$check = $this->phpass->CheckPassword($this->input->post('password'), $u->password);
if($check) /*logged in*/
else /*wrong credentials.*/
When you download the Phpass file it comes with a test.php file which demos how the functions work. I suggest reviewing it.

Database input sanitation

Sorry if this question has somewhat been answered, but everywhere I look answers seems to change..
I'm really not 100% sure of how to deal with data into and from a db.
For instance: A UTF8 mysql database and a form that takes user input.
When dealing with the post - should I htmlspecialchars('data',ENT_QUOTES) to the data before it's saved to the database or do I just save it raw.. the data will most likely contain umlouts and the like of special chars. so if no sanitization is done I assume < and > and all types of quotes would be stored exactly as they are.
Also do I need to addslashes or mysql_real_escape_string before saving.
OR should all this stuff be done on the output and just use filtering for input, I use zend so I have filters added to most elements.
Not sure its relevant magic_quotes but are off.
EDIT 2:
I believe my queries use prepared statements ->where('fqha.form_question_has_answer_form_id = ?', $result[$input->formpage]['form_id'])
So does this mean I can ignore any further manipulation to data and just save what the post vars contain. Only worrying about sanitizing for output to the page?
EDIT:
I'm using doctrine 1.2 and from what I can tell this is pdo.. but regarding this and the above question any advice would be greatly appreciated
protected function _initDoctrine()
{
require_once 'Doctrine/Doctrine.php';
require_once 'Doctrine/Overloadable.php';
require_once 'Doctrine/Connection/Profiler.php';
$this->getApplication()
->getAutoloader()
->pushAutoloader(array('Doctrine', 'autoload'), 'Doctrine');
$manager = Doctrine_Manager::getInstance();
$manager->setAttribute(
Doctrine::ATTR_MODEL_LOADING,
Doctrine::MODEL_LOADING_CONSERVATIVE
);
$cacheDriver = new Doctrine_Cache_Apc();
$config = $this->getOption('doctrine');
$conn = Doctrine_Manager::connection('mysql://user:pass#localhost/db_name', 'doctrine');
$conn->setAttribute(Doctrine_Core::ATTR_QUERY_CACHE, $cacheDriver);
$conn->setCharset('utf8');
$conn->exec('SET NAMES utf8');
$profiler = new Imind_Profiler_Doctrine_Firebug();
$conn->setListener($profiler);
return $conn;
}

Why does my Perl script fail to connect to the database?

I have a Perl script which retrieves data from MySQL Database. this is the code:
sub startSession{
my $self = shift;
my $dsn = "dbi:".$self{platform}.":".$self{database}.":".$self{host}.":".$self{port};
print "$dsn\n" ;
$self{dbHandle} = DBI->connect($dsn,$user,$password);
}
I have provided every information from an external file. I get the error message
DBI connect('dbname:**.**.**.**:3306','',...) failed: Access denied for user 'root'#'dbserver' (using password: NO) at line 89
Can't call method "prepare" on an undefined value at at line 97
I am very sure the root can connect from any host and the password is also correct.
First, your immediate problem, is as #Sinan Ünür says, that you need to change $self{platform} to $self->{platform}, etc.
Your second immediate problem is that it appears you're getting $user and $password from nowhere (they are not passed to the function, so they are undefined unless they are global variables), which would explain the using password: NO part of the error. Maybe those should be $self->{user} and $self->{password}?
You should considering put this at the top of your module, at least during development, to automatically catch errors like these:
use warnings qw(all);
use strict;
But I'd also comment, that from a design perspective, you really ought to treat DSNs as opaque strings. Each database has its own DSN format. So if you ever want to target a different database, you'll need a different DSN format. Or, possibly, someday MySQL will use a different format (it already has two). Either way, it'll be much easier to change it one place, in a configuration file, than to track down each place you concatenate the various pieces together.
The key part of the warning that I see is "using password: NO". Check that the password is being set properly.
Presumably, $self is a hashref, not a plain hash, and you don't have warnings on. So, turn them on, and use $self->{platform} etc.

MySQL Security Check

Evening all,
Before i make my site live i obviously want to ensure it's secure (or as secure as possible).
I have a search form, an opportunity for a user to upload an entry to a database, and that's about it i think.
So i just want to check what i should be doing to protect things. Firstly, my database is accessed by a dedicated user account (not admin or root), so i think i've got that part locked down.
Secondly, on all my search queries i have this sort of format:
$result = mysql_query(
"SELECT *
FROM table
WHERE fieldname = '" . mysql_real_escape_string($country) . "'
AND county = '" . mysql_real_escape_string($county) . "'
ORDER BY unique_id DESC");
Finally, on the $_POST fields from my submission form, i treat the variables with this BEFORE they are inserted into the database:
$variable = mysql_real_escape_string($variable);
$result = mysql_query(
"INSERT INTO table (columnone)
VALUES ($variable)";
Could anyone let me know what else i should be considering or whether this is acceptable enough?
Thanks in advance, as always,
Dan
The code looks fine, though you should look into using PDO prepared statements if at all possible.
Beyond that, make sure that whatever account your PHP code is using to connect to MySQL has the absolute minimum in the way of permissions. Most web-facing scripts do NOT need alter/drop/create type privileges. Most can get away with only update/insert/select/delete, and maybe even less. This way, even if something goes horribly wrong with your code-level security, a malicious user can't send you a '; drop table students -- type query (re: bobby-tables.com)
Everything you show looks fine in terms of protection against SQL injection, except for
$variable = mysql_real_escape_string($variable);
$result = mysql_query(
"INSERT INTO table (columnone)
VALUES ($variable)";
this desperately needs quotes around $variable - or as #Dan points out, a check for whether it's a number - to be secure. mysql_real_escape_string sanitizes string data only - that means, any attempt to break out of a string delimited by single or double quotes. It provides no protection if the inserted value is not surrounded by quotes.
Have you considered using like MYSQL PDO and bound parameters in your SQL?
http://php.net/manual/en/pdostatement.bindparam.php
My understanding is that this is considerably more secure that using mysql_real_escape_string.