I'm experiencing a strange problem with save query, and I'd like to better understand how to solve it.
I have a database with 2 tables, example:
TBL_PERSON
person_id
person_name
person_telephone
TBL_ADDRESS
address_id
address_person_id
address_address
address_city
address_zip
Now, I use a query like this to store records:
$sqlQuery = "INSERT INTO TBL_PERSON (
person_name,
person_telephone
) VALUES (
'$person_name',
'$person_telephone'
)";
$result = MYSQL_QUERY($sqlQuery);
//Get last id
$address_person_id = mysql_insert_id();
$sqlQuery = "INSERT INTO TBL_ADDRESS (
address_person_id,
address_address,
address_city,
address_zip
) VALUES (
'$address_person_id',
'$address_address',
'$address_city',
'$address_zip'
)";
$result = MYSQL_QUERY($sqlQuery);
Sometimes, no record is added on TBL_ADDRESS.
After the user presses Insert, Action Button, Name and Telephone are stored on TBL_PERSON, but not address on TBL_ADDRESS.
Barring the discussion on the use of deprecated an insecure mysql_* functions, I think this is a good opportunity to explain methods of debugging issues like this.
In the replacements for the mysql_* query functions, exceptions are thrown on errors allowing you to wrap the query in a try/catch block and handle it accordingly. In the case of mysql_query(), you will simply get false returned from the function. So to be able to debug and consequently see what is wrong, you need to do something like this (from the PHP manual):
$result = mysql_query('SELECT * FROM myTable');
if (!$result) {
die('Invalid query: ' . mysql_error());
}
If your query fails, you will see why, which is important in debugging.
As mentioned in the comments, you do not escape any of your values. Aside from the fact that you shouldn't be using these functions at all (see mysqli or PDO), you should at minimum be escaping your values using the mysql_real_escape_string() method:
$value = mysql_real_escape_string($value);
If you follow the above logic, you will see what is causing the issue, and I suspect fix it successfully using proper escaping of values. If it's not the value, you may have an issue with your database schema design such as a column that is not nullable and has no default value, yet you may be passing a null value.
Related
I am trying to get the reputation of a union (everyone who is in the unions reputation added)
$the_member = mysql_query("SELECT `reputation` FROM `stats` WHERE `id` in (SELECT `id` FROM `user` WHERE `union`='".$id."')") or die(mysql_error());
Thats what I have So far and if you echo it its just blank, no errors and no text.
If you read the PHP doc for mysql_query, you'll see an example that shows you how to use it. Basically you need to use mysql_fetch_assoc (or some similar function) to get the actual data, like this:
while ($row = mysql_fetch_assoc($the_member)) {
echo $row['reputation'];
}
Warning: try not to use mysql_query, it's deprecated. Use mysqli_query, or better yet, PDO. It's all in the link above. Also, you need to make sure the $id value doesn't contain anything that would break your query. This is called "SQL injection", and in certain cases it lets anyone run an arbitrary query. Consider the case when $id == "'); drop table user; --"
I've made a simple search-script in PHP that searches a mySQL database and outputs the result. How this works is like this:
User searches for "jack's" through a search-form.
My PHP-script GETs this search, and sanitizes it.
Then the script, with the use of SELECT and LIKE, gets the results.
The script then outputs the result to the user.
Lastly, the script tells the user that "jack's returned x results." with the help of escaping.
What I would like to ask is, am I doing it right?
This is how I sanitize before SELECTING from the database:
if(isset($_GET['q'])){
if(strlen(trim($_GET['q'])) >= 2){
$q = trim(mysql_real_escape_string(addcslashes($_GET['q'], '%_')));
$sql = "SELECT name, age, address FROM book WHERE name LIKE '%".$q."%'";
}
}
And this is how I escape before outputting "jack's returned x results.":
echo htmlspecialchars(stripslashes($q)) . " returned x results.";
Is this the correct way to do it?
By the way, I know that PDO and mySQLi is preferred as they sanitize themselves through the use of prepared statements, but I have no real experience with them whatsoever. But I would gladly take a look, if you guys could link me some newbie tutorials/explanations.
Furthermore, I heard that magic_quotes and charset could in some way or another lead to injections -- is this correct?
For some reason we need also escape a backslash too.
So, the proper code would be, I believe
if(isset($_GET['q'])){
$_GET['q'] = trim($_GET['q']);
if(strlen($_GET['q']) >= 2){
$q = $_GET['q'];
$q = '%'.addCslashes($q, '\%_').'%';
// now we have the value ready either for escaping or binding
$q = mysql_real_escape_string($q);
$sql = "SELECT name, age, address FROM book WHERE name LIKE '$q'";
//or
$sql = "SELECT name, age, address FROM book WHERE name LIKE ?";
$stm = $pdo->prepare($sql);
$stm->execute(array($q));
$data = $stm->fetchAll();
}
}
For the output, use
echo htmlspecialchars($_GET['q']);
stripslashes not needed here.
Furthermore, I heard that magic_quotes and charset could in some way or another lead to injections -- is this correct?
magic quotes won't harm your security if you won't use them.
charset is dangerous in case of some extremely rare encodings but only if improperly set. if mysql(i)_set_charset or DSN (in case of PDO) were used for the purpose - you are safe again.
As for PDO, a tag wiki should be enough for starter, I believe
I am trying to compare an Email address stored in a database to one entered in the input however it is not recognizing:
I am trying to select a colum from my db with:
$query = mysql_query("SELECT * FROM `men` WHERE `Email`=$user_email");
however the query returns 0 even though the emails are exactly the same. What is the issue here
There are many issues. This query will interpolate to Email = email#example.com which is a syntax error in MySQL.
You should be checking for errors after mysql_query with something like mysql_query($query) or echo mysql_error()
You need to wrap $user_email in quotes so it interpolates to Email = 'email#example.com', which is the valid/desired query.
You should not even be using ext/mysql at all; it is deprecated. See big pink box.
Your code is vulnerable to injection because the query is not properly parameterized.
A much better alternative would be (in PDO):
$query = $pdo->prepare("SELECT * FROM `men` WHERE `Email` = ?");
$query->execute(array($user_email));
$result = $query->fetch();
Note that my comments about error checking and parameterization still apply to PDO.
I have a database. I had created a a table containing only one row in DB if it wasn't constructed before.
Why it has only 1 row is that I just use it to keep some info.
There is a field of TYPE NVARCHAR(100) which I want to use it to store session id,
and here comes the headache for me:
It seems that I can't even properly INSERT(I use phpmyadmin to check and it's blank) and UPDATE(syntax error...) it with a session id obtained from session_id(), which is returned as a string.
Here is the portion of my code relating to my action:
//uamip,uamport is in URL;I use $_GET[]
$_SESSION[uamport] = $_GET['uamport'];
$_SESSION[uamip] = $_GET['uamip'];
**$_SESSION[sid] = session_id();**
//construct
$sql="CREATE TABLE trans_vector(
`index` INT NOT NULL AUTO_INCREMENT,
`sid` NVARCHAR(100),
`uamip` CHAR(15),
`uamport` INT,
PRIMARY KEY (`index`)
)" ;
mysql_query($sql);
//insert(first time, so not constructed)
$sql="INSERT INTO trans_vector (sid,uamip,uamport) VALUES(
'$_SESSION[sid]',
'$_SESSION[myuamip]',
'$_SESSION[myuamport]'
)";
mysql_query($sql);
//update(from 2nd time and later, table exists, so I want to update the sid part)
$sql="UPDATE trans_vector SET sid="**.**$_SESSION[sid];
mysql_query($sql)
Now, when I use phpmyadmin to check the sid field after INSERT or UPDATE, It is blank;
But if I do this:
$vector=mysql_fetch_array(mysql_query("SELECT TABLES LIKE 'trans_vector'"));
and echo $vector[sid] ,then it's printed on webpage.
Another question is:
With the UPDATE statement above, I always get such error:
"Unknown column xxxxxx....(some session id returned, it seems it always translate it first and put it in the SQL statement, ** treating it as a column NAME** that's not what I want!)"
I tried some TYPE in CREATE statement, and also lots of syntax of the UPDATE statement(everything!!!) but it always give this error.
I am dealing trouble with ' and string representation containing a variable where the latter's value is actually what I want... and maybe the problem arise from type in CREATE and string representation in UPDATE statement?
Should CAST() statement helpful for me?
Wish you can help me deal with this...and probably list some real reference of such issue in PHP?
Thanks so much!!
$insert = "INSERT INTO trans_vector (`sid`, `uamip`, `uamport`) VALUES(
'".$_SESSION["sid"]."',
'".$_SESSION["myuamip"]."',
'".$_SESSION["myuamport"]."'
)";
this should solve at least some warnings, if not errors.
and for update...
$update = "UPDATE trans_vector SET `sid`='".$_SESSION["sid"]."';";
Notes about your code:
Array values have to be put into the string with operator '.' and cannot be inserted directly. Array indexes must be strings (note the ") or integers.
Column names should have `` around them. To insert a string with SQL, you have to put string into ''s, so the parser knows what is string and what column name. Without ''s parser is assuming you are stating a column.
and for mysql_escape_string, I assumed you handle that before storing data to sessions. Without those, you might can get unwanted SQL injections. And in case you did not do that, you can either do that (before you create queries):
foreach($_SESSION as $key => $value)
$_SESSION[$key] = mysql_escape_string($value);
or manually escape strings when you create a query.
As for the update statement, it’s clear that there are apostrophes missing. You always need apostrophes, when you want to insert a string value into the database. Moreover, you should use mysql_real_escape_string.
However, I think standard mysql is deprecated and has been removed in newer versions of PHP in favor of MySQLi and PDO. Thus you should switch to MySQLi or PDO soon.
You should also use apostrophes when referencing values within $_SESSION. Otherwise PHP will try to find a constanst with the name sid and later fallback to the string 'sid'. You will get into trouble if there once really is a constant called sid defined.
Here, the corrected update statement in mysql library:
$sql = "UPDATE trans_vector SET sid='" . mysql_real_escape_string($_SESSION['sid']) . "'";
Even better:
$sql = "UPDATE `trans_vector` SET `sid`='" . mysql_real_escape_string($_SESSION['sid']) . "'";
Using backticks makes clear for MySQL that this is a column name. Sometimes you will have column names that are called like reserved keywords in SQL. Then you will need apostrophes. A common example is a column called order for the sequence of entries.
If we can't use PDO or mysqli (for any reason), is this method safe for INSERT and SELECT?
<?php
if (!empty($_POST[id]) && !empty($_POST[name])) {
require_once ( 'config.php' );
// SAFE INTVAL ID
$id = intval($_POST[id]);
$connect = mysql_connect("$server", "$user", "$password")
OR die(mysql_error());
mysql_select_db("$database", $connect);
// ESCAPING NAME
$name = mysql_real_escape_string($_POST[name]);
$query = "INSERT INTO table (id, name) VALUES ('$id', '$name')";
$result = mysql_query($query, $connect);
if (!$result) { echo 'success'; } else { echo 'fail'; }
}
?>
cause i've read many times never to use mysql_query,
is it dangerous even if we are careful and escape in time?
As per my knowledge, your query is perfectly fine.
You are escaping the SQL with
mysql_real_escape_string($_POST[name])
This adds additional security to your code.
The only suggestion is that use:
$_POST['name']
instead of
$_POST[name]
As it will generate PHP warning.
Thanks.
To add to the other answers, it's "safe", as in the query can't be exploited. The one thing to watch out for though is that you're trusting your users to provide you with an ID (which I assume here is your primary key). Of course, this means that your users can overwrite other records.
A better way would be to omit the id column (and its value) from your query, and mark the column as AUTO_INCREMENT when creating the table. Any omitted value from a query becomes its default value, which in this case will normally be the last value of id+1.
Even though you say you can't use them, possibly because they're too complicated (?), you really should doing a little research and understanding how to use them. I promise that once you do, you won't even want to go back! :) I recommend using PDO / MySQLi because PHP 5.5 is depreciating MySQL and you'll get E_DEPRECIATED notices.
Prepared statements using MySQLi or PDO mean that you don't have to escape any strings, you simply refer to each variable with a ?, and then state later on what datatype the ? has s being string, for example.
You wouldn't need to use mysql_real_escape_string() then. Future proof your code! :)