How would I add mysql_real_escape_string() to this QUERY? - php

I'm using a .Jquery autocomplete function and I'm tring to figure out where can put the mysql_real_escape_string() at. I've tried a few different ideas but I'm just not sure. I get an error of...
Warning: mysql_real_escape_string(): Access denied for user 'www-data'#'localhost'
When I use $ac_term = mysql_real_escape_string("%".$_GET['term']."%"); I'm not even sure if that the right way to use it.
Here's what I have...
<?php
if (!isset($_SESSION)) {
session_start();
}
try {
$conn = new PDO("mysql:host=$dbhost;dbname=$dbname", $dbuser, $dbpass);
}
catch(PDOException $e) {
echo $e->getMessage();
}
$return_arr = array();
if ($conn)
{
$ac_term = "%".$_GET['term']."%";
$query = "SELECT
CONCAT_WS('', '(',User_ID,') ', UserName, ' (',AccessLevel,')') AS DispName,
User_ID, UserName, AccessLevel
FROM Employees
WHERE UserName LIKE :term
OR User_ID LIKE :term
OR AccessLevel LIKE :term
";
$result = $conn->prepare($query);
$result->bindValue(":term",$ac_term);
$result->execute();
while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
$row_array['value'] = $row['DispName'];
$row_array['User_ID'] = $row['User_ID'];
$row_array['UserName'] = $row['UserName'];
$row_array['AccessLevel'] = $row['AccessLevel'];
array_push($return_arr,$row_array);
}
}
$conn = NULL;
echo json_encode($return_arr);
?>
Any suggestions?

You don't have to add mysql_real_escape_string() to this query at all.
Just leave your code as is.

I believe that mysql_real_escape_string is not a right method to be used with PDO, for escaping purpose use PDO quote method.
As stated in documentation, escaping string is not necessary for prepare and execute statements:
Calling PDO::prepare() and PDOStatement::execute() for statements that will be issued multiple times with different parameter values optimizes the performance of your application by allowing the driver to negotiate client and/or server side caching of the query plan and meta information, and helps to prevent SQL injection attacks by eliminating the need to manually quote the parameters.

Prepared statement parameters don't need to be escaped; it's one of the main reasons for them.
Some PDO drivers don't currently support repeating a named parameter. Depending on which version of PHP is installed, you may need to create a separate parameter for each value.

You need to create the connection first. mysql_real_escape_string() relies on an active MySQL connection; it's trying to assume your credentials will let you connect to localhost most likely.
create an active, authenticated mysql connection prior to using mysql_real_escape_string(), and at least that error message should go away.
Additionally, the best way to use it would be:
$ac_term = mysql_real_escape_string($_GET['term']);
with your query looking like
$query = "SELECT ... FROM ... WHERE column LIKE '%$ac_term%'";

Related

Grabbing things from database using functions. Is this safe?

I have a simple question. I'm not too good at programming yet but is this safe and correct?
Currently I am using functions to grab the username, avatars, etc.
Looks like this:
try {
$conn = new PDO("mysql:host=". $mysql_host .";dbname=" . $mysql_db ."", $mysql_username, $mysql_password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
}
catch(PDOException $e)
{
echo "Connection failed: " . $e->getMessage();
}
config.php ^^
function getUsername($userid) {
require "config/config.php";
$stmt = $conn->prepare("SELECT username FROM accounts WHERE id = ? LIMIT 1");
$stmt->execute([$userid]);
$name = $stmt->fetch();
return $name["username"];
}
function getProfilePicture($userid) {
require "config/config.php";
$stmt = $conn->prepare("SELECT profilepicture FROM accounts WHERE id = ? LIMIT 1");
$stmt->execute([$userid]);
$image = $stmt->fetch();
return $image["profilepicture"];
}
Is this correct and even more important, is this safe?
Yes, it's safe with respect to SQL injections.
Some other answers are getting off topic into XSS protection, but the code you show doesn't echo anything, it just fetches from the database and returns values from functions. I recommend against pre-escaping values as you return them from functions, because it's not certain that you'll be calling that function with the intention of echoing the result to an HTML response.
It's unnecessary to use is_int() because MySQL will automatically cast to an integer when you use a parameter in a numeric context. A non-numeric string is interpreted as zero. In other words, the following predicates give the same results.
WHERE id = 0
WHERE id = '0'
WHERE id = 'banana'
I recommend against connecting to the database in every function. MySQL's connection code is fairly quick (especially compared to some other RDBMS), but it's still wasteful to make a new connection for every SQL query. Instead, connect to the database once and pass the connection to the function.
When you connect to your database, you catch the exception and echo an error, but then your code is allowed to continue as if the connection succeeded. Instead, you should make your script die if there's a problem. Also, don't output the system error message to users, since they can't do anything with that information and it might reveal too much about your code. Log the error for your own troubleshooting, but output something more general.
You may also consider defining a function for your connection, and a class for your user. Here's an example, although I have not tested it:
function dbConnect() {
try {
$conn = new PDO("mysql:host=". $mysql_host .";dbname=" . $mysql_db ."", $mysql_username, $mysql_password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
}
catch(PDOException $e)
{
error_log("PDO connection failed: " . $e->getMessage());
die("Application failure, please contact administrator");
}
}
class User {
protected $row;
public function __construct($userid) {
global $conn;
if (!isset($conn)) {
$conn = dbConnect();
}
$stmt = $conn->prepare("SELECT username, profilepicture FROM accounts WHERE id = ? LIMIT 1");
$stmt->execute([$userid]);
$this->row = $stmt->fetch(PDO::FETCH_ASSOC);
}
function getUsername() {
return $this->row["username"]
}
function getProfilePicture() {
return $this->row["profilepicture"]
}
}
Usage:
$user = new User(123);
$username = $user->getUsername();
$profilePicture = $user->getProfilePicture();
That looks like it would work assuming that your config file is correct. Because it is a prepared statement it looks fine as far as security.
They are only passing in the id. One thing you could do to add some security is ensure that the $userid that is passed in is the proper type. (I am assuming an int).
For example if you are expecting an integer ID coming in and you get a string that might be phishy (possible SQL injection), but if you can confirm that it is an int (perhaps throw an error if it isn't) then you can be sure you are getting what you want.
You can use:
is_int($userid);
To ensure it is an int
More details for is_int() at http://php.net/manual/en/function.is-int.php
Hope this helps.
It is safe (at least this part of the code, I have no idea about the database connection part as pointed out by #icecub), but some things you should pay attention to are:
You only need to require your config.php once on the start of the file
You only need to prepare the statement once then call it on the function, preparing it every time might slow down your script:
The query only needs to be parsed (or prepared) once, but can be executed multiple times with the same or different parameters. When the query is prepared, the database will analyze, compile and optimize its plan for executing the query. - PHP Docs
(Not an error but I personally recommend it) Use Object Orientation to help organize your code better and make easier to mantain/understand
As stated by #BHinkson, you could use is_int to validate the ID of the user (if you are using the IDs as numbers)
Regarding HTML escaping, I'd recommend that you already register your username and etc. HTML escaped.

Mysqli_real_escape_string() or addslashes() in a forum context

I'm making a forum in php and MySql, so I need to insert and select data from my data base. I'm using mysqli to connect to my db. Something like this:
$link=mysqli_connect("fake_server", "fake_user", "fake_pass", "fake_db");
$user=mysqli_real_escape_string($link, $_POST['user']);
$pass=hash("sha256", mysqli_real_escape_string($link, $_POST['pass']));
$combo=mysqli_fetch_array(mysqli_query($link, "SELECT 1 FROM users WHERE user='$user' AND pwd='$pass'"));
if($combo==0){
// ERROR
} else {
// CORRECT
}
mysqli_close($link);
The problem is the next one:
Everybody say that mysqli_real_escape_string() is MUCH better than addslashes() for insert, but I want users can use single and double quotes in their topics. Myqsli_real_escape_string() removes them but addslashes() doesn't. What can I do in this context?
You should use prepared statements, http://php.net/manual/en/mysqli.quickstart.prepared-statements.php. In the future please provide your code in your question. Here's how you can use your current code with prepared statements:
$link=mysqli_connect("fake_server", "fake_user", "fake_pass", "fake_db");
$user=$_POST['user'];
$pass=hash("sha256", $_POST['pass']);
$stmt = $link->prepare("SELECT 1 FROM users WHERE user = ? AND pwd = ?");
$stmt->bind_param("ss", $user, $pass);
$combo=mysqli_fetch_array($stmt->execute());
if($combo==0){
// ERROR
} else {
// CORRECT
}
mysqli_close($link);
Further reading on the topic:
How can I prevent SQL injection in PHP?mysqli or PDO - what are the pros and cons?
https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet#Defense_Option_1:_Prepared_Statements_.28Parameterized_Queries.29http://php.net/manual/en/mysqlinfo.api.choosing.php
Use a parameterized query with PDO and forget worrying about escaping your queries.
Edit
Your test code:
$link=mysqli_connect("fake_server", "fake_user", "fake_pass", "fake_db");
$user=mysqli_real_escape_string($link, $_POST['user']);
$pass=hash("sha256", mysqli_real_escape_string($link, $_POST['pass']));
$combo=mysqli_fetch_array(mysqli_query($link, "SELECT 1 FROM users WHERE user='$user' AND pwd='$pass'"));
if($combo==0){
// ERROR
} else {
// CORRECT
}
mysqli_close($link);
The PDO version:
$pdo = new PDO('mysql:host=fake_server;dbname=fake_db', 'fake_user', 'fake_pass');
$query = $pdo->prepare("SELECT 1 FROM users WHERE user='?' AND pwd='?'");
$query->execute(array($_POST('user'), hash('sha256', $_POST('pass')));
if ($combo = $query->fetch ()) {
// CORRECT
// $combo would contain an array containing your select fields
} else {
// ERROR
}

PHP mysql query syntax errors

I'm fairly new to PHP/MySQL and I seem to be having a newbie issue.
The following code keeps throwing me errors no matter what I change, and I have a feeling it's got to be somewhere in the syntax that I'm messing up with. It all worked at home 'localhost' but now that I'm trying to host it online it seems to be much more temperamental with spaces and whatnot.
It's a simple login system, problem code is as follows:
<?php
session_start();
require 'connect.php';
echo "Test";
//Hash passwords using MD5 hash (32bit string).
$username=($_POST['username']);
$password=MD5($_POST['password']);
//Get required information from admin_logins table
$sql=mysql_query("SELECT * FROM admin_logins WHERE Username='$username' ");
$row=mysql_fetch_array($sql);
//Check that entered username is valid by checking returned UserID
if($row['UserID'] === NULL){
header("Location: ../adminlogin.php?errCode=UserFail");
}
//Where username is correct, check corresponding password
else if ($row['UserID'] != NULL && $row['Password'] != $password){
header("Location: ../adminlogin.php?errCode=PassFail");
}
else{
$_SESSION['isAdmin'] = true;
header("Location: ../admincontrols.php");
}
mysql_close($con);
?>
The test is just in there, so I know why the page is throwing an error, which is:
`Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource in 'THISPAGE' on line 12`
It seems to dislike my SQL query.
Any help is much appreciated.
EDIT:
connect.php page is:
<?php
$con = mysql_connect("localhost","username","password");
if(!$con) {
die('Could not connect: ' . mysql_error());
}
mysql_select_db("dbname", $con);
?>
and yes it is mysql_*, LOL, I'll get to fix that too.
You should escape column name username using backtick, try
SELECT *
FROM admin_logins
WHERE `Username` = '$username'
You're code is prone to SQL Injection. Use PDO or MYSQLI
Example of using PDO extension:
<?php
$stmt = $dbh->prepare("SELECT * FROM admin_logins WHERE `Username` = ?");
$stmt->bindParam(1, $username);
if ($stmt->execute(array($_GET['name']))) {
while ($row = $stmt->fetch()) {
print_r($row);
}
}
?>
Sean, you have to use dots around your variable, like this:
$sql = mysql_query("SELECT * FROM admin_logins WHERE Username = '". mysql_real_escape_string($username)."' ");
If you use your code just like this then it's vulnerable for SQL Injection. I would strongly recommend using mysql_real_escape_string as you insert data into your database to prevent SQL injections, as a quick solution or better use PDO or MySQLi.
Besides if you use mysql_* to connect to your database, then I'd recommend reading the PHP manual chapter on the mysql_* functions,
where they point out, that this extension is not recommended for writing new code. Instead, they say, you should use either the MySQLi or PDO_MySQL extension.
EDITED:
I also checked your mysql_connect and found a weird regularity which is - if you use " on mysql_connect arguments, then it fails to connect and in my case, when I was testing it for you, it happened just described way, so, please try this instead:
$con = mysql_connect('localhost','username','password');
Try to replace " to ' as it's shown in the PHP Manual examples and it will work, I think!
If it still doesn't work just print $row, with print_r($row); right after $sql=mysql_query() and see what you have on $row array or variable.

Trying to execute a SELECT statement in MYSQL but it is not working

I believe I have the syntax correct, at least according to my textbook. This is just a piece of the file as the other info is irrelevant to my problem. The table name is user, as well as the column name is user. I don't believe this to be the problem, as other sql statements work. Though it isn't the smartest thing to do I know :) Anyone see an error?
try {
$db=new PDO("mysql:host=$db_host;dbname=$db_name",
$db_user,$db_pass);
} catch (PDOException $e) {
exit("Error connecting to database: " . $e->getMessage());
}
$user=$_SESSION["user"];
$pickselect = "SELECT game1 FROM user WHERE user='$user' ";
$pickedyet = $db->prepare($pickselect);
$pickedyet->execute();
echo $pickselect;
if ($pickedyet == "0")
{
echo '<form method="post" action="makepicks.php">
<h2>Game 1</h2>......'
Since you're seemingly using prepared statements, I'd recommend using them to their fullest extent so that you can avoid traditional problems like SQL injection (this is when someone passes malicious SQL code to your application, it's partially avoided by cleansing user inputs and/or using bound prepared statements).
Beyond that, you've got to actually fetch the results of your query in order to display them (assuming that's your goal). PHP has very strong documentation with good examples. Here are some links: fetchAll; prepare; bindParam.
Here is an example:
try
{
$db = new PDO("mysql:host=$db_host;dbname=$db_name",
$db_user, $db_pass);
}
catch (PDOException $e)
{
exit('Error connecting to database: ' . $e->getMessage());
}
$user = $_SESSION['user'];
$pickedyet = $db->prepare('SELECT game1 FROM user WHERE user = :user');
/* Bind the parameter :user using bindParam - no need for quotes */
$pickedyet->bindParam(':user', $user);
$pickedyet->execute();
/* fetchAll used for example, you may want to just fetch one row (see fetch) */
$results = $pickedyet->fetchAll(PDO::FETCH_ASSOC);
/* Dump the $results variable, which should be a multi-dimensional array */
var_dump($results);
EDIT - I'm also assuming that there is a table called 'user' with a column called 'user' and another column called 'game1' (i.e. that your SQL statement is correct aside from the usage of bound parameters).
<?php
session_start();
$db_user = 'example';
$db_pass = 'xxxxx';
try
{
// nothing was wrong here - using braces is better since it remove any confusion as to what the variable name is
$db=new PDO( "mysql:host={$db_host}dbname={$db_name}", $db_user, $db_pass);
}
catch ( Exception $e ) // catch all exceptions here just in case
{
exit( "Error connecting to database: " . $e->getMessage() );
}
// this line is unecessary unless you're using it later.
//$user = $_SESSION["user"];
// no need for a new variable here, just send it directly to the prepare method
// $pickselect = '...';
// also, I changed it to a * to get the entire record.
$statement = $db->prepare( "SELECT * FROM user WHERE user=:user" );
// http://www.php.net/manual/en/pdostatement.bindvalue.php
$statement->bindValue( ':user', $_SESSION['user'], PDO::PARAM_STR );
$statement->execute();
// http://www.php.net/manual/en/pdostatement.fetch.php
// fetches an object representing the db row.
// PDO::FETCH_ASSOC is another possibility
$userRow = $statement->fetch( PDO::FETCH_OBJ );
var_dump( $userRow );
echo $userRow->game1;
Change this user=$user with this user='$user'. Please, note the single quotes.
Moreover, you are executing the query $pickedyet->execute(); but then you do echo $pickselect; which is nothing different from the string that contains the query.
Little hints:
You've to retrieve the result of the query execution.
You're using prepared statement which are very good but you're not really using they because you're not doing any binding.

Basic SQL output question

this is probably the most basic question in the world, but I cannot figure it out.
I would like to simply display a users First name, and Email adress from my table. I have tried using a loop, but that was entirely worthless considering I am only selecting one row. I know this is a menial question but I could not find/remember how to do it. Thank you!
$db = mysql_connect("server","un", "pw");
mysql_select_db("db", $db);
$sql = "SELECT FirstName, EmailAddress"
. " FROM Student"
. " WHERE StudentID = '$student' ";
$result = mysql_query($sql, $db);
$num = mysql_num_rows($result);
$userinfo = mysql_result($result,$userinfo);
$student is a session variable. I want to echo the First name and email address somewhere in the page, but I cannot believe how much pain thats causing me. Thanks again!
mysql_fetch_assoc() turns a result row into an array.
$result = mysql_query($sql, $db);
$user = mysql_fetch_assoc($result);
echo $user['FirstName'];
echo $user['EmailAddress'];
It looks like you spelled address wrong, so it probably doesn't match your real column name. More importantly, your code appears vulnerable to SQL injection. You really need to use prepared statements (see How to create a secure mysql prepared statement in php?) or escaping.
To fetch a row, you must use one of the mysql_fetch functions (e.g. mysql_ fetch_ array, mysql_ fetch_ object, etc.)

Categories