Retrieving email addresses with special characters using MySQL query - mysql

I am fairly new to PHP and Mysql. The question I am going to ask will be begging for someone to tell me to use prepared statements so first of all let me say I am learning this, but not quite there yet. I have a query that looks to see if an email address is in the database. The email addresses may contain unusual characters like - , / | "" etc etc. I can't seem to retrieve them - here is my code (the repeatemail is coming from a form). Works perfectly with email addresses without this characters.
$checkemail = $_POST['repeatemail'];
$checkemail = mysqli_real_escape_string($con, $checkemail);
//Perform database to see if email exists
$query = "SELECT email FROM scorers WHERE email = '{$checkemail}'";
$result = mysqli_query($con, $query);
$row = mysqli_fetch_row($result);
if ($row[0] == $checkemail){
echo "found";
} else {
echo "not found";
}
As it stands I have wondered if the escape string is stripping the unusual characters and therefore once its queried it been altered but that doesn't seem to be the case. Also, I have no problem entering addresses like simon.o'malley#nhs.uk but just can't check them with the above code. Looked up many explanations regarding UTF etc but its a bit above my head at this point. Could someone give me a solution to this....how do I alter the code above so it will pick out these funky email addresses? Many thanks

Got it...this works fine but if any of you have major concerns let me know. Its the magic quotes issue that seemed to be the only problem. All other characters seem fine
$checkemail = $_POST['repeatemail'];
$check_email_no_slashes = $checkemail;
$checkemail = mysqli_real_escape_string($con, $checkemail);
echo $check_email_no_slashes . "</br>";
//Perform database to see if email exists
$query = "SELECT email FROM scorers WHERE email = '{$checkemail}'";
$result = mysqli_query($con, $query);
$row = mysqli_fetch_row($result);
if ($row[0] == $check_email_no_slashes){ etc etc etc .......}
Thanks for your input Tim.

You really need to use prepared statements. If you don't, you're asking for SQL injection issues (see http://en.wikipedia.org/wiki/SQL_injection). For example, I could send you an email address that would delete all the rows in your table.
Prepared statements aren't hard; here's an example:
$stmt = $mysqli->prepare("SELECT email FROM scorers WHERE email = ?")
// use the string in $checkemail in place of the ?
$stmt->bind_param("s", $checkemail);
// run the query
$stmt->execute();
// put the result into $email
$stmt->bind_result($email);
if ($stmt->fetch()) {
// found a matching email; do something about it
}
$stmt->close();
You can read more about prepared statements in the PHP docs: http://php.net/manual/en/mysqli.prepare.php

Related

SQL - Database search gives error when user form input search criteria contains apostrophe

I have a database of mountains the names of which often contain an apostrophe, e.g. Beinn A'Chroin. All my search criteria work fine except when the user inputs a search via the form with the apostrophe included, i.e. Beinn A'Chroin, and then it throws up an error - Beinn A will work, Chroin will work, but never with the apostrophe. As most users will invariably insert the proper name, including the apostrophe I would prefer always to have it in the table data - Your help appreciated - Thanks John
The relative portion of my code is:
$srch = $_POST['srch'];
// Prepare query
// Named Mountain Search Search for:
if ($srch != '') { //Options for specific walk types in a specific area selected
$query = "SELECT walk, status, distance, report, dateofwalk FROM walkslist WHERE walk LIKE '%$srch%' ORDER BY walk ASC;";
update your code use PDO
try {
$conn = new PDO("mysql:host=$host;dbname=$dbname", $username, $password);
$sql = 'SELECT walk, status, distance, report, dateofwalk
FROM walkslist WHERE walk LIKE ? ORDER BY walk ASC;';
$q = $conn->prepare($sql);
$q->execute(array('%$srch%'));
$q->setFetchMode(PDO::FETCH_ASSOC);
while ($r = $q->fetch()) {
}
} catch (PDOException $pe) {
die("Could not connect to the database $dbname :" . $pe->getMessage());
}

Placing PHP variable inside SQL

I am trying to send city from a page to another and then show items from database where city is the mentioned city but this code does not return any results. Please guide. I am sure everything else is fine with the code.
$city = $_POST["city"];
$sql = "SELECT id,full_name, email, password,full_address,city,age,contact_number,gender,education FROM users WHERE city=$city";
// strip tags from the input
$city = strip_tags($_POST["city"]);
// escape the input to prevent sql injection (assuming you are using mysqli() as your connection method...)
$city = mysqli_real_escape_string($city);
// your query does not work because you need to put strings inside single quotes
$sql = "SELECT id,full_name, email, password,full_address,city,age,contact_number,gender,education FROM users WHERE city='$city'";
Actually, you're not even executing the request on your mysql server, but if you are using PDO (what you SHOULD do), just do something like this:
<?php
$bdd = new PDO(etc);
$req = $bdd->prepare("SELECT id,full_name, email, password,full_address,city,age,contact_number,gender,education FROM users WHERE city=?");
$req->execute(array($_POST['city']));
print_r($req->fetchAll());
?>
And here you go, $req->fetchAll() will return you an array with each element returned by your request, and the best part is that prepare will prevent you from every SQLi
Edit: You can use short syntax for array [$_POST['city']] or old and complete syntax: array($_POST['city'])

how to inject sql in login process

I've received an old application which completely lacks user input sanitization and is vulnerable to sql injection. To prove gravity of the situation i need to give client an example and what can be better to scare him than the login process. I've tried standard techniques but the problem with them is that they return multiple rows and due to nature of the code it returns an error instead of logging him in. What sql should i inject so that only a single row is returned and the execution reaches "return $access" line in order to pass the value of this "access" column to code calling this login function. The request is made via POST method and magic quotes are off on the server. Please let me know if you need any other information.
function login($username, $pw)
{
global $dbname, $connection, $sqluser, $sqlpw;
$db = mysql_connect($connection,$sqluser,$sqlpw);
mysql_select_db($dbname);
if(!($dba = mysql_query("select * from users where username = '$username' AND password = '$pw'"))){
printf("%s", sprintf("internal error5 %d:%s\n", mysql_errno(), mysql_error()));
exit();
}
$row = mysql_fetch_array($dba);
$access = $row['access'];
if ($access != ''){
return $access;
} else {
return "error occured";
}
mysql_close ($db);
}
Note: it turns out that magic_quotes_gpc is turned on and the php version is 5.2.17
Thanks
Starting with the goal query:
SELECT *
FROM users
WHERE username = '' OR '1'='1'
AND password = '' OR 1=1 LIMIT 1;#'
We get username is ' OR '1'='1 and password is ' OR 1=1 LIMIT 1;#
It depends what values the login function is called with. If there's sanitation before passing it to the function it might actually be safe. However it's better to filter it right before the query so you can see that your built query is safe.
However if you have something like this:
login($_POST['user'], $_POST['pass']);
In that case just put foo' OR 1=1 OR ' in the user field in the login form :)

Query only working on PHPMyAdmin

I'm trying this query:
//connect;
$site = mysql_real_escape_string($_GET['site']);
$data = mysql_query("SELECT * FROM Items WHERE Site = '$site'");
while($row = mysql_fetch_array( $data ))
{
print $row['type'];
}
doesn't print anything, running SELECT * FROM Items WHERE Site = 'http://rollingstone.com/' from PHPMyAdmin returns one row.
I'm sure it must be something really basic, since I haven't got much experience with MySQL.
I'm trying it here btw: http://www.chusmix.com/game/insert/get-items.php?site=http://rollingstone.com/
What am I doing wrong?
Make sure $site actually contains something; doing a quick echo $site before your mysql_query() should tell you this. If it's empty, try print_r($_GET) to see if it's in the $_GET array. It should be, but it might not for some other reason; check any code above this snippet for stuff that modifies $_GET or $_REQUEST in any way.
To request data from a MySQL table, you need to connect to the server using mysql_connect(), then select the database with mysql_select_db(). PHP should throw errors, but to be sure put these lines at the top of your script:
error_reporting(E_ALL);
ini_set('display_errors', '1');
All errors will now be shown.
In addition, you can also test for how many rows that were returned using mysql_num_rows(). For example:
if(mysql_num_rows($data) !== false)
{
while(...)
{
...
}
}
else
{
echo "No rows";
}
Will echo No rows if there weren't any results from the query. This is all error detection code; the cause of your error isn't obvious, so a little investigation is necessary, using the above methods (and any more you can think of).
Have you called mysql_select_db('your_database_name'); on the connection first? Have you tried echoing out the SQL before it's executed to confirm that Site is what you expect it to be?
$query = sprintf("SELECT * FROM Items WHERE Site ='%s'",
mysql_real_escape_string($site));
$result = mysql_query($query);
Just to be on the safe side (avoid SQL Injections).

Making a form submit a variable safely

while($info = mysql_fetch_array( $data )) {
// Print out the contents of the entry
Print "<li><b>Name:</b> ".$info['name'] . " <br />";
Print "<b>ID:</b> ".$info['ID']." <br />";
Print "<b>Age:</b> ".$info['age'] ." <br />";
Print "<b>Location:</b> ".$info['location'] ."<br /> ";
Print "<form action=delete.php method=POST><input name=ID value="safe(.$info['ID']." type=hidden><input type=submit name=submit value=Remove class=submit></form></li>";
}
Print "</ol>";
That's my code. I am, however, focusing on this line:
Print "<form action=delete.php method=POST><input name=ID value=".$info['ID']." type=hidden><input type=submit name=submit value=Remove class=submit></form></li>";
As has been pointed out in one of my previous posts, it's not safe against a SQL injection attack.
I've borrowed this function from another post:
function safe($value){
return mysql_real_escape_string($value);
}
Now, how in the heck would I make this part safe from an attack?
value=".$info['ID']."
Your continued support is greatly appreciated.
YES YES YES YOU NEED ESCAPING
(not to be too emphatic)
To protect this code from attack, you need to make sure that you have an authenticated user. Is the user that is viewing this page logged in? If so, where is their session stored?
Whatever logic you used to read the data you need to use when deleting the data.
// Read data in at top to prevent E_STRICT errors if user messes with Query string
$User_ID = $_SESSION['User_ID']; //assuming it was authenticated
$a_filter = (isset($_POST['a_filter']) ? $_POST['a_filter'] : '');
$query = "
SELECT
a, b, c
FROM
table
WHERE 1
AND a = " . mysql_real_escape_string($a_filter) . "
AND User_ID = " . intval($User_ID) . "
";
That query will ensure:
That the user in question can only see their records.
That it doesn't matter what hacking data they send, it will be escaped.
Now when you PRINT it to HTML, make sure you protect against XSS attacks:
<td><?= htmlspecialchars($data); ?></td>
or if you are in an attribute:
<input type="text" name="a_filter" value="<? htmlspecialchars($data, ENT_QUOTES); ?>" />
Now, when you delete the record, just make sure you apply the same safeguards...
// Read data in at top to prevent E_STRICT errors if user messes with Query string
$User_ID = $_SESSION['User_ID']; //assuming it was authenticated
$ID = (int) (isset($_POST['id']) ? $_POST['id'] : 0);
$query = "
DELETE FROM
table
WHERE 1
AND ID = " . intval($ID) . "
AND User_ID = " . intval($User_ID) . "
";
This post covered escaping SQL, escaping HTML, escaping HTML attributes, and ensuring that the queries are authorized.
Here is a short post on where escaping is important:
http://blog.gahooa.com/answers/what-kind-of-data-needs-to-be-escaped/
PHP Filter (a php 5.2.x feature) allows you to both validate, and sanitize data.
http://us.php.net/manual/en/filter.examples.php
simply check whether the server has this entry or not.
To do this:
$query = 'SELECT * FROM `table` WHERE `ID` = '.(int)$_POST['ID'];
Casting it to integer should be quite safe. If it is a string, it will be converted as well. See PHP's Type Juggling: http://www.php.net/manual/en/language.types.type-juggling.php
Also, by checking whether this entry exists or not, you are double securing that the data is valid.
So:
$result=mysql_query('DELETE FROM `savannah` WHERE `ID`='.(int)$_POST['ID']);
if(!$result){
die(mysql_error());
}
the security here should probably be multi-level - there's not a lot else you can do on that specific field.
do you have a unique session to identify the user (even if you don't yet, it isn't too difficult to do this simply)?
if yes, then you can use that to determine if that user is allowed to delete items in general or even that item in particular.
that should protect against simple injection attacks...
as for escaping integer values - I generally cast the incoming value as an integer, and that typically removes the problem of rogue characters and invalid inputs:
$safe['value'] = (int) $_POST['value'];
If the string is not-numeric, your safe value will be 0.
Edit: I should mention that simply relying on the fact that the database field is an integer is not secure in anyway, and without escaping or casting the inputs before you create the query, you are opening yourself to SQL injection.