php select statement doesn't give answer - php

I used php code from tutorial and it worked fine. But when I am rewriting it to me it gives me null. This code gives me what I want I mean it gives data in JSON format:
$q=mysql_query("SELECT * FROM people WHERE birthyear>'".$_REQUEST['year']."'");
while($e=mysql_fetch_assoc($q))
$output[]=$e;
print(json_encode($output));
But this code even it looks identically doesn't work it gives null:
$q=mysql_query("SELECT username, firstname, lastname, email, phone1, skype, city, description
FROM mdl_user WHERE username LIKE'".$_REQUEST['usern']."'");
while($e=mysql_fetch_assoc($q))
$output[]=$e;
print(json_encode($output));
If I don't use $_REQUEST['usern'] and am getting data in JSON. But I need to use request to search specific data. So where could be the problem. Because I trustfully don't understand. It looks the same to me.

To make a pattern with LIKE use a %. Put it around or at any end, beginning or end.
$username = mysql_real_escape_string($_REQUEST['usern']);
$q=mysql_query("SELECT username, firstname, lastname, email, phone1, skype, city, description
FROM mdl_user WHERE username LIKE '$username%'");
^
|
// You also missed this space --+
Note your query is wide open to SQL injection. Just think if someone inserts year as '; drop table people; --. Use mysql_real_escape_string to sanitize those field.
And it's better to use explicitly $_POST or $_GET,ths makes sure your data is coming from proper source.

With LIKE you can use the following two wildcard characters in the pattern.
% Matches any number of characters, even zero characters
_ Matches exactly one character

I assume that you are getting no result because your username is not the exact same as $_REQUEST['usern'], and that's why you're using LIKE in the first place. You should therefore place wildcard characters to tell MySQL to look for any characters (%) before or after your string, for example:
LIKE '%".$_REQUEST['usern']."%'
Keep in mind that this is inefficient and you should try to use only one % after the string (if this will work for you), or better yet, find another way to search the table.
Edit: Also as a user in the comments noted and I failed to mention, this particular code is vulnerable to SQL injections. You should sanitize the variable $_REQUEST['usern'] before passing it onto the query.

Related

Is it possible that a query gives a different result when in a loop?

We have an upload tool to upload users via CSV. In this loop we check with MySql if the user exists in this way:
SELECT id FROM user_table WHERE email = 'email#domain.com'
We save the result of this query in $sql_array.
After that we do a count($sql_array). If that count is higher than zero we don´t do anything. Otherwise we insert the user in the user_table.
Now the weird thing we´ve been noticing is that in some cases it inserts users with an email address that already exists.
We have a function that sends us an email if the query results in an error. For example in case of a timeout or connection loss with MySQL. We didn´t receive any emails but still have these duplicate results. Does anybody know how this is possible?
Make sure that the email addresses are really identical and don't contain any stray whitespace before or after the actual string. Capitalization of the email addresses could differ as well, but my first guess is untrimmed strings.
One other thing to note is the performance of your query. Doing a select, transforming the result into an array and then counting the array is not optimal. Better you SELECT COUNT(*) FROM users_table WHERE email = '…' (putting an index on email also helps)
Its possible that your query fails to match a record if:
The collation of your db is case sensitive email#domain.com is not equal to Email#domain.com
Be sure the emails are trimmed and they are stored in database trimmed.
Important update:
If your script is vulnerable to sql injection, a simple quote "'" can cause the query to fail. For example if the $email has value
fdassdfsdf'sdfsfd#.com
will result to a query
SELECT id FROM user_table WHERE email = 'fdassdfsdf'sdfsfd#.com'
this will NOT execute since it has bad syntax, you will get 0 rows as result, and your script will think user does not exist and will allow registration.
Depending on the way your data is saved in the table, there could be white space issues making it a false positive
Something like this may help
$query = 'SELECT id FROM user_table WHERE email = "'.trim($emailFromCsv).'"';

Dynamic select value

Example:
$user_input = $_POST['input'];
'SELECT '.$user_input.' FROM table_name'
So it's selecting a column in a database based on a secure (this example isn't secure obviously) value. Is this practical/allowable code?
In SQL you simply send a string to the DBMS (like MySQL). Because of this you can build any string you want and submit it to the DBMS.
You just have to make sure the resulting SQL query is valid. That means that e.g. the columns exist and that no invalid symbol appears.
On it's face, this code is valid, assuming that $user_input must be a valid column name, which means that it must exist and must not contain any special characters, reserved words, etc. (unless they're escaped).
As you said, however, this code isn't secure, but as long as you plan to build the query securely and use PDO or MySQLi (no deprecated mysql_* functions...), you should be fine. If you need an example that doesn't use deprecated functions (including mysql_real_escape_string, which is also being deprecated) I'll provide one.
I know you stated that you know this code isn't secure, but here's another example if you're curious. As was discussed in the comments and this question, this input:
$user_input = '; DELETE FROM table_name ; *';
'SELECT '.$user_input.' FROM table_name'
will delete the entire contents of the table table_name. Even though this code raises a syntax error, MySQL will continue to execute it, thus effectively truncating table_name.

Trouble with LIKE MySQL query

I have the following MySQL query that I execute from a .php page
SELECT * FROM servers WHERE name LIKE '%$value%'
which, when executed, selects 0 rows (However, the query runs successfully, so I can't use mysql_error() to debug). When I run the query in PHPMyAdmin it selects the appropriate rows. Other queries such as
SELECT * FROM servers
work fine. I can put my code up here if it will help.
Edit: Here's something offering an improvement based on Marek's answer below. Please see the comments regarding the practice of putting variables directly into queries and consider using prepared statements. Anyway, here it goes.
PHP substitutes variables inside doubly-quoted strings, but not inside singly-quoted strings.
One quote character is just treated as an ordinary character within a string delimited by the other.
Putting that together, you can write:
$q = "SELECT * FROM servers WHERE name LIKE '%$value%'"; //Fine
You cannot write:
$p = 'SELECT * FROM servers WHERE name LIKE "%$value%"'; //Broken!
$q works because it's a doubly-quoted string, and the apostrophes are just ordinary characters. $p does not work because it's a singly-quoted string.
As pointed out by GoodFather below, you can also say ${value} to avoid ambiguities with the ambient string, e.g. $r = "ABC${value}DEF";.
You really need to look at doing this query more safely. This will help with your issue as well. As it stands, you are vulnerable to SQL injection. Look at the examples from the PHP manual for how to do it right:
http://php.net/manual/en/function.mysql-query.php
EDIT: From your comments you mentioned that you are already taking care of the string properly, which is great. The code below should fix your problem.
For example, you could rewrite your query statement (in PHP) like so:
$query = sprintf("SELECT * FROM servers WHERE name LIKE '%". mysql_real_escape_string($value) . "%'");
That will clean up your code and it will also handle the issue with your LIKE statement not working properly.
Here is another good article on the subject:
http://joshhighland.com/blog/2008/07/06/php-sprintf-sql-like/
Are you expecting a case-sensitive or case-insensitive query? I'm betting case-insensitive since you're expecting results but not seeing them. Take a look at your database's default collation or the table's specific collation and make sure it ends in _ci, whatever it is.

PHP with SQL Injection

Ok, starting fresh >
For our first assignment in a System Security class, we have to hack into the professors "cheaply organized" sql database. I know the only user is "admin" and picking a random password, the select statement generated in the php is:
select user_id from user where user_username = 'admin' AND user_password = md5('noob')
Now, I go for the basic starting point of trying to hack the crappy login with "admin'--"
select user_id from user where user_username = 'admin'--' AND user_password = md5('noob')
but the actual value being pushed to the database is
select user_id from user where user_username = 'admin\'--' AND user_password = md5('noob')
which doesn't help. The server uses POST to get the values from the form. I've already bypassed any value processing on my side of the send by disabling javascript.
There does not appear to be anything in the php that modifies the input in any way.
Assuming the select statement is part of a login form, then most likely it's generated something like this:
$user = $_POST['username'];
$pwd = $_POST['password'];
$query = "SELECT .... WHERE user_username='$user' AND user_password=md5('$pwd')";
which means, you could hack in by entering:
noob') or ('a'='a
for the password, giving you
SELECT .... AND user_password=md5('noob') or ('a'='a')
^^^^^^^^^^^^^^^^^-- your contribution
The actual password might not match, but 'a' will always equal itself, so the where clause will succeed and match a record based purely on the username and return the admin user's user_id.
As others had mentioned the escaping that you see is not the OS, but some form of encoding done in PHP (likely magic quotes, but could be a straight call to addslashes()).
Basically what you need to do is send in a form of quote that will not be escaped. You should research why one would use mysql_escape_string() rather than addslashes() and/or check this out: http://forums.hackthissite.org/viewtopic.php?f=37&t=4295&p=30747
Try ' OR 1; -- as user name. Imagine what the SQL query from such a user name looks like.
This has nothing to do with the operating system. The operating system simply runs the PHP package. PHP is what does sanitization, etc.
Have you tried submitting the following string for user_username?:
admin' OR 1=1-- #assuming mysql
Would yield a query:
select user_id from user where user_username = 'admin' OR 1=1 --' AND user_password = md5('noob')
In mysql (assuming the database type), -- is a comment, so everything after 1=1 is ignored. As a result, you've successfully gained access.
If php magic quotes are on, however, this will be slightly more difficult. You will need to submit characters outside of utf-8 or attempt overflows or submitting null bytes.
You could also try a bit of googling after entering a string that will error out the admin and use part of message that comes back as the key words.
You could also use the http://gray.cs.uni.edu/moodle/mod/forum/discuss.php?d=106 fourm to ask questions so the whole class can benifit!
if you can figure out how to upload files that would be great! I want to get c99.php up to really do some damage!
you could also try some "hash" verse "dash dash"

apostrophes are breaking my mysql query in PHP

My database has name records that occasionally contain apostrophes, such as Joe's Bar and I've just coded a query script in PHP that grabs that field and sticks it into a select statement with the usual $query = "SELECT address FROM restaurants WHERE name='$name'"; and the apostrophe in some of the restaurant names derails the Love Train.
How do I keep this from happening?
Snide answer - Use the same technique you used when you inserted them INTO the database via PHP.
Rebuttal - I was having the same problem then and cheated and entered the troublesome ones directly using PHPMyAdmin but this can't be ignored any longer.
Thank you for taking the time to answer this during the holidays.
You have to $name = mysql_real_escape_string($name); before that line.
You might also want to read up on SQL Injections, since your inputs are clearly unsanitized.
Have a look here
How can I use an apostrophe (') in a
query string?
mysql_real_escape_string
PHP mysql_real_escape_string

Categories