Is this update statement missing something? - php

I have made a database where email id and corresponding name and password is stored. I have successfully obtained a form's data.. where the user enters updated name and password. But the problem is occuring with the query which is as follows
$db = mysqli_connect(all details)...
$name = $_POST['name'];
$password = $_POST['password']:
$email = $_POST['email'];
$query = "UPDATE mytable SET name='$name',password='$password' WHERE emailid='$email'";
$result = mysqli_query($db,$query);
Though I am getting all form values succesffuly and until and unless I put the 'where' clause.It works.But obviously updates all values. i want it to work with where..but so far unsuccessful :(

you need to put {} around the variables if its surrounded by quote ''
so your query should look like this
$query = "UPDATE mytable SET name='{$name}',password='{$password}' WHERE emailid='{$email}'";
$result = mysqli_query($db,$query);
EDIT : also before saving data to database make sure to filter and validate data

You need to make sure that emailid exists in mytable, you truly intended to filter by it and in your database scheme it has a type which supports the posted data. It seems that you are sending strings, like 'foo#bar.lorem' and your emailid is an int or something in the database scheme. Check it by running
desc mytable;
You need to put curly brackets around variables if you use apostrophe around them, but as a matter of style I like to close the string and attach the $variable with a . as this coding style is closer to me personally.
If everything fails, see what is generated, by echoing out the query string, try to run that directly, see what the error is and fix until...
... until it is fixed.
Also, you do not encrypt the password and your code is vulnerable to SQL injection too. Please, read about password encryption and SQL injection and then protect your project against these dangers.

You can write your statement as:
$query = "UPDATE mytable SET name='".$name."',password='".$password."' WHERE emailid='".$email."'";
using . as string concatenating operator

Related

Is there a way to demonstrate SQL injection with mysqli?

I want to make a quick and easy demonstration about how SQL injection work. And I've solved some of my problems. I have a table with random usernames, passwords and emails in, and I'm able to "inject" SQL code to view all of the users in a search with this injection:
' OR '1'='1
This is how my PHP code looks for searching for "members":
if (isset($_POST['search'])) {
$searchterm = $_POST['searchterm'];
echo $searchterm . '<br>';
/* SQL query for searching in database */
$sql = "SELECT username, email FROM Members where username = '$searchterm'";
if ($stmt = $conn->prepare($sql)) {
/* Execute statement */
$stmt->execute();
/* Bind result variables */
$stmt->bind_result($name, $email);
/* Fetch values */
while ($stmt->fetch()) {
echo "Username: " . $name . " E-mail: " . $email . "<br>";
}
}
else {
die($conn->error);
}
}
Now I want to demonstrate some more fatal problems, like someone truncating your whole table. So I tried this code in the search bar:
'; TRUNCATE TABLE Members; --
But I get this error message:
You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'TRUNCATE TABLE Members; -- '' at line 1
It seems like I get an extra ', but I don't know how to get rid of it, though the -- would comment that out. First I thought that the problem was that I had no whitespace behind the -- but adding a whitespace didn't make any difference.
I have tried switching to PDO, because I thought there was a problem with mysqli not accepting multiple queries, but then I somewhere read that PDO doesn't support that either, but I don't know.
Is there a way I can make it work?
I later found that PDO supports multi-querying by default, but when I tried it it didn't work. Maybe I bound the parameters wrong. But I couldn't even make a simple select query to work.
mysqli_query() does not support multi-query by default. It has a separate function for that: mysqli_multi_query().
SQL injection is not only about running multiple statements, the famous XKCD cartoon notwithstanding.
Your code has a bad SQL injection vulnerability. Do you think that using prepare() somehow makes a query safe, even though you interpolate content from your $_POST request data directly into the SQL string?
Your code is this:
$searchterm = $_POST['searchterm'];
$sql = "SELECT username, email FROM Members where username = '$searchterm'";
if ($stmt = $conn->prepare($sql)) {
/* execute statement */
$stmt->execute();
...
It's easy for unsafe input to make SQL injection mischief this way. It might even be innocent, but still result in problems. Suppose for example the search is: O'Reilly. Copying that value directly into your SQL would result in a query like this:
SELECT username, email FROM Members where username = 'O'Reilly'
See the mismatched ' quotes? This won't do anything malicious, but it'll just cause the query to fail, because unbalanced quotes create a syntax error.
Using prepare() doesn't fix accidental syntax errors, nor does it protect against copying malicious content that modifies the query syntax.
To protect against both accidental and malicious SQL injection, you should use bound parameters like this:
$searchterm = $_POST['searchterm'];
$sql = "SELECT username, email FROM Members where username = ?";
if ($stmt = $conn->prepare($sql)) {
$stmt->bind_param('s', $searchterm);
/* execute statement */
$stmt->execute();
...
Bound parameters are not copied into the SQL query. They are sent to the database server separately, and never combined with the query until after it has been parsed, and therefore it can't cause problems with the syntax.
As for your question about mysqli::query(), you may use that if your SQL query needs no bound parameters.
Re your comment:
... vulnerable to injection, so I can show the students how much harm a malicious attack may [do].
Here's an example:
A few years ago I was an SQL trainer, and during one of my trainings at a company I was talking about SQL injection. One of the attendees said, "ok, show me an SQL injection attack." He handed me his laptop. The browser was open to a login screen for his site (it was just his testing site, not the real production site). The login form was simple with just fields for username and password.
I had never seen his code that handles the login form, but I assumed the form was handled by some code like most insecure websites are:
$user = $_POST['user'];
$password = $_POST['password'];
$sql = "SELECT * FROM accounts WHERE user = '$user' AND password = '$password'";
// execute this query.
// if it returns more than zero rows, then the user and password
// entered into the form match an account's credentials, and the
// client should be logged in.
(This was my educated guess at his code, I had still not seen the code.)
It took me 5 seconds to think about the logic, and I typed a boolean expression into the login form for the username, and for the password, I typed random garbage characters.
I was then logged into his account — without knowing or even attempting to guess his password.
I won't give the exact boolean expression I used, but if you understand basic boolean operator precedence covered in any Discrete Math class, you should be able to figure it out.
Did you try something like this ?
'(here put something);
in this way you are going to close the query with ' and add other stuff to it, when you add ; everything else is going to be discarded

Insert mysql error when parsing a webpage

Hi when ever I want to insert a comment into my database, I sanitize the data by using Mysql Escape String function this however inserts the following verbatim in field. I print the comment and it works fine and show me the text however when ever I sanitize it, it literally inserts the following into my db
mysql_real_escape_string(Comment)
This is my insert statement, The Id inserts correctly however the comment doesn't it just inserts the "mysql_real_escape_string(Comment)" into the field. what can be wrong?
foreach($html->find("div[class=comment]") as $content){
$comment = $content->plaintext;
$username = mysql_real_escape_string($comment);
$querytwo = "insert into Tchild(Tid,Tcomment)values('$id','$username')";
$resulttwo = $db -> Execute($querytwo);
}
If I'm reading the documentation correctly, you should make the call like this:
$db->Execute("insert into Tchild(Tid,Tcomment)values(?, ?)", array($id, $username));
That will account for proper escaping. Having unescaped values in your query string is dangerous and should be avoided whenever possible. As your database layer has support for SQL placeholders like ? you should make full use of those any time you're placing data in your query.
A call to mysql_real_escape_string will not work unless you're using mysql_query. It needs a connection to a MySQL database to function properly.
Since you're using ADODB, what you want is probably $db->qstr(). For example:
$username = $db->qstr($comment, get_magic_quotes_gpc());
See this page for more information: http://phplens.com/lens/adodb/docs-adodb.htm

Inserting values into mysql

I've user profile update page and have some forms to update, here they are
NAME
SURNAME
password
phone
And I am trying to make this update without big script, I mean I don't want to define if for example NAME exists or not and so on. I want that if any marked form value exists it changed in mysql. How I know this is possible with mysqli_prepare statement. I've written sql like this
$stmt = "UPDATE table SET NAME=?,SURNAME=?,PASSWORD=?,PHONE=? WHERE email='" . $email . "'";
but something wrong, any ideas how to do it ? And also please advice why it is better way to use mysqli_prepare , why it is safe too ?
PS. I do not write php script because I've not any problem with it
UPDATE
I've marked sql statement and above this script in php I am writting this =>
if (isset($_POST['name']){
$name = $_POST['name'];
} else {
$name = null;
}
and so on ...
but it doesn't execute , nothing error msg is shown up , because I think something wrong with sql statement
Just want if some of detail is filled it updated and if all fields are filled all updated, how to write with script?
I can not understand this question marks in sql statement , does it means that if for example NAME is not exists it is ignored ?
The question marks in your SQL string not part of the SQL syntax, they are placeholders for the actual parameters. If you want to do it like this, you should first make a SQL statement, and then set the parameters.
Something like
$con = new mysqli($hostname,$username,$password,$database);
$statement = $con->prepare( "UPDATE table SET NAME=?,SURNAME=?,".
"`PASSWORD`=?,PHONE=? ".
" WHERE email=?");
$statement->bind_param("sssss",$name,$surname,$pass,$phone,$email);
example derived of http://www.xphp.info/security/getting-started-with-mysqli/
Also note the comment of ThiefMaster: password is a reserved word in MySQL so you will need to put it in backticks (``)
Alternatively you directly insert the values into the mysql string, like you initially did with the email address. You need to escape the values in that case, by using mysql_real_escape_string()
Note that you are in both cases replacing ALL values with what was set, be it NULL or a string, or whatever.

Trying to delete an entry in a database, recieve an sql error but can't work out how

I am doing a really simple script to delete a row out of a database. I have done it before with almost identical code but for some reason this wont work!
Viewmessages.php has no problem running but when I try and delete the row using deletemessage.php I receive the an sql error, I only have one line of sql:
viewmessage (sending info to deletemessage.php):
echo "<a href='deletemessage.php?contactname=".$contactname."'>Delete</a>";
The following is the delete message code:
<?php
session_start();
if ( !isset($_SESSION['adminusername']))
{
header("Location:admin.php");
exit();
}
require "dbconn.php";
$contactname = $_GET['contactname'];
$query = "DELETE FROM message WHERE contactname =".$contactname;
$results = mysql_query($query) or die(mysql_error());
header("Location: viewmessages.php");
?>
I cant work out what the error is! $contactname in the viewmessages.php file definately speaks of the primary key for the table!
Any Ideas?>
EDIT: I know that the problem lies with the contactname in the sql... for some reason it is not recieving it well, I did an echo to see what it thought the contactname was and it was correct. I then changed the variable and put in a string of one values in contactname and it deleted the row correctly... so the problem is the GET_['contactname'] but I am not sure what....
Enclose $contactname in quotes in the query, since it is a string. But escape it first! It is highly vulnerable to SQL injection the way it is now. I understand it may be an administrative page, but it is a very good habit to always observe, even when your users are trusted. (Especially since Mr O'Malley would break the SQL statement when you tried to delete him)
$concatname = mysql_real_escape_string($_GET['contactname']);
$query = "DELETE FROM message WHERE contactname ='".$contactname . "'";
Always beware when deleting via a hyperlink. Looks like you are checking for admin privileges before allowing this to execute, but be sure these links are not accessible to the broad Internet, where they might get crawled.
Wild guess here? $contactname is a STRING. Therefore it must be in quotes in the query. Also, you want people to destroy your database, apparently.
$query = "DELETE FROM `message` WHERE `contactname` = '".mysql_real_escape_string($contactname)."'";
You need quotes around a string you're inserting.
$query = "DELETE FROM message WHERE contactname ='".$contactname."'";
Note that this is MASSIVELY vulnerable to SQL injection. Someone could delete your entire database table with this code as it stands.

mysql_real_escape_string again if copying data?

Before I put data into my database I pass it through mysql_real_escape_string.
If I want to copy that same data into another table, do I need to pass it through mysql_real_escape_string again before I copy it?
I wrote a small script to test the issue and it looks like the answer is yes:
$db = new AQLDatabase();
$db->connect();
$title = "imran's color";
$title = mysql_real_escape_string($title);
$sql = "insert into tags (title, color) values ('".$title."','#32324')";
$db->executeSQL($sql);
$sql = "select * from tags where color = '#32324' ";
$result = $db->executeSQL($sql);
while($row= mysql_fetch_array($result))
{
$new_title = $row['title'];
}
$new_title = mysql_real_escape_string($new_title);
$sql = "insert into tags (title, color) values ('".$new_title."','DDDDD')";
$db->executeSQL($sql);
NOTE: If I remove the second mysql_real_escape_string call, then the second insert won't take place
Are doing something like this?
save mysql_real_escape_string($bla) to database
fetch $bla from database
save $bla again (in another table..)
Fetching $bla from the database will "unescape" it so it could be a harmful string again. Always escape it again when saving it.
Before I put data into my database I always make it go the Mysql_real_Escape_String thing.
You are doing right. Just keep it as is. Not database though but query it is.
The only note: only strings should be escaped using this function. It shouldn't be used with any other query parts.
do I need to make it go through the Mysql_real_Escape_String again before I copy it?
Didn't you answer your question already? Before I put [string-type] data into my [query] I always make it go the Mysql_real_Escape_String thing. Is your data going to SQL query? So, here is an answer you have already.
Well, if you are sure this data is already properly escaped, there is no need to.
mysql_real_escape_string is for 1) escaping 2) security purposes. Since it's your own data base and as long as you pass data to another database outside a potential hacker reach - you are already safe
Its already scaped, just copy it as is, if you want to undo the mysql_real_escape_string you can use stripslashes($sting) to remove it
PD: This is false and now i understand why.

Categories