SQL Update code issue/PHP injection - php

I am having an issue with my SQL Update script.
It prints "Motto Changed" but doesn't update the row. My code is all correct according to many tutorials. Please Help
$sql="UPDATE loadout SET motto='".$_POST['motto']."' WHERE steamid='".$steamid."'";
UPDATE AGAIN:
<?php
require "../requires/php/steam.php";
$dbhost = '**';
$dbname = 'battlefield';
$dbuser = 'battlefield';
$dbpass = '**';
$con = mysql_connect($dbhost, $dbuser, $dbpass);
$authserver = bcsub( SteamID(), '76561197960265728' ) & 1;
$authid = ( bcsub( SteamID(), '76561197960265728' ) - $authserver ) / 2;
$steamid = mysql_real_escape_string("STEAM_0:$authserver:$authid");
$motto = mysql_real_escape_string($_POST['motto']);
mysql_select_db($dbname, $con);
$sql="UPDATE loadout SET motto='{$motto}' WHERE steamid='{$steamid}'";
if (!mysql_query($sql, $con))
{
die('Error: ' . mysql_error());
}
echo "Motto Changed";
if (!mysql_query($sql, $con))
{
die('Error: ' . mysql_error());
}
$n = mysql_affected_rows();
echo"Motto changed on {$n} row(s)";
mysql_close($con)
?>

Never interpolate $_POST variables directly into SQL strings. You can't trust $_POST variables, they may easily contain characters that modify your SQL syntax, and that's what causes SQL injection vulnerabilties.
The weird thing is that you create an escaped version as $motto and then you never use it (as per comment from #Arth).
Always escape strings that you interpolate into SQL, even if you think they are "safe." For example, your $steamid contains only literal text that you control, plus a couple of integers. That should be safe, but what if some other developer changes the format of a steamid next year? If you escape it, you can't go wrong.
$steamid = mysql_real_escape_string("STEAM_0:$authserver:$authid");
$motto = mysql_real_escape_string($_POST['motto']);
$sql="UPDATE loadout SET motto='{$motto}' WHERE steamid='{$steamid}'";
Of course, the best practice is to use query parameters. You are using PHP's deprecated mysql extension, which doesn't support query parameters. But I understand if you're not ready to rewrite a lot of code to switch to PDO. When you are, follow examples in How can I prevent SQL-injection in PHP?
Another issue: if you want to know if the UPDATE affected rows, don't assume it did just because the UPDATE didn't return an error. It's not an error if your condition in your WHERE clause simply matched zero rows. It's also not an error if the UPDATE matched a row, but the motto already contained the string you tried to set.
After the UPDATE, check the number of affected rows:
if (!mysql_query($sql, $con))
{
die('Error: ' . mysql_error());
}
$n = mysql_affected_rows();
echo "Motto changed on {$n} row(s)";

Related

PHP code no longer works when switching to mysqli

I'm trying to convert some php code that uses mysql into mysqli code. I'm not sure why it doesn't work - I didn't write the original code and am not that comfortable with the hash part of it, and it seems to be where the issue is. As I show in the code below, the "error" part gets echo'ed so it's something to do with the hash strings, but I don't really understand why changing to mysqli has broken the code. Both versions of the code are below, and the original code works. I deleted the variables (host name, etc.) but otherwise this is the code I am working with.
Mysql Code:
// Send variables for the MySQL database class.
function db_connect($db_name)
{
$host_name = "";
$user_name = "";
$password = "";
$db_link = mysql_connect($host_name, $user_name, $password) //attempt to connect to the database
or die("Could not connect to $host_name" . mysql_connect_error());
mysql_select_db($db_name) //attempt to select the database
or die("Could not select database $db_name");
return $db_link;
}
$db_link = db_connect(""); //connect to the database using db_connect function
// Strings must be escaped to prevent SQL injection attack.
$name = mysql_real_escape_string($_GET['name'], $db_link);
$score = mysql_real_escape_string($_GET['score'], $db_link);
$hash = $_GET['hash'];
$secretKey=""; # Change this value to match the value stored in the client javascript below
$real_hash = md5($name . $score . $secretKey);
if($real_hash == $hash) {
// Send variables for the MySQL database class.
$query = "insert into scores values (NULL, '$name', '$score');";
$result = mysql_query($query) or die('Query failed: ' . mysql_error());
}
Mysqli code (doesn't work):
// Send variables for the MySQL database class.
function db_connect($db_name)
{
$host_name = "";
$user_name = "";
$password = "";
$db_link = mysqli_connect($host_name, $user_name, $password) //attempt to connect to the database
or die("Could not connect to $host_name" . mysqli_connect_error());
mysqli_select_db($db_link, $db_name) //attempt to select the database
or die("Could not select database $db_name");
return $db_link;
}
$db_link = db_connect(""); //connect to the database using db_connect function
// Strings must be escaped to prevent SQL injection attack.
$name = mysqli_real_escape_string($_GET['name'], $db_link);
$score = mysqli_real_escape_string($_GET['score'], $db_link);
$hash = $_GET['hash'];
$secretKey=""; # Change this value to match the value stored in the client javascript below
$real_hash = md5($name . $score . $secretKey);
if($real_hash == $hash) {
// Send variables for the MySQL database class.
$query = "INSERT INTO `scores` VALUES (NULL, '$name', '$score');";
$result = mysqli_query($db_link, $query) or die('Query failed: ' . mysqli_error($db_link));
echo $result;
}
else {
echo "error"; //added for testing. This part gets echoed.
}
mysqli_close($db_link); //close the database connection
One notable "gotchu" is that the argument order is not the same between mysql_real_escape_string and mysqli_real_escape_string, so you need to swap those arguments in your conversion.
$name = mysqli_real_escape_string($db_link, $_GET['name']);
$score = mysqli_real_escape_string($db_link, $_GET['score']);
It's good that you're taking the time to convert, though do convert fully to the object-oriented interface if mysqli is what you want to use:
// Send variables for the MySQL database class.
function db_connect($db_name)
{
$host_name = "";
$user_name = "";
$password = "";
// Enable exceptions
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$db = new mysqli($host_name, $user_name, $password);
$db->select_db($db_name);
return $db;
}
$db = db_connect(""); //connect to the database using db_connect function
$secretKey=""; # Change this value to match the value stored in the client javascript below
$real_hash = md5($name . $score . $secretKey);
if($real_hash == $_GET['hash']) {
// Don't include ; inside queries run through PHP, that's only
// necessary when using interactive MySQL shells.
// Specify the columns you're inserting into, don't leave them ambiguous
// ALWAYS use prepared statements with placeholder values
$stmt = $db->prepare("INSERT INTO `scores` (name, score) VALUES (?, ?)");
$stmt->bind_param("ss", $_GET['name'], $_GET['score']);
$result = $stmt->execute();
echo $result;
}
else {
echo "error"; //added for testing. This part gets echoed.
}
// Should use a connection pool here
$db->close();
The key here is to use prepared statements with placeholder values and to always specify which columns you're actually inserting into. You don't want a minor schema change to completely break your code.
The first step to solving a complex problem is to eliminate all of the mess from the solution so the mistakes become more obvious.
The last if statement is controlling whether the mysql query gets run or not. Since you say this script is echoing "error" form the else portion of that statement, it looks like the hashes don't match.
The $hash variable is getting passed in on the URL string in $_GET['hash']. I suggest echo'ing $_GET['hash'] and $real_hash (after its computed by the call to MD5) and verify that they're not identical strings.
My hunch is that the $secretKey value doesn't match the key that's being used to generate the hash that's passed in in $_GET['hash']. As the comment there hints at, the $secretKey value has to match the value that's used in the Javascript, or the hashes won't match.
Also, you may find that there's a difference in Javascript's md5 implementation compared to PHP's. They may be encoding the same input but are returning slightly different hashes.
Edit: It could also be a character encoding difference between Javascript and PHP, so the input strings are seen as different (thus generating different hashes). See: identical md5 for JS and PHP and Generate the same MD5 using javascript and PHP.
You're also using the values of $name and $score after they've been escaped though mysqli_real_string_escape, so I'd suggest making sure Javascript portion is handling that escaping as well (so the input strings match) and that the msqli escape function is still behaving identically to the previous version. I'd suggest echo'ing the values of $name and $score and make sure they match what the Javascript side is using too. If you're running the newer code on a different server, you may need to set the character set to match the old server. See the "default character set" warning at http://php.net/manual/en/mysqli.real-escape-string.php.

PHP MySQL Query Insert consistent error

//--------------------------------------------------------------------------
// php script for adding data from mysql database
//--------------------------------------------------------------------------
$ip = $_GET['ip']; //for debugging sake, will be POST from Ajax
$key = substr(md5(microtime()),rand(0,26),5); //random referral ID - will implement exist analysis
echo $ip; //debugging
$dbhost = 'localhost';
$dbuser = user;
$dbpass = 'pass';
$conn = mysql_connect($dbhost, $dbuser, $dbpass);
if(! $conn ) {
die('Could not connect: ' . mysql_error());
}
mysql_select_db("database", $conn);
$tbl_name = "refs";
$sql="INSERT INTO $tbl_name(ip, key)VALUES('frfr', 'grgr')";
if (!mysql_query($sql,$con)) {
die('Error: ' . mysql_error());
}
echo "1 record added";
I'm not sure if it's my Digital Ocean server or what, but the only syntax my PhpMyAdmin will accept as a query is as INSERT INTOrefs(ip,key) VALUES ("insert","432")
with the double quoted values. I cannot seem to get this implemented in the PHP without getting a flat out error or an Unknown column in 'field list' error.
Similar questions suggest junk non-printable characters from copy-paste, however I've retyped my code within the editor. Thanks for all the help
I'm creating a basic referral system by the way, storing requested IP's in 'refs' table with a key, or id.
key is a reserve word and thus needs to be escaped using backtique. Along with that you have spacing issue as well. Your query should looks like below
INSERT INTO refs(ip,`key`) VALUES ('insert','432')
Never use a reserve word as column or table name. if in doubt, then escape all the columns present in query.
Start referring MySQL Documentation for more inforamtion. It's way easier than posting it as question in stackoverflow.

PHP SQL syntax error MYSQL UPDATE [duplicate]

This question already has answers here:
When to use single quotes, double quotes, and backticks in MySQL
(13 answers)
Closed 7 years ago.
So for a long time this code worked but now all of the sudden i get this error:
Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''j_users' SET patient = '', year = '', gender = '', age = '', height = 'Select a' at line 1
HELP!
define('DB_NAME', 'DATABASE');
define('DB_USER', 'USERNAME');
define('DB_PASSWORD', 'PASSWORD');
define('DB_HOST', 'localhost');
$link = mysql_connect(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);
if (!$link) {
die('Could not connect: ' . mysql_error());
}
$db_selected = mysql_select_db(DB_NAME, $link);
if (!$db_selected) {
die('Can\'t use ' . DB_NAME . ': ' . mysql_error());
}
$value = htmlspecialchars($_POST['patient']);
$value4 = htmlspecialchars($_POST['year']);
$value5 = htmlspecialchars($_POST['gender']);
$value6 = htmlspecialchars($_POST['age']);
$value7 = htmlspecialchars($_POST['height']) . '.' . htmlspecialchars($_POST['height_inch']);
$value8 = htmlspecialchars($_POST['weight']);
$value9 = htmlspecialchars($_POST['foot_length']);
$value10 = htmlspecialchars($_POST['sheight']) . '.' . htmlspecialchars($_POST['sheight1']);
$value11 = htmlspecialchars($_POST['Amputation']);
$value13 = htmlspecialchars($_POST['Side']);
$value16 = htmlspecialchars($_POST['Flesh']);
$value18 = htmlspecialchars($_POST['Activity']);
$value21 = htmlspecialchars($_POST['practitioner']);
$value22 = htmlspecialchars($_POST['phone']);
$value23 = htmlspecialchars($_POST['email']);
$value24 = htmlspecialchars($_POST['Account']);
$value25 = htmlspecialchars($_POST['companyname']);
$value26 = htmlspecialchars($_POST['streetaddress']);
$value27 = htmlspecialchars($_POST['city']);
$value28 = htmlspecialchars($_POST['state']);
$value29 = htmlspecialchars($_POST['zip']);
$value30 = htmlspecialchars($_POST['companyname2']);
$value31 = htmlspecialchars($_POST['streetadress2']);
$value32 = htmlspecialchars($_POST['city2']);
$value33 = htmlspecialchars($_POST['state2']);
$value34 = htmlspecialchars($_POST['zip2']);
$value35 = htmlspecialchars($_POST['foot']);
$value39 = htmlspecialchars($_POST['purchaseorder']);
$value40 = htmlspecialchars($_POST['radio']);
$value41 = htmlspecialchars($_POST['lightflesh2']);
$value42 = htmlspecialchars($_POST['darkfleah2']);
$value43 = htmlspecialchars($_POST['foamcalf']);
$value44 = htmlspecialchars($_POST['additional']);
$value45 = htmlspecialchars($_POST['Sock1']);
$value46 = htmlspecialchars($_POST['Sock2']);
$value47 = htmlspecialchars($_POST['Sock3']);
$value48 = htmlspecialchars($_POST['day']);
//$sql = "INSERT INTO order_form (patient, newamputee, yearamputee, year, gender, age, height, weight, foot_length, sheight, ak, bk, left1, right1, bilateral, light_flesh, dark_flesh, k2, k3, k4, k4_extrme, practitioner, email, Account, companyname, streetaddress, city, state, zip, companyname2, streetaddress2, city2, state2, zip2, UltraStride, ActiveStride, NaturalStride, K2_ComfortStride, purchaseorder, radio, lightflesh2, darkfleah2, foamcalf, additional, Sock1, Sock2, Sock3, ground, thirdday, twoday, nextday) VALUES ('$value', '$value2', '$value3', '$value4', '$value5', '$value6', '$value7', '$value8', '$value9', '$value10', '$value11', '$value12', '$value13', '$value14', '$value15', '$value16', '$value17', '$value18', '$value19', '$value20', '$value21', '$value22', '$value23', '$value24', '$value25', '$value26', '$value27', '$value28', '$value29', '$value30', '$value31', '$value32', '$value33', '$value34', '$value35', '$value36', '$value37', '$value38', '$value39', '$value40', '$value41', '$value42', '$value43', '$value44', '$value45', '$value46', '$value47', '$value48', '$value49', '$value50', '$value51')";
$update = "UPDATE 'j_users'
SET patient = '$value', year = '$value4', gender = '$value5', age = '$value6', height = '$value7', weight = '$value8', foot_length = '$value9', sheight = '$value10', Amputation = '$value11', Side = '$value13', Flesh = '$value16', Activity = '$value18', practitioner='$value21', phone='$value22', email='$value23', Account = '$value24', companyname = '$value25', streetadress='$value26', city='$value27', state='$value28', zip='$value29', companyname2='$value30', streetadress2='$value31', city2='$value32', state2='$value33', zip2='$value34', foot='$value35', purchaseorder='$value39', radio='$value40', lightflesh2='$value41', darkfleah2='$value42', foamcalf='$value43', foamcalf='$value44', Sock1='$value45', Sock2='$value45', Sock3='$value46', day='$value47'
WHERE user_login = '" . $user . "'";
if (!$update) {
die('Invalid query: ' . mysql_error());
}
mysql_query($update, $link);
if (!mysql_query($update)) {
die('Error: ' . mysql_error()) ;
mysql_close();
}
The immediate cause of the error, as pointed out by Uueerdo in the comment is the incorrect symbol (single-quote instead of a backtick) in the quoting of the name of the table - which in this case does not need to be quoted at all as it is fixed and contains no special characters.
There are other issues in the code which we will leave alone for now as they do not immediately affect the issue, but I will update the answer if OP is interested in other things that would be good to fix.
UPDATE - things to fix:
As pointed out by Drew and Uueerdo in the comments, migrate from the deprecated mysql_ interface to mysqli_ or PDO.
The values entered by the user should be escaped with mysql_real_escape_string() (with the current interface), mysqli_escape_string() or via PDO parameter holders (?) depending on the interface, but not with htmlspecialchars(). If HTML escaping is needed, it should be done immediately before the HTML is to be displayed, not at the time it is stored in the database.
Note that most of your input names match the database column names. Thus you might be better off fetching the fields from the database via SHOW FIELDS once into a hard-coded array, editing it to exclude the irrelevant ones (another option to fetch it dynamically and fix up the array once it is fetched), and adding some logic to deal with the exceptions like height and height_inches as you iterate through the array and generate your query in a loop. The code thus becomes more flexible and easier to maintain.
Create some wrapper interface for your database access rather than directly accessing MySQL API. This way should a need arise to change the interface (e.g. mysql_ to mysqli) it is a matter of fixing a few calls in just one module rather than a major code change. You are also able to add things like query logging, automatic query EXPLAIN in trace mode, performance timing, and whatever else you might think of with regard to your queries, rather easy.

What is wrong with my MySQL query?

So, I have a form that posts to my php file using ajax, and succeeds. But the following query doesn't insert anything. Can someone help me understand what I'm doing wrong?
My php file:
<?php
include 'connect.php' ;
$type = mysql_real_escape_string($_POST['type']);
$title = mysql_real_escape_string($_POST['title']);
$content = mysql_real_escape_string($_POST['content']);
if ($type == 'Just Text') {
mysql_query("INSERT INTO articles (title, type, thisisaninteger, content) VALUES ('".$title."', '".$type."', 0, '".$content."')")or die("MySQL Error: " . mysql_error());
}
?>
My connect.php:
<?php
$dbhost = "localhost";
$dbname = "example";
$dbuser = "test";
$dbpass = "test";
mysql_connect($dbhost, $dbuser, $dbpass) or die("MySQL Error: " . mysql_error());
mysql_select_db($dbname) or die("MySQL Error: " . mysql_error());
?>
If you aren't receiving any errors and the INSERT just doesn't happen, it is most likely because the if statement fails to be true. Verify that $type actually matches Just Text.
You should also be inserting values using prepared statements, and use PDO or MySQLi - this article will help you decide which.
first, echo "something" after the if statement and recall the data with your ajax post. you can find out if your if statement is working, then try formatting your variables like so
mysql_query("INSERT INTO articles (title, type, thisisaninteger, content) VALUES ('$title', '$type', 0, '$content')")or die("MySQL Error: " . mysql_error());
I just want to throw in an official vote/recommendation in favor of switching to a parameterized SQL statement, too. In spite of the use of mysql_real_escape_string, schlepping a SQL statement together via string concatenation is neither necessary nor a good idea. Honestly, I find a prepared statement much, much easier to read than the typical string-concatenation exercise, as well:
$stmt = $dbh->prepare("SELECT * FROM users WHERE USERNAME = ? AND PASSWORD = ?");
$stmt->execute(array($username, $password));
Alright, it was a stupid mistake on my side. There were columns I didn't include and they were not being assigned a value. Thanks everyone for helping out.

PHP attempt to update a MySQL database doesn't update anything

I have my code below to update a my MySQL database, it's running but is not updating the database when I check rcords using phpmyadmin. plae hlp me.
$database = "carzilla";
$con = mysql_connect("localhost","root","");
if (!$con)
{
die('Could not connect: ' . mysql_error());
}
$manufacturerTable = $_POST[vehicleManufacturer];
$numberToSearch = $_POST[vehicleIdNo];
$engineType = $_POST[engineType];
$engineCC = $_POST[engineCC];
$year = $_POST[year];
$numberofDoors = $_POST[numberofDoors];
$tireSize = $_POST[tireSize];
$chasisNumber = $_POST[chasisNumber];
$vehicleMake = $_POST[vehicleMake];
$price=$_POST[price];
mysql_select_db("$database", $con);
$sql = mysql_query("UPDATE $manufacturerTable SET username='vehicleMake',
engineType='$engineType', engineCC='$engineCC', year='$year', chasisNo='$chasisNumber', numberOfDoors='$numberofDoors' ,numberOfDoors='$numberofDoors', tireSize='$tireSize', price='$price' WHERE `index` ='$id'");
if (!mysql_query($sql,$con))
{
die('Error: ' . mysql_error());
}
echo 'record has been successfuly';
mysql_close($con);
?>
Take a good look at your query. You are referring to PHP variables in several different fashions in the same statement. In the query $manufacturerTable is just $manufacturerTable, you encase a few others in single quotes, some of which you remove the $ from, others you do not. I know I preach this far too often, but you should really look into using prepared statements. They take all the guess work out of using variables in your queries, and they prevent you from being victimized by injection hacks. But the short answer here is that you are not referencing your variables correctly in the query.
Sometimes putting the variables directly in the syntax can cause issues. Have you tried to use concatenation for the query.
$query = "UPDATE ".$manufacturerTable." SET username='vehicleMake', engineType='."$engineType."', engineCC='".$engineCC."', year='".$year."', chasisNo='".$chasisNumber."', numberOfDoors='".$numberofDoors."' ,numberOfDoors='".$numberofDoors."', tireSize='".$tireSize."', price='".$price."' WHERE index =".$id;
$sql = mysql_query($query); # this should be put in the if else
If index is number based you do not need the '' surrounding it. Plus is username='vehicleMake' or is it a variable. if it is a variable, add the $ or use concatenation like the rest. Your SQL check should be something like follows.
if (mysql_query($query))
{
echo 'record has been successfuly';
} else {
die('Error: ' . mysql_error() . ' | ' . $query);
}
The reason you export the query is so you can try it manually to make sure it works and what error you may be getting. phpMySQL can show a different error then the mysql_error() at times
Plus you should be escaping all input that is user entered using mysql_escape_string() or mysql_real_escape_string()

Categories