New to SQL Injections (error) [closed] - php

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
I've been advised to use anti-sql injection methods, as I am inserting values inside my database. I've looked around the web, and my first failed attempt is this, of which I need some help, with the PDO method. I found examples online to be waaay too empty of substance for me to understand (btw, I ran a line and it told me PDO is enabled):
Is this good in any way, shape or form?
<?php
include ('config.php');
// Host, User, Pass, DB
$con=mysqli_connect("127.0.0.1","*****","*****","*****");
// Check connection
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQLi: " . mysqli_connect_error();
}
$host = 'localhost';
$dbname = '****';
$user = '****';
$pass = '*****';
try {
# MS SQL Server and Sybase with PDO_DBLIB
$DBH = new PDO("mssql:host=$host;dbname=$dbname, $user, $pass");
$DBH = new PDO("sybase:host=$host;dbname=$dbname, $user, $pass");
# MySQL with PDO_MYSQL
$DBH = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
# SQLite Database
$DBH = new PDO("sqlite:my/database/path/database.db");
}
catch(PDOException $e) {
echo $e->getMessage();
}
Also, I get this error upon submitting my form:
Fatal error: Call to a member function prepare() on a non-object in /home/product/*****/*****/*****/processForm-test.php on line 68

One big problem in your code is that it's using both mysqli_connect and PDO to create database connections. Don't do that; that's not supported. Use one or the other.
The lines you have that make PDO connections attempt to connect to four separate databases, SQL Server, Sybase, MySQL and SQLLite, all running on localhost. But you are keeping a handle to only the last one, since you're assigning the database connection to the same variable.
That variable $DBH is your reference to the database session (connection), if the connect succeeds. If it doesn't succeed, that gets assigned a value of false, which you can test, before you proceed.
I think all you need is a single PDO connection to MySQL, like this:
<?php
include ('config.php');
$host = 'localhost';
$dbname = '****';
$user = '****';
$pass = '*****';
try {
# MySQL with PDO_MYSQL
$DBH = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
}
catch(PDOException $e) {
echo "Connect failed: " . $e->getMessage();
}
I'm extrapolating here, but the most likely explanation for the error message you are getting is that you've got a line of code (not shown in your code sample) like this:
$sth = $DBH->prepare($sql);
The issue is that $DBH is not a reference to valid database connection. $DBH has a value of 'false', and that's because the attempt to connect to the database failed. And false is not an object, so there's no way it can have a method named 'prepare' associated with it.

Related

mysqli_insert_id() is returning 0 but inserting the data

The Code is:
class anything_i
{
/*Every variable is defined and hidden fro privacy.*/
public function connect(){
return mysqli_connect(self::HOST,self::USERNAME,self::PASSWORD,self::DATBASE);
}
public function insertData($postData){
$sqli = 'INSERT INTO `payments`(`item_name`,`price`,`email`,`date`,`time`,`detail`,`volume`,`ip`,`payment_status`) VALUES ("'.$productData['name'].'","'.$productData['price'].'","'.$postData['email'].'","'.$date.'","'.$time.'","'.$postData['list'].'","'.$productData['volume'].'","'.$ip.'","On Hold")';
if(mysqli_query($this->connect(),$sqli)){
print_r(mysqli_insert_id($this->connect()));
}else{
print_r(mysqli_error($this->connect()));
}
}
}
It is inserting the data and working fine but does not return anything other than a 0 (zero) not getting any error.
Let me clear that my table contains auto_increment and my connection is fine because it is entering data just fine. Please don't disregard the question because you found similar once answered. I also found similar questions but most of them have connection problems, some of them the no AUTO_INCREMENT column and there may be some which included another query in between. So, please read it before mentioning another answer.
Here is the proof of AUTO_INCREMENT:
I suspect this code has been migrated from the legacy mysql extension where mysql_connect():
Opens or reuses a connection to a MySQL server.
This is no longer the case with mysqli_connect():
Opens a connection to the MySQL Server.
You really need to store the connection in a variable and reuse that same connection. Currently you're starting many different connections within the same script run.
When you call mysqli_connect() it will create a new connection each time. It does not reuse the previous connection. When a new connection is created all the properties of the old one are lost.
You are calling mysqli_connect() every time you call $this->connect() so you will never get the errors or the auto-generated ID.
mysqli connection should be global to your application. It does not make sense to keep recreating the same connection because it will lead to terrible performance issues and it will cause you problems like this one. If you are using dependency injection it should be easy to create the mysqli at the start of your application and then pass it as an argument to your class' constructor.
Connecting to the database using mysqli is always the same 3 lines of code. Only the details you pass as arguments are different.
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli('localhost', 'user', 'pass', 'db_name');
$mysqli->set_charset('utf8mb4'); // always set the charset
You can then pass this to your constructor whenever you create an object and store it in a private property.
Your fixed code would like this:
<?php
class anything_i {
private mysqli $db = null;
public function connect(mysqli $db) {
$this->db = $db;
}
public function insertData($postData) {
/*
...
*/
$stmt = $this->db->prepare('INSERT INTO `payments`(`item_name`,`price`,`email`,`date`,`time`,`detail`,`volume`,`ip`,`payment_status`) VALUES (?,?,?,?,?,?,?,"On Hold")');
$stmt->bind_param('ssssssss', $productData['name'], $productData['price'], $postData['email'], $date, $time, $postData['list'], $productData['volume'], $ip);
$stmt->execute();
}
}
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli('localhost', 'inet', '5432', 'test');
$mysqli->set_charset('utf8mb4'); // always set the charset
$obj = new anything_i($mysqli);

php PDO change connection during script via function

I have an app that has to use more than one database for reasons of client protection and archiving with a core one for administration - eg user detail storage. I appreciate the need to migrate from the mysql extension (soon to be deprecated) and I first tried mysqli but could not get away from the persistent connection, even using the change_user function, probably because the same user/pass combo is used so cross-database joins are possible.
I am implementing many stored procedures during the migration to reduce bottlenecks. MYSQL now assigns SPs to each specific database, so it is important to be connected to the right one when making a CALL. That means putting full database.table references in queries is not practical
So I have turned to PDO.
I created a test script:
$db_host="localhost";
$db_username='root';
$db_pass='';
$add='admin';
$db_name='host_base_name'.$add;
try{
$db= new PDO('mysql:host='.$db_host.';dbname='.$db_name,$db_username,$db_pass);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$result= $db->query("SELECT firstname from centralusers WHERE usr_id='1'");
while($row=$result->fetch(PDO::FETCH_ASSOC)){echo $row['firstname']."<br>";}
}
catch(PDOException $e){echo $e->getMessage();}
$add='test';
$db_name='host_base_name_'.$add;
try{
$db= new PDO('mysql:host='.$db_host.';dbname='.$db_name,$db_username,$db_pass);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$result= $db->query("SELECT stage_desc from action_stage WHERE stage_id='1'");
while($row=$result->fetch(PDO::FETCH_ASSOC)){echo $row['stage_desc']."<br>";}
}
catch(PDOException $e){echo $e->getMessage();}
And that successfully does the switch - I tried across three databases but have not shown the third for economy.
However, in the development code my script has a 'require' file which contains a function to handle the connection. it is sent the last part of the table name via the call (a process that has worked fine in the mysql extension. Here is that code;
function db_connect($add) {
$db=NULL;
$db_host="localhost";
$db_username='root';
$db_pass='';
$db_name='host_base_name_'.$add;
try{
$db= new PDO('mysql:host='.$db_host.';dbname='.$db_name,$db_username,$db_pass);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
}
catch(PDOException $e){echo $e->getMessage();}
return $db;
}
After the second call (to change the database) my next query produces an error that the table cannot be found - and gives the 'host_base_name_ 'part of the table reference as the original. I thought the NULL call would have destroyed the instance.
If I put the $db=NULL; in the calling script, just before the function I get a "Call to a member function query() on a non-object " Scream error.
Why does one work and not the other because they seem identical and how could I work round this?
Have separate PDOs for each database
$db_host="localhost";
$db_username='root';
$db_pass='';
$add='admin';
$db_name1='host_base_name'.$add1;One database
$db_name2='host_base_name'.$add2;Other database
try{
//PDO for one database
$db1= new PDO('mysql:host='.$db_host.';dbname='.$db_name1,$db_username,$db_pass);
$db1->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
//PDO for other database
$db2= new PDO('mysql:host='.$db_host.';dbname='.$db_name1,$db_username,$db_pass);
$db2->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
For those coming across this in future, I found I could indeed replace the function call with a class and create a new connection to a different database. Along the way I discovered the tremendous speed improvement by replacing 'localhost' with '127.0.0.1' -halving the execution of a test script from 0.0060 seconds to 0.0029 which can be significant in complex scripts.
So here is my class - because it is included anyway at the top of the script, I put the main connection parameters at the head of the include so they could be used in the class. The $db_name is modified in the script so it refers to the correct database.
$db_host='127.0.0.1';
$db_user='root';
$db_pass='';
$db_name='host_base_name';
class databaseConnect{
public function connect($db_host, $db_user,$db_pass,$db_name){
try{
$db= new PDO('mysql:host='.$db_host.';dbname='.$db_name,$db_user,$db_pass, array(PDO::ATTR_PERSISTENT=>false));
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
}
catch(PDOException $e){echo "Error: ".$e->getMessage()."<br />"; die(); }
return $db;
}
}
I get the new database connection instance (in this case to 'host_base_nametest' using the code below I replace $con with another variable when I have to switch databases, essentially giving me totally flexible and transportable database naming within the connection:
$add='test'; // in production this comes from another variable
$db_inst=$db_name.$add; //builds the database name
$con=new databaseConnect; //calls the class
$db=$con->connect($db_host, $db_user,$db_pass,$db_inst); //gets the new instance

Using default values for mysqli constructor fails

I am trying to connect to a database using the default values for the mysqli constructor, which is documented to be:
host = ini_get("mysqli.default_host")
username = ini_get("mysqli.default_user")
passwd = ini_get("mysqli.default_pw")
The reason I want to use the defaults is so I can have the credentials in the config file instead of scattered through my code. However, when I pass no values, the connection succeeds but then subsequent queries fail with no error.
$db = new mysqli();
if ($db->connect_errno) die("Connect failed: " . $db->connect_error);
if ($rs = $db->query("select user();") or die("Query failed: " . $db->error)) {
$row = $rs->fetch_row();
echo $row[0];
$rs->close();
}
This outputs:
Query failed:
That means the connection succeeded, but any query fails with an error. (Other actions, such as select_db, fail the same way.)
Interestingly, I can fix it by changing the first line to:
$db = new mysqli(ini_get("mysqli.default_host"),
ini_get("mysqli.default_user"),
ini_get("mysqli.default_pw"));
... but I'd prefer to not have to type out the default values everywhere I need a database connection. What am I doing wrong? Is there a way to use the mysqli constructor with no arguments?
While writing this question, I happened to scroll down the documentation page and noted the following:
Note: Calling the constructor with no parameters is the same as calling mysqli_init().
Looking up the mysqli_init documentation, it says:
Note: Any subsequent calls to any mysqli function (except mysqli_options()) will fail until mysqli_real_connect() was called.
Therefore, the fix is to change the first line from:
$db = new mysqli();
To:
$db = new mysqli();
$db->real_connect();
I would have expected in that scenario that mysqli_error would have returned something like "not connected" instead of an empty string. That's a bit counter-intuitive, but at least it's somewhat documented.

PDO: Can't connect to mysql when host is set in variable

i'm in trouble. I'm trying to connect remote mysql server with pdo (php 5.4.12). With this code it's connect normally:
$dbh=new PDO('mysql:host=xxx.xxx.xxx.xxx;dbname=newdb', $user, $pass);
But, if i try set host with variable, like this:
$host='xxx.xxx.xxx.xxx';
$dbh=new PDO('mysql:host='.$host.';dbname=newdb', $user, $pass);
It's just thinks sometime, and tell me:
Fatal error: Uncaught exception 'PDOException' with message ' in
D:\wamp\www\test.php on line 21
21 it's line of creating new PDO object.
Ok, i'm try to catch exception (sorry, it's new for me), and now i have this:
Error!: SQLSTATE[HY000] [2002]
Can you help me, please?
Double quoting not helps
$dbh = new PDO("mysql:host=$host;dbname=newdb", $user, $pass);
Nothing changed.
var_dump('mysql:host='.$host.';dbname=newdb');
string 'mysql:host=xx.xx.xxx.xxx;dbname=newdb' (length=37)
Way with {} not helped for me.
Ok, the situation becomes clear. I'm try to connect another server on another IP, and it's normally connected. Can it be mysql server security options?
Try this way
$host = "xxx.xxx.xxx.xxx";
$dbh = new PDO("mysql:host={$host};dbname=newdb", $user, $pass);
The double quotes and the braces to include the var in the string as you can see here
http://www.php.net/manual/en/language.operators.string.php

PDO slow on PHP 5.4 and Apache 2.4.3 [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
mysql_connect (localhost / 127.0.0.1) on Windows platform
I just updated my Apache and PHP versions on a development machine and PDO has totally crapped out.
This is the dead simple PDO class:
class PDO_DBH {
public static function openSesame() {
echo '<p>start openSesame: </p>'.microtime(true);
$db_username = 'root';
$db_password = 'pass';
try {
$dbh = new PDO('mysql:host=localhost;dbname=DB_NAME', $db_username, $db_password);
$dbh->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
echo '<p>end successful openSesame: </p>'.microtime(true);
return $dbh;
} catch (PDOException $e) {
echo '<p>end failed openSesame: </p>'.microtime(true);
return 'PDO database access error!';
}
}
}
Prior to upgrading, and currently on other dev machines, a typical page will load in a second, two at most.
Now, via the wonders of microtime(true), I am seeing each connection opening requires about a full second.
A typical page may create a new $dbh and then $dbh = null; it 20 times as different objects and methods go about retrieving the data they need. This has never been a problem on other machines or on my webhost.
Where have I gone wrong here?
It was just a guess - but on windows machines changing to 127.0.0.1 instead of localhost does the trick.

Categories