2

I have a DB using windows-1252 character encoding and dynamic SQL that does simple single quote escaping like this...

l_str := REPLACE(TRIM(someUserInput),'''','''''');

Because the DB is windows-1252 when the notorious Unicode Character 'MODIFIER LETTER APOSTROPHE' (U+02BC) is sent it gets converted.

Example: The front end app submits this...

TESTʼEND

But ends up searching on this...

and someColumn like '%TESTʼEND%'

What I want to know is, since the ʼ was converted into ʼ (which luckily is safe just yields wrong search results) is there any scenario where a non-windows-1252 characters can be converted into something that WILL break this thus making SQL injection possible?

I know about bind variables, I know the DB should be unicode as well, that's not what I'm asking here. I am needing proof that what you see above is not safe. I have searched for days and cannot find a way to cause SQL injection when doing simple single quote escaping like this when the DB is windows-1252. Thanks!

Oh, and always assuming the column being search is a varchar, not number. I am aware of the issues and how things change when dealing with numbers. So assume this is always the case:

l_str := REPLACE(TRIM(someUserInput),'''','''''');
...
... and someVarcharColumn like '%'||l_str||'%'
gfrobenius
  • 3,987
  • 8
  • 34
  • 66
  • What is the nls characterset of your DB? (Check `v$nls_parameters`) – ruudvan Mar 30 '16 at 21:35
  • NLS_CHARACTERSET: WE8MSWIN1252 – gfrobenius Mar 30 '16 at 21:38
  • To make things more complicated, you may also need to worry about the types of l_str and the variable it is concatenated with. If l_str or the statement variable is NVARCHAR2 or NCLOB maybe the character won't be caught by the REPLACE but will be implicitly converted to an apostrophe later. Would it help if such a test case was constructured? Or can you reasonably assume that l_str will always be used with regular VARCHAR2 variables? – Jon Heller Mar 31 '16 at 03:51
  • Or to take another approach, it might be easier to show the evils of not using bind variables with a date or number format. See [this AskTom](http://tkyte.blogspot.com/2012/02/all-about-security-sql-injection.html) page for an example. – Jon Heller Mar 31 '16 at 03:58

2 Answers2

1

Putting the argument of using bind variables aside, since you said you wanted proof that it could break without bind variables. Here's what's going on in your example -

The Unicode character 'MODIFIER LETTER APOSTROPHE' (U+02BC) in UTF-8 is made up of 2 bytes - 0xCA 0xBC.

Of that 0xCA is 'LATIN CAPITAL LETTER E WITH CIRCUMFLEX' which looks like - Ê

and 0xBC is 'VULGAR FRACTION ONE QUARTER' which looks like ¼.

This happens because your client probably uses an encoding that supports multi-byte characters but your DB doesn't. You would want to make sure that the encoding in both database and client is the same to avoid these issues.

Coming back to the question - is it possible that dynamic SQL without bind variables can be injected into because of these special unicode characters - The answer is probably yes.

All you need to break that dynamic sql using this encoding difference is a multibyte character, one of whose bytes is 0x27 which is an apostrophe.

I said 'probably' because a quick search on fileformat.info for 0x27 didn't give me anything back. Not sure if I'm using that site right. However that doesn't mean that it isn't possible, maybe a different client could use a different encoding.

I would recommend to never use dynamic SQL where input parameter values are used without bind variables, irrespective of whatever encoding you choose. You're just setting yourself up for so many problems going forward, apart from the performance penalty you have to pay to do a hard parse every single time.

Edit: And of course, most importantly, there is nothing stopping your client to send an actual apostrophe instead of the unicode multibyte character and that would be your definitive proof that the SQL is not safe and can be injected into.

Edit2: I missed your first part where you replace one apostrophe with 2. That should technically take care of the multibyte characters too. I'd still be against this approach.

ruudvan
  • 1,361
  • 6
  • 16
0

Your problem is not about SQL Injection, the problem is the character set of your front end app.

Your front end app sends the text in UTF-8, however the database "thinks" it is a Windows-1252 string.

Set your client NLS_LANG value to AMERICAN_AMERICA.AL32UTF8 (you may choose a different territory and/or language), then it should look better.

Then your front end app sends the string in UTF-8 and the database recognize it as UTF-8. It will be converted to Windows-1252 internally. I case you enter a string which is not supported by CP1252 (e.g. Cyrillic Capital Letter Ж) it will end up to something like Cyrillic Capital Letter ¿ - which should be fine in terms of SQL injection.

See this answer to get more information about database and client character sets.

Community
  • 1
  • 1
Wernfried Domscheit
  • 54,457
  • 9
  • 76
  • 110