I have a php script which selects from a MySQL table. The Table Content is set to UTF8, so is the php script interfacing with it.
The input strings are real_escaped. I am facing the following issue:
Given the following data in the table:
ID Username
1 Test
2 Test1
3 Test-A
The following SQL returns the IDs for 1 and 2 successfully but when asked for the 3rd it returns nothing.
SELECT `ID` FROM `User` WHERE `Username` = '$User'
Why is it not returning when I ask for the ID where Username = Test-A?
Is it because the Username contains a minus?
It has to be a different string. Double check the dash/hyphen mark in both cases (may be different unicode characters like described here) - it happens frequently when copying and pasting data from "rich" text editors.
Also check for whitespaces.
Depending on what you mean by "real_escaped" it might be the case that your username is escaped turning into something similar to ('Test\-A') which essentially does not exist.
Print out the value of the $User to check what you're sending to MySQL.
On top of that, you are using old outdated practices, there are better ways of querying the database securely with PDO::prepare (http://us1.php.net/manual/en/pdo.prepare.php), use those examples there.
Related
I have a social networking site which I am in the process of constructing. Users can follow each other and it adds their name to a list of followers. I need to scan that list for the session username cookie to choose which statuses (posts) to display. In my sql recordset, I have the code:
SELECT *
FROM statuses
WHERE followedby CONTAINS '". $_SESSION['MM_Username']."'
But this just brings up 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 'CONTAINS 'Usernamecookie'' at line 1
Try this:
SELECT *
FROM statuses
WHERE followedby LIKE '%". $_SESSION['MM_Username']."%'
LIKE clause is used for string matching.
Others have correctly answered this question already, but I just want to add the meaning of contains in MySQL:
MySQL only recognizes the CONTAINS SQL function when dealing with
spatial data. It requires two graphics objects as arguments, and
returns a 1 or 0 depending on if the first object completely contains
the second. Designed as an implementation of the OpenGIS framework,
the MySQL CONTAINS function does not work on ordinary strings, and
will produce an error if you try it. MySQL only recognizes the LIKE
and STRCMP functions when dealing with string of information.
So in your case, you want to use like.
References:
https://blog.udemy.com/sql-contains/
https://dev.mysql.com/doc/refman/5.0/en/string-comparison-functions.html#operator_like
Instead of Contains use LIKE.
Try this:
mysql_query("
SELECT *
FROM statuses
WHERE followedby LIKE '%{$MM_Username}%'
");
Put the MM_Username in its own var. Nicer code ;)
Remember to enable index for FollowedBy if your table grows.
Read more about how to enable fulltext indexes here
I cant figure it out. I have this variable (for example):
$level_building = "test,";
and this sql string:
mysql_query("UPDATE info_buildings SET building='$level_building' + building WHERE nick='$nick'") or die(mysql_error());
all i want to do is to add new text test, after existing text, but after updating it, sql shows 0 (building=0).. My sql output should look like this test,test,test,... Example: building=test,test,test, and each time i use sql string UPDATE it should write new test text in the same building string.. Sorry for bad english i hope you understand this.
In MySQL, + is for arithmetic addition. To concatenate strings, use CONCAT():
UPDATE info_buildings
SET building = CONCAT('$level_building', building)
WHERE nick = '$nick'
All the MySQL string functions can be found here.
However, I recommend you reconsider your table design. Putting comma-separated lists in a single column is usually poor design. You should use a separate table with a row for each value.
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"
This question already has an answer here:
Syntax error due to using a reserved word as a table or column name in MySQL
(1 answer)
Closed 8 years ago.
So I have a primary key column called key. I'm trying to select the row with key = 1 via this code:
$query ="SELECT * FROM Bowlers WHERE key = '1'";
$result = mysql_query($query) or die(mysql_error());
For some reason, I'm getting this result:
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 'key = '1'' at line 1
The mysql statement works for using other keys, ie WHERE name = 'djs22'.
Any ideas?
key is a reserved word, try putting ticks around it:
$query ="SELECT * FROM `Bowlers` WHERE `key` = '1'";
$result = mysql_query($query) or die(mysql_error());
To see all the reserved words, go here and scroll down:
http://dev.mysql.com/doc/refman/5.1/en/reserved-words.html
'key' is a reserved keyword, put backtick quotes around it:
"SELECT * FROM Bowlers WHERE `key` = '1'"
Without checking, it's likely that "key" is a reserved word in MySQL.
Try wrapping it in backticks
$query ="SELECT * FROM Bowlers WHERE `key` = '1'";
You should write the column name key in quotes
$query ="SELECT * FROM Bowlers WHERE `key` = '1'";
Otherwise it is a keyword
I run into that all the time. MySQL has a crap load of reserved words. And when you come across one, the mysql error function is not even nice enough to let you know what is wrong.
The only thing you can do is change the column name. I accidentally used "date, to and from" the other day. Was pulling my hair out when it dawned on me, DuHH!!! those are DB reserved.
You can wrap all kind of quotes around it, it does not matter when it references a column name. Reserved is reserved!
It is common practice to to do a couple of things.
1) When making tables: Split resource type with resource name using underscore. Example: xref_userMessages
This would mean it is a cross reference table for User messages.
2) Other examples of table names: msg_Messages | sys_Settings | cli_Logins
So any other table made related to messages would be called msg_??? , not only does this keep them grouped together in phpMyadmin but makes remembering the names easier too.
3) When Making columns: Never use a reserved. Thus causing key columns to always be 6 didgets. Example: admkey | usrkey | msgkey | clikey grpkey
Obviously Admin Key | User Key | Message Key | Client Key | Group Key
So this means "msg_Messages" keys are "msgkey" and the xref table would be xref_Messages and its keys are xref_msgkey. Following this logic you not only know what to name everything without even thinking about it, but you never run into any reserved words doing it.
4) Examples of Column names: dateInsert dateStart timeCreate admName admAddress admPhone admCell
Just like above there is a logic to it. Placing purpose/owner and noun/item together makes the name and again avoids reserved words.
Last Example:
Table: users_Admins users_Clients
Key: admkey usrkey
Table: msg_Messages
Columns: msgkey admkey usrkey msgRead msgMessage msgTitle
Just in this short example I avoided 2 reserved words. Key and Read
So in short, your problem is not reading a primary key. It is a problem with column names.
MySQL is seeing your code as having a syntax that has commands out of place. SELECT read ... or SELECT key ... it doesnt matter if you put quotes around it or not. MySQL is basically seeing ...
SELECT (SELECT,WHERE,FROM) FROM select,from,where
WHERE SELECT = WHERE & FROM = SELECT. hehehehehehehe
Putting a different kind of quote around this will not change the confusion level you just sent to MySQL.
Mixing my mistake and your mistake together looks like this...
SELECT key,from,to,date FROM my_table WHERE key='1';
// Same as...
SELECT SELECT,SELECT,SELECT,SELECT FROM my_table WHERE SELECT='1';
The first one you can't really tell by looking at it there is anything wrong with it. The second one it is obvious that it is not right and won't work. However, according to MySQL they are the SAME THING.
MySQL receives this syntax as so... SELECT? You told me to SELECT 5 times, never told me what to even select. You get the FROM right, but then you ended with a left hook telling to select something else, not only did you not tell me what to select again but you threw in an NULL='1'; what the heck is that all about?
This is why when you make these kinds of errors the error function doesn't even report what the heck happened. There were so many errors it can't throw you an error number so it just stops.
So this means your syntax is like this
SELECT * FROM Bowlers WHERE SELECT = '1';
Sometimes I get frustrated and say, "I wish MySQL was smarter than this!!!" But then I realize i would have to trade the key words in for a lesser valued database. Each one of those reserved words represents a word that is doing a whole lot more work on the database side for me. When I first started to learn programming I had to write my own text input field sub routines, so I appreciate all the neat things MySQL does for me.
Ok this is a new one for me. Basically I have a table articles:
id: int auto increment
title: varchar(200)
description: varchar(1000)
ctext: longtext
chtml: longtext
Now I do an insert into this table with mysql_query:
INSERT INTO articles
(title, description, ctext, chtml)
VALUES
('$title', '$description', '$text', '$html')
All values have been passed through mysql_escape_string().
The text and html here are roughly 50k in size (so I can't really post the fully query here).
Now, here's the problem: the query works. A new row is inserted. However the ctext and chtml columns are empty. This is MySQL 5.0.51a and PHP 5.2.8. No errors are raised of any kind as far as I can tell.
Now I dumped the query out to a file in /tmp and ran it with:
mysql -u username -p dbname < /tmp/query
Same thing.
I copy the query into Navicat and it... works.
So what on earth is going on?
Some random thoughts:
Have you tried controlling the text length see if it only fails at one point?
What kind of connection are you opening? Which driver?
Have you checked the encoding of your connection? Some invalid characters might be sent in.
Have you tried using parameters instead of mysql_escape_string?
Have you tried executing directly from the same file from Navicat instead of using the copy-paste? Again, might be related to an invalid character that's not passed through the copy-paste but was saved in the file.
Just to cover the basics we so often forget, how do you verify that the data is not inserted? I mean, how to you visualize it? You could have a line break that hides the first lines from 2 out of 3 means of visualization. Just a long shot, but I've seen it happen.
Addition: MySQL connections defaults to latin1, you need to use something like mysql_query("SET NAMES 'utf8'") to transfer unicode characters.
I'm not sure if this matters, but mysql_escape_string is deprecated and replaced by mysql_real_escape_string
Have you tried it with smaller text?