Mysql, dealing with String Regex - mysql

I'm developing a Java desktop application that connects with a database, and I would like to know the next. It results that as far as I know, Prepared Statements avoid SQL injections while you don't make a direct concatenation with user data, but today I figured out that it doesn't escape String regex (like '%' from the LIKE operator,) due that it just escapes characters that could break up the String itself and alter the query. So, if user does:
Search = "%Dogs"; // User input
Query = "SELECT * FROM Table WHERE Field LIKE ?";
blah.setString(1, Search);
It will return all the rows that contains 'Dogs' at the beginning by injection.
Now I ask:
1-) Is this something bad / dangerous viewing from a global point?
2-) Is there a full list of Regex that Mysql could use from inside a String? if so, can you please share it with me?
Thank you.

If the user uses such meta characters in their search, the results may or may not be catastrophic, but a search for %% could be bad. A valid search for %Dogs may also not return the results the user was expecting which affects their experience.
LIKE only offers two meta characters, so you can escape them both on your own when acquired from users (simply using something akin to Search = Search.replaceAll("%", "\\\\%")).

Related

Query binding adding slashes.. prevents me from doing searches

I am trying to search a store by its name, and when using mysql data binding, it adds a slash in between and prevents me from searching for the store name
The store name is Jimmy's Pita
When I run the query it looks like this
SELECT * FROM stores WHERE store_name = 'Jimmy\'s Pita'
But the store name in the database looks like this ... 'Jimmy's Pita & Poke'
What can I do to fix this issue?
Any help would be really appreciated!
This is to do with escaping. When you specify using single quotes you must escape other single quotes, as in:
'Jimmy\'s Pita'
If you use different quotes, which MySQL allows by default, then you can do this instead:
"Jimmy's Pita"
Both of these are equivalent and in both cases the data saved is:
Jimmy's Pita
The backslash is only there to deal with escaping issues. It is not literally part of the data.
When it comes to searching you may want to use the MySQL full-text index so you can get "close enough" matches, like searching for "jimmys pita" and so on.

SQL injection with malicious payload disguise in hexadecimal value

I am investigating in SQL injection and having a difficulty at hiding payload in hex, hope someone can advise.
For example, the injection:
select name from user where id= ? --> this where I want to inject
I want to make the query like:( just for example only)
select name from user where id= 1 union select 1,2,3
In order to hide my payload, I would like to convert "1 union select 1,2,3" into hexadecimal as below:
select name from products where id=X'3120756E696F6E2073656C65637420313233';
select name from products where id=0x3120756E696F6E2073656C65637420313233;
However, somehow mysql does not interpret my hex into the original string, but consider it as a number which is not logic in my point of view. Anyone can help me with this?
Thanks.
It's perfectly logical for MySQL to interpret both 0x3120... and X'3120...' as hexadecimal literal expressions in both cases, and to interpret as a number, string, or blob, as context dictates.
The parser would not under any circumstance interpret such expressions ambiguously, any more than it would misinterpret something like this:
WHERE id = '1 UNION ALL SELECT ...'
It's unambiguously a literal string expression, the same as the two examples provided.
https://dev.mysql.com/doc/refman/5.6/en/hexadecimal-literals.html
I am not inclined to assist anyone with advice on how to exploit a SQL injection vulnerability. Using urlencoding would allow you to pass something like %31%20%75%6E... which is really no clever exploit at all, only a different way of encoding a URL for presentation at an already-vulnerable interface and would serve no advanced purpose. Either it's properly written, or it's already vulnerable without such a tactic, and such an encoding wouldn't change that except maybe in rare cases.

Wildcard searches w/MySQL

I've a situation where my wildcard search is not really working how I thought it should...
This is the MySQL query I am running and it will return only whole words...
eg. If I enter "phone" as a search word it will return all rows with "phone" in it but not rows with "phones" (note the added 's')
mysql_query(" SELECT * FROM posts WHERE permalink = '$permalink' AND LOWER(raw_text) LIKE '%$str%' " );
How can I get it to return all variations of the search word? Obviously I know this could run into problems as it could return all sorts of matches if the user enters a common run of letters, I thought I could make this part of the advanced search option.
ADENDUM
I have narrowed it down to not a problem with the wildcard but with what I'm doing with the returned data... It is in my Regex that I am throwing at the data.
$pattern= "/(?:[\w\"',.-]+\s*){0,5}[\"',.-]?\S*".$str."(\s|[,.!?])(\s*[A-Za-z0-9.,-]+){0,5}/";
preg_match_all($pattern, $row["raw_text"], $matches);
The regex is not finding the string in the raw data that I am returning so it is throwing me a null. A new problem, I'm not that familiar with regex so I will havbe to fugure this one out as well... Maybe I'll be throwing up a new question soon!
Thanks,
M
I think something else is going on. The % part of the query seems correct. And this seems to be confirmation:
select 'phones' LIKE '%phone%';
+-------------------------+
| 'phones' LIKE '%phone%' |
+-------------------------+
| 1 |
+-------------------------+
1 row in set (0.00 sec)
By the way, I really hope you are doing a rigorous sanitation on $str (and $permalink too if it is from user input). You should only allow alphanumerics and a small number of other safe characters (spaces, probably) and you should be running it through mysql_real_escape_string() before using it in mysql_query(). Better yet, have a look at PDO.
Anyway, back to troubleshooting this: One thing to try might be to have the program log the string your sending to mysql_query(). Basically, change the call to mysql_query() to a call to error_log() or echo() or something like that. Then copy and paste the resulting query into MySQL command-line tool or PHPmyAdmin or whatever. When that query doesn't work the way you expect, at least you can look at it and tweak it to figure out what's up. And who knows, maybe it will be super obvious once you see the query spelled out.
I suspect you have a trailing space in your $str variable, which would explain what you're seeing: Your LIKE criterion would be '%phone %', which matches "... phone ...", but not "... phones ...".
Try trimming your value first.

Punctuation insensitive search in mySQL

I have a database of phrases that users will search for from their own input. I want them to find the phrase regardless of what punctuation they use. For example if the phrase, "Hey, how are you?" is in the row, I want all of the following searches to return it:
"Hey! How are you?!"
"Hey how are you?"
"Hey :) How are you?"
Right now, I have the columns 'phrase' and 'phrase_search'. Phrase search is a stripped down version of phrase so our example would be 'hey-how-are-you'.
Is there anyway to achieve this without storing the phrase twice?
Thank you!
-Nicky
What you've done is probably the most time-efficient way of doing it. Yes, it requires double the space, but is that an issue?
If it is an issue, a possible solution would be to convert your search string to use wildcards (eg. %Hey%how%are%you%) and then filter the SQL results in your code by applying the same stripping function to the database input and the search string and comparing them. The rationale behind this is that there should be relatively few matches with non-punctuation characters in-between the words, so you're still getting MySQL to do the "heavy lifting" while your PHP/Perl/Python/whatever code can do a more fine-grained check on a relatively small number of rows.
(This assumes that you have some code calling this, rather than a user typing the SQL query from the command line, of course.)

Is there a mySQL equivalent to Postgresql's "Dollar-Quoted String Constants"?

In postgresql, it's possible to use "Dollar-Quoted String Constants" to avoid escaping single quotes in constant strings:
Without Dollar-Quoted String Constants:
'Jeff''s table'
With Dollar-Quoted String Constants:
$$Jeff's table$$
Is there a MySQL equivalent?
On edit: I'm not looking for a way to sanitize inputs, I'm looking for a way to make queries that generate sql easier to read.
No, because it doesn't really work. An attacker just addes a pair of dollar signs to their injection attempt instead.
The correct way to handle this is a system that uses real query parameters, such that the parameter values are never substituted directly into a query string. This is also generally better for performance because the db can do a better job caching the execution plan you don't end up building string dynamically, which tends to be slow in modern languages.
Not having excess concatenation statements greatly improves the readability of the code, as well. Instead of this:
sql = "SELECT * FROM MyTable WHERE Column1=$$" + somevarialbe + "$$ AND Column2=$$" + OtherVariable";
it's just this:
sql = "SELECT * FROM MyTable wHERE Column1=#Value1 AND Column2=#Value2";
Hmm... Okay, I can see some limited utility for this feature now.
Imagine a ticket tracking system with a stored procedure to get open tickets. You might actually hard-code the literal 'open' into the where clause of the query. Not that this would be a good design — ticket status should be in a table with it's own key, so that you'd hardcode the key rather than the text. But it plants the seed for something valid and more-complicated.
You can enclose your string in double quotes instead, e.g.
"Jeff's table"
Note: If this doesn't work, it means that you've got ANSI_QUOTES SQL mode turned on. The MySQL docs say:
If the ANSI_QUOTES SQL mode is enabled, string literals can be quoted only within single quotation marks because a string quoted within double quotation marks is interpreted as an identifier.