Is PDO database connection secure? - php

I am trying to connect to my database with the following code. And it works, but I am not sure how secure is it. Do I must have a private function too? I don't have any examples of how to apply a private function on this code.
$username = 'user';
$dsn = 'mysql:host=localhost; dbname=register';
$password = 'somepassword';
try{
$db = new PDO($dsn, $username, $password);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}catch (PDOException $ex){
echo "Connection failed ".$ex->getMessage();
}

Better use php composer where you can put these details in a environment file .env. It will be secured as .env is hidden and is placed on Server.

Put the connection parameters into a secure place (i.e. not reachable
by HTTP requests, something like the first answer will be nice), don't leave them into PHP script or some file in the same context... if you put there, protect it with htaccess DENY directive
Never echo exceptions into script output, always deal with them (put
into a log file, translate to friendly errors hiding parameters,
etc). The script never should throw exceptions to the user, it must be handled... the user must only see friendly messages from the script, even a "Ops, something bad happen here..." is better than a "ERROR: SQLSTATE[42000] [1049] Unknown database 'users'" (that show the user a part of the database structure, witch is a security problem)

Related

PHP PDOException not catching

I need some guidance on PDO error handling.
I got this code:
<?php
$config = include('config.php');
try{
$handler = new PDO('mysql:host-127.0.0.1;dbname=not_a_valid_dbname', $config->username, $config->password);
$handler->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
echo 'Yup!';
}catch(PDOException $e){
echo 'Caught! '.$e->getMessage();
}
As you can see I provided an unvalid db name. This page outputs 'Yup!' instead of letting me know that there is no such database. Same goes when changing 'mysql:not_valid_host'. Only when I change driver name it throws an error letting me know that there is no driver by that name.
I tried:
Checking php.ini for settigs (I have hard time getting around with this)
Adding
error_reporting(E_ALL);
ini_set("display_errors", 1);
ini_set("display_startup_errors", 1);
Adding
ini_set('display_errors',true);
Also tried adding a backslash in catch param:
catch(\PDOException $e)
Still the same result. Help me break my code :D
The documentation is very unclear, but I've made some tests and drawn some conclusions. This is pure speculation. I'll try to back some of these claims up if I find further information.
If host is not present, localhost is then assumed.
Database name is not mandatory. This is, I imagine, so you can connect to a server and create a new database through PDO.
If you have a syntax error, the string will stop being considered thereafter.
With those suppositions, we can assume why your code is working the way it is. Your DSN is:
mysql:host-127.0.0.1;dbname=not_a_valid_dbname
Since there's a syntax error (- after host), neither of the parameters are considered, and there's no DB selected, with the host being localhost. This is why you get no errors. If you delete the host parameter, however:
mysql:dbname=not_a_valid_dbname
localhost is used as host (selected by default), but not_a_valid_dbname is tried as the database, which results in
Caught! SQLSTATE[HY000] [1049] Unknown database '1234'
mysql:not_valid_host would be the same case as the first example. The DSN is invalid so localhost is assumed with no database selected.
Further, you get no error because no actual DB is selected but you didn't try to run a query. As soon as you do,
try {
$handler = new PDO('mysql:', "root", "root");
$handler->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$handler->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$handler->query("SELECT * FROM test");
echo 'Yup!';
} catch(PDOException $e) {
echo 'Caught! '.$e->getMessage();
}
You'll get an PDOException, as expected:
Caught! SQLSTATE[3D000]: Invalid catalog name: 1046 No database selected
Like I said, all of this is speculation as I couldn't really find concrete evidence on most of this. I hope this guides you in the right direction. I'll keep looking for more information and edit if I find anything.

error handling if pdo db connection is not present?

I have my db connection parameters set in a single file which I include on all pages I need it. Connection files looks like so... called connect.php :
$db_host = '111.111.111.111';
$db_database = 'test';
$db_user = 'test';
$db_pass = 'test';
$db_port = '3306';
//db connection
try {
$db = new PDO("mysql:host=$db_host;port=$db_port;dbname=$db_database;charset=utf8", $db_user, $db_pass,
array(
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, //PDO::ERRMODE_SILENT is default setting
PDO::ATTR_PERSISTENT => false //when true
)
);
}
catch(PDOException $e) {
error_log("Failed to connect to database (/connect.php): ".$e->getMessage());
}
When I need to do things with the db I include this file and end up with something like this... called example.php :
require $_SERVER['DOCUMENT_ROOT'].'/assets/functions/connect.php';
$stmt = $db->prepare("
SELECT
accounts.account_id,
FROM accounts
WHERE accounts.account_key = :account_key
");
//bindings
$binding = array(
'account_key' => $_POST['account_key']
);
$stmt->execute($binding);
//result (can only be one or none)
$result = $stmt->fetch(PDO::FETCH_ASSOC);
//if result
if($result)
{
// result found so do something
}
Occasionally the database connection will fail (updating, I shut it down, its being hammered, whatever)... when that happens the PDOException I have in the try/catch works as it should and adds an entry into my error log saying so.
What I would also like to do is add a 'check' in my example.php so it doesn't attempt to do any database work if there is no connection (the include file with my connect script failed to get a connection). How would I go about this and what is the preferred method of doing so?
I'm not sure of the correct way to 'test' $db before my $stmt entry. Would there be a way to retry the connection if it was not set?
I realize I can leave it as it and there would be no problems, other than the database query fails and the code doesn't execute, but I want to have more options like adding another entry to the error log when this happens.
To stop further processings just add an exit() at the end of each catch block, unless you want to apply a finally block.
try {
//...
} catch(PDOException $e) {
// Display a message and log the exception.
exit();
}
Also, throwing exceptions and true/false/null validations must be applied through the whole connect/prepare/fetch/close operations involving data access. You may want to see a post of mine:
Applying PDO prepared statements and exception handling
Your idea with including db connection file I find good, too. But think about using require_once, so that a db connection is created only once, not on any include.
Note: In my example I implemented a solution which - somehow - emulates the fact that all exceptions/errors should be handled only on the entry point of an application. So it's more directed toward the MVC concept, where all user requests are sent through a single file: index.php. In this file should almost all try-catch situations be handled (log and display). Inside other pages exceptions would then be thwrown and rethrown to the higher levels, until they reach the entry point, e.g index.php.
As for reconnecting to db, How it should be correlated with try-catch I don't know yet. But anyway it should imply a max-3-steps-iteration.

Cannot connect to MYSQL in MAMP using PHP

I just installed MAMP and have created a MYSQL database. I can access it via PHPMYADMIN.
In my php page I have this, pasted directly from the MAMP webstart page--
$user = 'root';
$password = 'root';
$db = 'local_db';
$host = 'localhost';
$port = 3306;
$link = mysql_connect(
"$host:$port",
$user,
$password
);
$db_selected = mysql_select_db(
$db,
$link
);
The resulting page stops at this point, won't print anything below these instructions.
I've tried changing the port in the MAMP preferences. I also included or die("Could not connect"); after the first line, but still don't get any text after the link data in the page.
I checked online, and others with the problem at least see the die text. I don't get that.
I haven't changed any passwords or data other than mess with the port number.
Any help would be appreciated!
Please give the following a try, I have developed and tested it locally, functionality within has been documented to help you understand what is going on in every step.
/**
*
* Modern method of connecting to a MySQL database and keeping it simple.
*
* If you would like to learn more about PDO,
* please visit http://php.net/manual/en/book.pdo.php
*
*/
//Set up database connection constants, so they cannot be changed.
define('DBHOST','127.0.0.1'); //Change this to the ip address of your database
define('DBNAME','test'); // Change this to the database name you are trying to connect to.
define('DBUSER','databaseuser'); // Insure this user is not the root user!!!!
define('DBPASS','databasepassword'); // Insure this is not the root password!!!!
//Let's try to connect to the database first.
try {
//Initiate a new PDO object called $MYDB and pass it the proper information to make
//the connection
$MYDB = new PDO("mysql:host=".DBHOST.";dbname=".DBNAME."", DBUSER, DBPASS);
//If we are successful show it :D for the test page, if this is for production you should not show this.
echo "Database connection was successful.";
//If this does not worth catch the exception thrown by PDO so we can use it.
} catch(PDOException $e) {
//Show that there was an issue connecting to the database. Do not be specific because,
//user's do not need to know the specific error that is causing a problem for security
//reasons.
echo "Oh, sorry there was an issue with your request please try again.";
//Since we had an issue connecting to the database we should log it, so we can review it.
error_log("Database Error" . $e->getMessage());
}
//Since this is 100% php code we do not need to add a closing php tag
//Visit http://php.net/manual/en/language.basic-syntax.phptags.php for more information.
If you have any issues with this please attempt to break it up into smaller pieces while reviewing the PDO documentation.

Newbie trying to learn how to connect to phpmyadmin

I have one file on one web serve and my phpmyadmin SQL databases on a seperate server and am currently trying to connect to my external serve but it doesnt seem to work.
I keep getting the error message:
'Access denied for user ''#'localhost' (using password: NO)'
and am not sure what this means.
Any help would be greatly appreciated or even an article to get started on figuring this out since I cant seem to find anything myself.
Thank you
EDIT --- PDO SCRIPT ---
My PDO Script is the generic one from w3, I have place holders for security reasons.
<?php
$servername = "externalIP";
$username = "username";
$password = "password";
try {
$conn = new PDO("mysql:host=$servername;dbname=Reservations", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
echo "Connected successfully";
}
catch(PDOException $e)
{
echo "Connection failed: " . $e->getMessage();
}
?>
you have to find your phpmyadmin page where you login using also a password.
Try this one :if you have not assign password into database for specific user then you just have to apply 'root' as user and leave blank password field and also set your hostname as 'localhost' or 127.0.0.1
also remember that you have to start first apache and mysql services before access.
If you are using remote server as database then not required.in that case you have to apply your remote Ip address and also remember that in that remote server if you have not specific user then leave password as blank. one another way to debug mysql connection into your remote server creating mysql connection file with its required paramter to check that your remote server ok or not.
This error will come most probably because of user permission issue. Make sure you have privilege to that user for that database.

PHP PDO: Unable to connect, Invalid catalog name

I am trying to set up a new site on my hosting (Host route if it matters) but i keep getting this error when i try using PDO (first PDO site im trying):
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[3D000]: Invalid catalog name: 1046 No database selected' in /home/kennyi81/public_html/gamersite/login.php:36 Stack trace: #0 /home/kennyi81/public_html/gamersite/login.php(36): PDOStatement->execute() #1 {main} thrown in /home/kennyi81/public_html/gamersite/login.php on line 36
When i use these settings:
$dbh = new PDO("mysql:91.146.107.11;dbname=kennyi81_gamersite", "kennyi81_gamer", "***************");
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
....
$stmt = $dbh->prepare('SELECT * FROM USERS WHERE ID = :id LIMIT 1');
How the database is laid out:
I am able to use mysqli connect fine on my other sub domains / main site, but i just cannot get PDO to work.
I've tried this, which i have seen around:
$stmt = $dbh->prepare('SELECT * FROM gamersite.USERS WHERE ID = :id LIMIT 1');
but it retuns a syntax error.
Anyone have any idea what may be causing this?
This is all working on my local server, nothing changed on upload apart from connect line.
Instead of:
$dbh = new PDO("mysql:91.146.107.11;dbname=kennyi81_gamersite", "kennyi81_gamer", "***************");
Try:
$dbh = new PDO("mysql:host=91.146.107.11;dbname=kennyi81_gamersite", "kennyi81_gamer", "***************");
(add host=)
And it most likely works on your local server, because you have mysql:localhost... or mysql:127.0.0.1... there and it's ignored (cause it's missing host= aswell) and by default it's localhost.
From the PDO manual page, you can see that you need to wrap the connection in a try/catch block. This way if something goes wrong with the connection, it will tell you. Something like this:
try {
$dbh = new PDO("mysql:91.146.107.11;dbname=kennyi81_gamersite", "kennyi81_gamer", "***************");
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbh = null;
} catch (PDOException $e) {
print "Error!: " . $e->getMessage() . "<br/>";
// Then actually do something about the error
logError($e->getMessage(), __FILE__, __LINE__);
emailErrorToAdmin($e->getMessage(), __FILE__, __LINE__);
// etc.
die(); // Comment this out if you want the script to continue execution
}
The reason you are getting this error is because there is an error with your connection, but since you don't tell your script to stop, it doesn't. Look at the error message produced, and how to fix it should be made obvious. It appears that Michael Prajsnar's answer is correct in that you aren't setting a "host".
Edit:
As it turns out, PDO doesn't complain if you leave out your host or dbname in the PDO connection DSN part (at least on Unix). I tested it and leaving it blank will default it to "localhost" and I was therefore able to connect perfectly fine leaving this out completely for localhost connections, which would explain why it worked on your local server but not on your production server. In fact, it is completely possible to connect supplying absolutely nothing in the DSN except for the database engine like this:
$dbh = new PDO("mysql:", "kennyi81_gamer", "***************");
The only problem is that it won't be using a database, so to USE a database, just do:
if ($dbh->query("USE kennyi81_gamersite") === false)) {
// Handle the error
}
However with that said, I have my doubts that you actually tried connecting using a try/catch block (as you mention in your comments) unless you somehow provided valid database credentials. The ONLY way that doing it this way did not produce any sort of error is if you actually connected correctly and selected the database kennyi81_gamersite. If not, you would have seen a message like this:
Unable to connect to database. "mysql" said: SQLSTATE[28000] [1045]
Access denied for user 'kennyi81_gamer'#'localhost' (using password: YES)
In summary, always wrap your connection in a try/catch block if you want to find errors during connection. Just make sure not to re-throw (and not catch) the PDOException's getMessage() or you could expose your login credentials.

Categories