WHERE Clause Requires Like When Equals Should Work - sql-server-2005

I have a query that I think should look like this:
select *
from Requesters
where CITIZEN_STATUS = 'OS-IE ';
The field CITIZEN_STATUS, whose data type is varchar(15), has a trailing space for this particular value. I have pasted it into Notepad++ and looked at it with a hex editor, and the final space is indeed 0x20.
For the query to work, I have to write it like this:
select *
from Requesters
where CITIZEN_STATUS like 'OS-IE%';
So, obviously, I have a workaround and the question is not urgent. But I would really like to know why the first query fails to do what I expect. Does anyone have any ideas?
I should mention I am using SQL Server 2005 and can provide more information about the configuration if needed.

In MySQL 5, this query works. However, it does not distinguish on trailing whitespace. The query matches 'OS-IE ' as well as 'OS-IE'. In SQL Server 2005 you can use a regular expression that defines the end of a line. The correct character for this is the dollar sign '$' to indicate that you do want the space. See http://msdn.microsoft.com/en-us/magazine/cc163473.aspx

Related

SQL: Use REGEXP_REPLACE on query parameter inside of LIKE statement

I have a query which is supposed to find matching rows ignoring case and special characters that may be present both in the query and the corresponding column. For that I use REGEXP_REPLACE like this:
SELECT *
FROM Order
WHERE REGEXP_REPLACE(reference, '[^a-zA-Z0-9äöüÄÖÜ]', '') LIKE %:search%
where search is the name of the parameter I want to use. That works, but doesn't yet sanitize the search parameter from unwanted special characters.
What I would like to do is something like the following, i.e. having the REGEXP_REPLACE on the right side as well:
SELECT *
FROM Order
WHERE REGEXP_REPLACE(reference, '[^a-zA-Z0-9äöüÄÖÜ]', '') LIKE %REGEXP_REPLACE(:search, '[^a-zA-Z0-9äöüÄÖÜ]', '')%
However that doesn't work and I get the following error:
42000][1064] You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '%REGEXP_REPLACE(
Is it not possible to use a function on the parameter or as part of a LIKE statement? Are there any workarounds?
It looks like you want to create a string starting and ending with '%' to use in your LIKE operator. To do that in MySQL's dialect of SQL you need to do your string manipulation explicitly using the built-in string manipulation functions.
You can use those functions anywhere your query needs a text string.
Try using CONCAT in an expression like this to generate that string. You'll be able to use it on the right side of your LIKE.
CONCAT('%', REGEXP_REPLACE(:search, '[^a-zA-Z0-9äöüÄÖÜ]', ''), '%')
I hope you don't want your query to be fast. It will be slow. It must examine every value of Order.reference in your table. It's slow because
it's not sargable due to WHERE f(column) LIKE whatever, and
column LIKE '%something%' requires looking at every value of column, rather than random-acccessing a BTREE index.
If you build a database to scale up, you design it so your queries can be sargeable. Sargability here might look like
WHERE cleaned_up_reference
LIKE CONCAT(REGEXP_REPLACE(:search, '[^a-zA-Z0-9äöüÄÖÜ]', ''), '%')
without the leading % on the right, and without evaluating any function on the column or columns being searched.
You can try this:
SELECT * FROM Order a
WHERE REGEXP_REPLACE(a.reference, '[^a-zA-Z0-9äöüÄÖÜ]', '') LIKE '%:search%'

Regex not working in LIKE condition

I'm currently using Oracle SQL developer and am trying to write a query that will allow me to search for all fields that resemble a certain value but always differ from it.
SELECT last_name FROM employees WHERE last_name LIKE 'Do[^e]%';
So the result that I'm after would be: Give me all last names that start with 'Do' but are not 'Doe'.
I got the square brackets method from a general SQL basics book so I assume any SQL database should be able to run it.
This is my first post and I'd be happy to clarify if my question wasn't clear enough.
In Oracle's LIKE no regular expressions can be used. But you can use REGEXP_LIKE.
SELECT * FROM EMPLOYEES WHERE REGEXP_LIKE (Name, '^Do[^e]');
The ^ at the beginning of the pattern anchors it to the beginning of the compared string. In other words the string must start with the pattern to match. And there is no wildcard needed at the end, as there is no anchor for the end of the string (which would be $). And you seem to already know the meaning of [^e].

Insert double quotes into SQL output

After I run a query and view the output, for example
select * from People
My output is as follows
First Last Email
Ray Smith raysmith#whatever.itis
How would I export this data so that it looks as follows?
"Ray","Smith","raysmith#whatever.itis"
Or is there a way to do this within SQL to modify records to contain quotes?
Because when you export, it's going to include the commas anyway, right?
If the columns you're interested in are 128 characters or less, you could use the QUOTENAME function. Be careful with this as anything over 128 characters will return NULL.
SELECT QUOTENAME(First, '"'), QUOTENAME(Last, '"'), QUOTENAME(Email, '"')
FROM People
select '"'+first+'","'+last+'","'+email+'"'
from people
This is the kind of thing best done in code however, you shouldn't query for presentation.
select concat(“\"”,first,“\"”,“\"”,Last,“\"”,“\"”,Email,“\"”) as allInOne
Modifying the records to contain quotes would be a disaster; you don't use the data only for export. Further, in theory you'd have to deal with names like:
Thomas "The Alley Cat" O'Malley
which presents some problems.
In Standard SQL, you'd use doubled-up single quotes to enclose single quotes (with no special treatment for double quotes):
'"Thomas "The Alley Cat" O''Malley"'
Some DBMS allow you to use double quotes around strings (in Standard SQL, the double quotes indicate a 'delimited identifier'; SQL Server uses square brackets for that), in which case you might write the string as:
"""Thomas ""The Alley Cat"" O'Malley"""
Normally, though, your exporter tools provide CSV output formatting and your SQL statement does not need to worry about it. Embedded quotes make anything else problematic. Indeed, you should usually not make the DBMS deal with the formatting of the data.
This worked best for me
SELECT 'UPDATE [dbo].[DirTree1] SET FLD2UPDATE=',QUOTENAME(FLD2UPDATE,'''')
+' WHERE KEYFLD='+QUOTENAME(KEYFLD,'''')
FROM [dbo].[Table1]
WHERE SUBSTRING(FLD2UPDATE,1,2) = 'MX'
order by 2
If you are using MS SQL Server, try something like:
SELECT '"'||Table.Column||'"'
FROM Table
-- Note that the first 3 characters between "SELECT" and "||" are:
' " '
-- The characters are the same after "||" at the end... that way you get a " on each side of your value.

Odd formatting in SQL Injection exploits?

I have been trying to learn more about SQL Injection attacks. I understand the principle, but when I actually look at some of these attacks I don't know how they are doing what they are doing.
There often seem to be uneven quotes, and a lot of obfuscation via HEX characters.
I don't get the HEX characters..., surely they are translated back to ASCII by the browser, so what is the point?
However, I am mainly confused by the odd quoting. I am having trouble finding an example right now, however it usually seems that the quoting will end at some point before the end of the statement, when I would have thought it would be at the end?
Perhaps an example is the common use of '1 or 1=1
What is such a statement doing?
I don't get the HEX characters...,
surely they are translated back to
ASCII by the browser
Nope.
However, I am mainly confused by the
odd quoting. I am having trouble
finding an example right now, however
it usually seems that the quoting will
end at some point before the end of
the statement, when I would have
thought it would be at the end?
Imagine you're building inline SQL instead of using parameter substitution as you should. We'll use a make-believe language that looks a lot like PHP for no particular reason.
$sql = "delete from foo where bar = '" + $param + "'";
So, now, imagine that $param gets set by the browser as such...
$param = "' or 1=1 --"
(We're pretending like -- is the SQL comment sequence here. If it's not there's ways around that too)
So, now, what is your SQL after the string substitution is done?
delete from foo where bar = '' or 1=1 --'
Which will delete every record in foo.
This has been purposefully simple, but it should give you a good idea of what the uneven quotes are for.
Let's say that we have a form where we submit a form with a name field. name was used in a variable, $Name. You then run this query:
INSERT INTO Students VALUES ( '$Name' )
It will be translated into:
INSERT INTO Students VALUES ( 'Robert' ); DROP TABLE STUDENTS; --')
The -- is a comment delimiter. After that everything will be ignored. The ' is used to delimit string literals.
To use hex chars in an attack has some reasons. One of the is the obfuscation, other one to bypass some naive security measures.
There are cases where quote marks are prohibited with sql injection. In this case an attacker has to use an encoding method, such as hex encoding for his strings. For instance '/etc/passwd' can be written as0x2f6574632f706173737764 which doesn't require quote marks. Here is an example of a vulnerable query where quote marks are prohibited. :
mysql_query("select name from users where id=".addslashes($_GET[id]));
If you want to use a mysql function like load_file(), then you have to use hex encoding.
PoC:/vuln.php?id=1 union select load_file(0x2f6574632f706173737764)
In this case /etc/passwd is being read and will be the 2nd row.
Here is a variation on the hex encode function that I use in my MySQL SQL Injection exploits:
function charEncode($string){
$char="char(";
$size=strlen($string);
for($x=0;$x<$size;$x++){
$char.=ord($string[$x]).",";
}
$char[strlen($char)-1]=")%00";
return $char;
}
I use this exact method for exploiting HLStats 1.35. I have also used this function in my php nuke exploit to bypass xss filters for writing <?php?> to the disk using into outfile. Its important to note that into outfile is a query operator that does not accept the output to a function or a hex encoded string, it will only accept a quoted string as a path, thus in the vulnerable query above into outfile cannot be used by an attacker. Where as load_file() is a function call and a hex encoding can be used.
As for the uneven quoting; sql injection occurs where the coder didn't sanitize user input for dangerous characters such as single quotes - consider following statement
SELECT * FROM admin WHERE username='$_GET["user"]' and password='$_GET["pass"]'
if I know that valid user is 'admin' and insert the 'or 1=1 I will get following
SELECT * FROM admin WHERE username='admin' and password='something' or 1=1
This will result in returning the query alway true, because the left side of the expression will always be true, regardless of the value of the password.
This is the most simple example of sql injection, and ofter you will find that the attacker won't need to use the quote at all, or maybe comment the rest of the query out with comment delimiter such as -- or /*, if there are more parameters passed after the injection point.
As for the HEX encoding, there may be several reasons, avoiding filtering, it is simply easier to use hex encoded values, because you don't need to worry about quoting all your values in a query.
This is for instance useful if you want to use concat to co-notate two fields together like so:
inject.php?id=1 and 1=0 union select 1,2,concat(username,0x3a3a,password) from admin
Which would providing 3rd row is visible one, return for isntance admin::admin. If I didn't use hex encoding, I would have to do this:
inject.php?id=1 and 1=0 union select 1,2,concat(username,'::',password) from admin
This could be problem with aforementioned addslashes function, but also with poorly written regex sanitization functions or if you have very complicated query.
Sql injection is very wide topic, and what I've covered is hardly even an introduction through.

How do I check the end of a particular string using SQL pattern matching?

I am trying to use sql pattern matching to check if a string value is in the correct format.
The string code should have the correct format of:
alphanumericvalue.alphanumericvalue
Therefore, the following are valid codes:
D0030.2190
C0052.1925
A0025.2013
And the following are invalid codes:
D0030
.2190
C0052.
A0025.2013.
A0025.2013.2013
So far I have the following SQL IF clause to check that the string is correct:
IF #vchAccountNumber LIKE '_%._%[^.]'
I believe that the "_%" part checks for 1 or more characters. Therefore, this statement checks for one or more characters, followed by a "." character, followed by one or more characters and checking that the final character is not a ".".
It seems that this would work for all combinations except for the following format which the IF clause allows as a valid code:
A0025.2013.2013
I'm having trouble correcting this IF clause to allow it to treat this format as incorrect. Can anybody help me to correct this?
Thank you.
This stackoverflow question mentions using word-boundaries: [[:<:]] and [[:>:]] for whole word matches. You might be able to use this since you don't have spaces in your code.
This is ANSI SQL solution
This LIKE expression will find any pattern not alphanumeric.alphanumeric. So NOT LIKE find only this that match as you wish:
IF #vchAccountNumber NOT LIKE '%[^A-Z0-9].[^A-Z0-9]%'
However, based on your examples, you can use this...
LIKE '[A-Z][0-9][0-9][0-9][0-9].[0-9][0-9][0-9][0-9]'
...or one like this if you 5 alphas, dot, 4 alphas
LIKE '[A-Z0-9][A-Z0-9][A-Z0-9][A-Z0-9][A-Z0-9].[A-Z0-9][A-Z0-9][A-Z0-9][A-Z0-9]'
The 2nd one is slightly more obvious for fixed length values. The 1st one is slighty less intuitive but works with variable length code either side of the dot.
Other SO questions Creating a Function in SQL Server with a Phone Number as a parameter and returns a Random Number and Best equivalent for IsInteger in SQL Server