I have a query in the following way.....i have a column named location_ns and it contains
'Marriott\256 Hotel & Convention Centre' as it's value. But query is not resulting any id.
when i remove \ in both value and query it is working.
SELECT id
FROM notice
WHERE
lon = 78.48693966865540000000
AND lat = 17.42434596639255000000
AND location_ns = 'Marriott\256 Hotel & Convention Centre'
AND notice_type="text"
Please let me know if any one has a solution for it
As documented under String Literals:
Within a string, certain sequences have special meaning unless the NO_BACKSLASH_ESCAPES SQL mode is enabled. Each of these sequences begins with a backslash (“\”), known as the escape character. MySQL recognizes the escape sequences shown in Table 9.1, “Special Character Escape Sequences”. For all other escape sequences, backslash is ignored. That is, the escaped character is interpreted as if it was not escaped. For example, “\x” is just “x”.
Therefore, you must escape your backslash:
AND location_ns = 'Marriott\\256 Hotel & Convention Centre'
However, you would do well to pass your literals to MySQL as parameters to a prepared statement.
\ is an escape sequence in MySQL. If you had a record with value:
Marriott\256 Hotel & Convention Centre
You would need to query for it like
AND location_ns = 'Marriott\\256 Hotel & Convention Centre'
This let's MySQL know you are looking for a literal \.
Related
I have a field called myfield that contains this string:
{'Content-Language': 'en', 'X-Frame-Options': 'SAMEORIGIN', 'X-Generator': 'Drupal 7 (http://drupal.org)', 'Link': '<https://01.org/node>; rel="shortlink"', 'Some-Header-Key': 'max-age=31; addSomething', 'Content-Encoding': 'gzip'}
I want to capture the 'Some-Header-Key': 'max-age=31; addSomething' where:
1) 'Some-Header-Key', max-age are fixed values that should always be present.
2) The addSomething is a optional.
3) There may be one or more spaces between the double colon and the equal sign
4) The general formal is 'key': 'value', with either single or double quotes.
5) The ([^""|'])* to say: zero or more characters that are not single or double quotes. This to capture addSomething.
I wrote this query:
select myfield
from mytable
where mycol regexp "('|"")Some-Header-Key('|"")\s*:\s*('|"")([^""|'])*max-age\s*=\s*[0-9]+([^""|'])*('|"")";
But it does not return anything!! although myfield contains the above example string.
When I copied the field value into an external text file and run the regexp in grep, the regexp captured the string correctly.
What is wrong in MySQL? I use MySQL workbench 8.0 in Ubuntu 18.04.
Your problem is with the \s in your regex expression. Versions of MySQL prior to 8 do not support this notation, you need to use the character class [:blank:] instead i.e.
where mycol regexp "('|"")Some-Header-Key('|"")[[:blank:]]*:[[:blank:]]*('|"")([^""|'])*max-age[[:blank:]]*=[[:blank:]]*[0-9]+([^""|'])*('|"")"
In MySQL 8, you can use \s but you need to escape the backslash as MySQL uses C-style escape syntax in strings, thus \s just translates to s. So change the \s to \\s and it should work:
where mycol regexp "('|"")Some-Header-Key('|"")\\s*:\\s*('|"")([^""|'])*max-age\\s*=\\s*[0-9]+([^""|'])*('|"")"
Demo on dbfiddle
Not single or double quotes: [^'"]
Zero or more of such: [^'"]
Either a single quote or two double quotes: ('|"")
Either a double quote or two single quotes: ("|'')
One of either type of quote: ['"] or ('|")
A single-quoted string: '[^']*'
A double-quoted string: "[^"]*"
Either of the above: ('[^']*'|"[^"]*")
Next problem: How to quote a regexp string: If it contains ' or ", escape that with a backslash:
my_json REGEXP "('[^']*'|\"[^\"]*\")"
If you use something that does "binding" for you, you don't need to do the escaping. PHP has mysqli_real_escape_string and add_slashes.
But... I you are going to use JSON, you should upgrade to MySQL 5.7 or MariaDB 10.2 so you can use JSON functions instead of REGEXP.
I would like to query only string that contains this exact string string_.
I tried this:
select * from table where name like "%string_%"
and results also include string-, but I need only exact _.
Any help?
Thanks
_ is the wildcard in SQL for a single character. If you want to search for _ you need to escape it:
select *
from some_table
where name like '%string\_%' escape '\'
Additionally: string literals are put into single quotes in SQL. If you ever want to use a more standard compliant DBMS (Oracle, Postgres) you should get used to using single quotes for strings. Double quotes are only for identifiers (and should essentially be avoided in the first place)
I tried running this query:
SELECT column FROM table WHERE column REGEXP '[^A-Za-z\-\']'
but this returns
#1139 - Got error 'invalid character range' from regexp
which seems to me like the - in the character class is not being escaped, and instead read as an invalid range. Is there some other way that it's suppose to be escaped for mysql to be the literal -?
This regex works as expected outside of mysql, https://regex101.com/r/wE8vY5/1.
I came up with an alternative to that regex which is
SELECT column FROM table WHERE column NOT REGEXP '([:alpha:]|-|\')'
so the question isn't how do I get this to work. The question is why doesn't the first regex work?
Here's a SQL fiddle of the issue, http://sqlfiddle.com/#!9/f8a006/1.
Also, there is no language being used here, query is being run at DB level.
Regex in PHP: http://sandbox.onlinephpfunctions.com/code/10f5fe2939bdbbbebcc986c171a97c0d63d06e55
Regex in JS: https://jsfiddle.net/6ay4zmrb/
Just change the order.
SELECT column FROM table WHERE column REGEXP '[^-A-Za-z\']'
#Avinash Raj is correct the - must be first (or last). The \ is not an escape character in POSIX, which is what mysql uses, https://dev.mysql.com/doc/refman/5.1/en/regexp.html.
One key syntactic difference is that the backslash is NOT a metacharacter in a POSIX bracket expression.
-http://www.regular-expressions.info/posixbrackets.html
What special characters must be escaped in regular expressions?
Inside character classes, the backslash is a literal character in POSIX regular expressions. You cannot use it to escape anything. You have to use "clever placement" if you want to include character class metacharacters as literals. Put the ^ anywhere except at the start, the ] at the start, and the - at the start or the end of the character class to match these literally
Is there any way to perform a SQL injection when single quotes are escaped by two single quotes? I know the MySQL server is using this specific technique to prevent against an attack. I'm trying to log in as a specific user but all of the common injections I've tried for the password have not worked successfully (i.e. ' or '1'='1, ' or ' 1=1, etc.).
No, and yes.
There's no way to have an unsafe values "breakout" of literal values that are enclosed in single quotes, if the value being supplied is "escaped" by preceding single quotes by with an additional single quote.
That is, assuming that your statement is guaranteeing that string literals are enclosed in quotes, as part of the "static" SQL text.
example perl-ish/php-ish
$sql = "... WHERE t.foo = '" . $safe_value . "' ... ";
^ ^
I've underscored here that the single quotes enclosing the literal are part of the SQL text. If $safe_value has been "escaped" by preceding each single quote in the "unsafe" value with another single value to make it "safe"...
$unsafe_value $safe_value
------------- ------------
I'm going I''m going
'she''s' ''she''''s''
1'='1 -- 1''=''1 --
As long as the escaping is handled properly, that we guarantee that potentially unsafe values are are run through the escaping, then including single quotes in data values is not a viable way to "breakout" of a literal with the SQL text.
That's the "no" part of the answer.
The "yes" part of the answer.
One of the biggest problems is making sure this is done EVERYWHERE, and that a mistake has not been made somewhere, assuming that a potentially unsafe string is "safe", and is not escaped. (For example, assuming that values pulled from a database table are "safe", and not escaping them before including them in SQL text.)
Also, the single quote trick is not the only avenue for SQL injection. The code could still be vulnerable.
Firstly, if we're not careful about other parts of the statement, like the single quotes enclosing string literals. Or, if for example, the code were to run the $sql through some other function, before it gets submitted to the database:
$sql = some_other_function($sql);
The return from some_other_function could potentially return SQL text that was in fact vulnerable. (As a ridiculous example, some_other_function might replace all occurrences of two consecutive single quotes with a single single quote. DOH!)
Also, with the vast number of possible unicode characters, if we're ever running through a characterset translation, there's also a possibility that some unicode character could get mapped to a single quote character. I don't have any specific example of that, but dollars to donuts that somewhere, in that plethora of multibyte encodings, there's some unicode character somewhere that will get translated to a single quote in some target.
There's a default character in the target for unmapped characters in the source, and that's usually a question mark (or a white question mark in a black diamond.) It would be a huge problem if the default character in the target (for unmapped characters in the source) was a single quote.
Bottom line: escaping unsafe strings by replacing single quotes with two single quotes goes a long ways towards mediating (mitigating?) SQL injection vulnerabilities. But in and of itself, it doesn't guarantee that code is not vulnerable in some other way.
if the input accepts unicode and is implicitly converted to ascii in the database (not as uncommon as it sounds) then an attacker can simply substitute ʻ or ʼ (0x02BB or 0x02BC) in place of single tick to get around the escaping mechanism and the implicit conversion will map those characters to single ticks (at least that's the case in SQL Server)
The last person in my job has flooded column names with special characters such as (?,!, and /), as well as used many reserved keywords for column names (more often than not, timestamp or user is used).
Normally, I step around this by using double quotes or brackets to escape the SQL object. A subset of the full list of columns are below:
DriverID,
Department,
Odometer,
MerchantState,
MerchantCity,
gallons/Units,
timestamp,
tax
Inside my query, I wrap the two columns in question (gallons/units and timestamp) inside double quotes. Timestamp because it's a reserved keyword, and Gallons/units, because without the quotes, SQL reads the query, stops at the slash, and tells me "Gallons" is not a column inside the table.
If I do wrap double quotes around the column name, SQL returns a different error: "Operand should contain 1 column(s)".
I've tried every variant (only capturing the slash in quotes, quoting both, using brackets, mixing brackets and quotes, etc. but with to no avail).
Is there anything I can do to fix this query short of renaming the column name and changing the associated code in the program that pulls from it? (the really tedious task I'm trying to avoid).
In SQL Server, identifiers can be delimited using square brackets, e.g.
SELECT [gallons/units] ...
In MySQL, identifiers can be delimited using backticks, e.g.
SELECT `gallons/units` ...
(NOTE: If MySQL SQL_MODE includes ANSI_QUOTES, then double quotes are treated as delimiters for identifiers, similar to the way Oracle handles double quotes; absent that setting, double quotes are handled as delimiters for string literals. With ANSI_QUOTES included SQL_MODE, "gallons/units" will be interpreted as an identifier (column name). Without ANSI_QUOTES, MySQL will see it as a string literal, as if it were enclosed in single quotes.)
FOLLOWUP:
As far as an error "operand should contain only 1 column(s)", that's usually a problem with query semantics, not an issue with escaping identifiers.
A subquery in the SELECT list can return only a single expression, for example, this would throw an error:
Query: SELECT 'foo' , ( SELECT 'fee' AS fee, 'fi' AS fi )
Error Code: 1241
Operand should contain 1 column(s)
You can try backticks instead of double quotes
`gallons/units`
There are a couple of options. First, have you tried using %/ to escape the slash?
Example: "select * from 'gallons%/units';"
Second one I've found, which may or may not be helpful, is to provide an escape character definition, such as
http://blogs.msdn.com/b/zainala/archive/2008/08/17/using-and-escape-clause-in-sql-server-like-query.aspx
select * from MyTable where Description like '|[summary|]%' escape '|'
In your case
select * from 'gallons|/units' escape '|'
You indicate both mysql and sql-server in your tags, so I'm not sure which server support I should be looking for exactly.