Can you write a sql statement without spaces between keywords - sql

I am trying to do SQL Injection testing but I am currently testing a command line that separates parameters by spaces, so I'm trying to write a sql statement without any spaces. I've gotten it down to:
create table"aab"("id"int,"notes"varchar(100))
But I cannot figure out how to get rid of the space between CREATE and TABLE. The same would apply obviously for DROP and TABLE, etc.
Does anyone have any ideas? This is for Microsoft SQL Server 2014. Thanks!
[Update]: We are evaluating a third party product for vulnerabilities. I am not doing this to test my own code for weaknesses.

You can write comments between lines instead of spaces in many cases. So /**/ instead of spaces.

Sure it is possible to write some pretty elaborate statements without spaces.
Here is one.
select'asdf'as[asdf]into[#MyTable]
You can even do things like execute sp_executesql without spaces.
exec[sp_executesql]N'select''asdf''as[asdf]into[#MyTable]'

This is not possible, you have to check every argument to make sure they are as intended.
If they are supposed to be numbers, make sure they are numbers, is they are supposed to be a string that may contain specific caracters (like ' or ,) you should escape them when executing the request.
There should be a dedicated mechanism in your programmation langage to take care of hat (like PreparedStatement in Java)

You can also using brackets () for every functions without spaces
SELECT(COUNT(id))FROM(users)where(id>5)

Related

How can my code be injected with SQL injection?

I have the following code running for logging in.
M_INVALID_PASSWORD_OR_USERNAME_2 SELECT `s1_members`.* FROM `s1_members`
WHERE (`password` LIKE '5bd7002ef05124e82000bb83d83455ec8c50a1e8') AND
(email LIKE 'test#tefrfrfwfe.frrfr' OR phone LIKE 'test#tefrfrfwfe.frrfr')"
I know my email/phone seem to be vulnerable, but I am escaping singled quotes by adding two backlashes (\) before each single quote. The double quotes get escaped by adding three backlashes beforehead (\). I also escape backslash by adding three more backslashes after (\).
I am still a learning in this field, so want to know in what ways/payloads then can an attacker inject an SQL injection? If there are payloads that will be executable here, then how do I protect myself?
I have tried different kinds of SQL injections I could find on Internet and seems that my special character escaping is working fine. I know it's not ideal though, so want to know what type of payloads of SQL injection can be successfully executed in my code.
You should use prepared statements (aka parameterized queries). When using prepared statements the parameters are never interpreted as SQL, they're simply processed by the database as data.
The escaping technique you're using, even if it works, is fragile. It is dependent on the client language, how the string is composed on the client, and which database you're using.
A couple of things that could go wrong:
The string on the client could have a fixed length - the encoding mechanism can be manipulated by the hacker to overrun that length. That can be used to truncate off key parts of the query or create buffer overflows.
The slashes may be interpreted by the client language as well, switching the client context might change the number of slashes required.
The database might change - either because the code is used with a different database or the behavior changes on upgrade. As mentioned by Jeroen in the comments, databases all handle encoding differently.

Preventing SQL injection without prepared statements/SQLite/C++

I'd appreciate some feedback on how secure this scheme is against SQL injection attacks.
At the front end, the user enters personal information: name, address, phone numbers, email, and some freeform text.
The back-end is coded from scratch in C++, with no framework support, and integrates SQLite.
The C++ code does not use SQLite prepared statements (for historical reasons, and it's too late to do anything about it). Instead, all SQL statements are constructed as printf-style format strings, along these lines:
#define STATEMENT_N "UPDATE members SET FirstName='%s', Surname='%s', DOB='%s', etc"
The actual statements are created with a hand-coded sprintf (sqlPrintf) statement which handles only %s, %c, and %d conversions. The final statement is then created something like:
sqlPrintf(query_buffer, STATEMENT_N, user_str_1, user_str_2, etc)
So, in other words (if you're not familiar with C/sprintf), the user input is 'printed' into the %s, %c, and %d. The only non-obvious processing in sqlPrintf is that user-supplied single-quote characters are escaped (they're doubled up).
Is this sufficient to prevent SQL injection attacks? And is a 'prepared statement' actually anything more than the above scheme?
Basically, the only thing you need to worry about here is the single quotes. Anything contained within single quotes in your query will be fine, but a lone single quote can end the string, allowing the rest of the data entry to run as code. If sqlPrintf doubles up single quotes, you should be fine. And reading the comments on your question, it sounds like this system works against the "';--" attack. :)
Doubling single quotes is sufficient to prevent injection problems with strings. There are no other special characters recognized inside strings.
(Please note that SQLite already has helper functions for this.)
If you ever need to handle blobs, you'd have to use parameters anyway. But that is a different question …

sql injection when single quote in input is always replaced with double quote

Suppose sql query invoked by the login form is:
SELECT * FROM Users WHERE Name ='user input data' AND Pass ='user input data'
Now all single quotes in user input data are replaced with double single quotes (in other words, ' is replaced with ''.).
I can think of this possible sql injection: set user as the intended user and set the password as '\' or 1=1
but I can't think of how I am going to avoid the last ' from disrupting my sql injection.
Avoiding the last ' from disrupting your SQL injection is as simple as using a comment, for example (-- works great for single-line SQL). Alternatively, you can always add something like this:
someHack and '' = '
Now, is it possible to get around your single-quote to double-quote replacement? That most likely depends heavily on the actual SQL variant and the SQL engine you're using. For example, some SQL engines might treat endlines in input in a way that would give you trouble. Unicode is very likely to give you trouble as well, with its very complicated rules. In particular, if parts of your code are unicode aware and others aren't, it's quite easy to pass a harmless unicode character to someone who expects ASCII, and actually use your replacement to add the (unescaped) quote. In case you think this is a weird edge case, it's actually a very real and used SQL injection vector for PHP programmers who thought replace (or addslashes) is good enough to prevent SQL injection :D
If possible, try to use parameters instead of slapping text together. It will likely help your performance as well :) The simplest way to avoid parser bugs is to avoid using the parser.

does removing all non-numeric characters effectively escape data?

I use this function to strip all non-numeric from a field before writing to a MYSQL dB:
function remove_non_numeric($inputtext) {return preg_replace("/[^0-9]/","",$inputtext);
Does this effectively escape the input data to prevent SQL Injection? I could wrap this function in mysql_real_escape_string, but thought that might be redundant.
Assumption is the mother of all bleep when it comes to sql injection. Wrap it in mysql_real_escape_string anyway.
It does not escape the data, but it is indeed an example of an OWASP recommended approach.
By removing all but numerics from the input you are effectively protecting against SQL-Injection by implementing a White list. There is no amount of paranoia that can make the resulting string (in this specific case) into an effective SQL Injection payload.
However, code ages, and changes and is misunderstood as it's inherited by new developers. So the bottom line, the correct advice, the end all and be all - is to actively prevent against SQL Injection with one or more of the following 3 steps. In this order. Ever. Single. Time.
Use a safe database API. (prepared statements or parametrized queries for example)
Use db specific escaping or escaping routines (mysql_real_escape_string falls into this category).
White list the domain of acceptable input values. (Your proposed numeric solution falls into this category)
mysql_real_escape_string is not the answer for all anti-sql-injection. It's not even the most robust method, but it works. Stripping all but numerics is white listing the safe values and is also a sound idea - however, neither are as good as using a safe API.

Can I protect against SQL injection by escaping single-quote and surrounding user input with single-quotes?

I realize that parameterized SQL queries is the optimal way to sanitize user input when building queries that contain user input, but I'm wondering what is wrong with taking user input and escaping any single quotes and surrounding the whole string with single quotes. Here's the code:
sSanitizedInput = "'" & Replace(sInput, "'", "''") & "'"
Any single-quote the user enters is replaced with double single-quotes, which eliminates the users ability to end the string, so anything else they may type, such as semicolons, percent signs, etc., will all be part of the string and not actually executed as part of the command.
We are using Microsoft SQL Server 2000, for which I believe the single-quote is the only string delimiter and the only way to escape the string delimiter, so there is no way to execute anything the user types in.
I don't see any way to launch an SQL injection attack against this, but I realize that if this were as bulletproof as it seems to me someone else would have thought of it already and it would be common practice.
What's wrong with this code? Is there a way to get an SQL injection attack past this sanitization technique? Sample user input that exploits this technique would be very helpful.
UPDATE:
I still don't know of any way to effectively launch a SQL injection attack against this code. A few people suggested that a backslash would escape one single-quote and leave the other to end the string so that the rest of the string would be executed as part of the SQL command, and I realize that this method would work to inject SQL into a MySQL database, but in SQL Server 2000 the only way (that I've been able to find) to escape a single-quote is with another single-quote; backslashes won't do it.
And unless there is a way to stop the escaping of the single-quote, none of the rest of the user input will be executed because it will all be taken as one contiguous string.
I understand that there are better ways to sanitize input, but I'm really more interested in learning why the method I provided above won't work. If anyone knows of any specific way to mount a SQL injection attack against this sanitization method I would love to see it.
First of all, it's just bad practice. Input validation is always necessary, but it's also always iffy.
Worse yet, blacklist validation is always problematic, it's much better to explicitly and strictly define what values/formats you accept. Admittedly, this is not always possible - but to some extent it must always be done.
Some research papers on the subject:
http://www.imperva.com/docs/WP_SQL_Injection_Protection_LK.pdf
http://www.it-docs.net/ddata/4954.pdf (Disclosure, this last one was mine ;) )
https://www.owasp.org/images/d/d4/OWASP_IL_2007_SQL_Smuggling.pdf (based on the previous paper, which is no longer available)
Point is, any blacklist you do (and too-permissive whitelists) can be bypassed. The last link to my paper shows situations where even quote escaping can be bypassed.
Even if these situations do not apply to you, it's still a bad idea. Moreover, unless your app is trivially small, you're going to have to deal with maintenance, and maybe a certain amount of governance: how do you ensure that its done right, everywhere all the time?
The proper way to do it:
Whitelist validation: type, length, format or accepted values
If you want to blacklist, go right ahead. Quote escaping is good, but within context of the other mitigations.
Use Command and Parameter objects, to preparse and validate
Call parameterized queries only.
Better yet, use Stored Procedures exclusively.
Avoid using dynamic SQL, and dont use string concatenation to build queries.
If using SPs, you can also limit permissions in the database to executing the needed SPs only, and not access tables directly.
you can also easily verify that the entire codebase only accesses the DB through SPs...
Okay, this response will relate to the update of the question:
"If anyone knows of any specific way to mount a SQL injection attack against this sanitization method I would love to see it."
Now, besides the MySQL backslash escaping - and taking into account that we're actually talking about MSSQL, there are actually 3 possible ways of still SQL injecting your code
sSanitizedInput = "'" & Replace(sInput, "'", "''") & "'"
Take into account that these will not all be valid at all times, and are very dependant on your actual code around it:
Second-order SQL Injection - if an SQL query is rebuilt based upon data retrieved from the database after escaping, the data is concatenated unescaped and may be indirectly SQL-injected. See
String truncation - (a bit more complicated) - Scenario is you have two fields, say a username and password, and the SQL concatenates both of them. And both fields (or just the first) has a hard limit on length. For instance, the username is limited to 20 characters. Say you have this code:
username = left(Replace(sInput, "'", "''"), 20)
Then what you get - is the username, escaped, and then trimmed to 20 characters. The problem here - I'll stick my quote in the 20th character (e.g. after 19 a's), and your escaping quote will be trimmed (in the 21st character). Then the SQL
sSQL = "select * from USERS where username = '" + username + "' and password = '" + password + "'"
combined with the aforementioned malformed username will result in the password already being outside the quotes, and will just contain the payload directly.
3. Unicode Smuggling - In certain situations, it is possible to pass a high-level unicode character that looks like a quote, but isn't - until it gets to the database, where suddenly it is. Since it isn't a quote when you validate it, it will go through easy... See my previous response for more details, and link to original research.
In a nutshell: Never do query escaping yourself. You're bound to get something wrong. Instead, use parameterized queries, or if you can't do that for some reason, use an existing library that does this for you. There's no reason to be doing it yourself.
I realize this is a long time after the question was asked, but ..
One way to launch an attack on the 'quote the argument' procedure is with string truncation.
According to MSDN, in SQL Server 2000 SP4 (and SQL Server 2005 SP1), a too long string will be quietly truncated.
When you quote a string, the string increases in size. Every apostrophe is repeated.
This can then be used to push parts of the SQL outside the buffer. So you could effectively trim away parts of a where clause.
This would probably be mostly useful in a 'user admin' page scenario where you could abuse the 'update' statement to not do all the checks it was supposed to do.
So if you decide to quote all the arguments, make sure you know what goes on with the string sizes and see to it that you don't run into truncation.
I would recommend going with parameters. Always. Just wish I could enforce that in the database. And as a side effect, you are more likely to get better cache hits because more of the statements look the same. (This was certainly true on Oracle 8)
I've used this technique when dealing with 'advanced search' functionality, where building a query from scratch was the only viable answer. (Example: allow the user to search for products based on an unlimited set of constraints on product attributes, displaying columns and their permitted values as GUI controls to reduce the learning threshold for users.)
In itself it is safe AFAIK. As another answerer pointed out, however, you may also need to deal with backspace escaping (albeit not when passing the query to SQL Server using ADO or ADO.NET, at least -- can't vouch for all databases or technologies).
The snag is that you really have to be certain which strings contain user input (always potentially malicious), and which strings are valid SQL queries. One of the traps is if you use values from the database -- were those values originally user-supplied? If so, they must also be escaped. My answer is to try to sanitize as late as possible (but no later!), when constructing the SQL query.
However, in most cases, parameter binding is the way to go -- it's just simpler.
Input sanitation is not something you want to half-ass. Use your whole ass. Use regular expressions on text fields. TryCast your numerics to the proper numeric type, and report a validation error if it doesn't work. It is very easy to search for attack patterns in your input, such as ' --. Assume all input from the user is hostile.
It's a bad idea anyway as you seem to know.
What about something like escaping the quote in string like this: \'
Your replace would result in: \''
If the backslash escapes the first quote, then the second quote has ended the string.
Simple answer: It will work sometimes, but not all the time.
You want to use white-list validation on everything you do, but I realize that's not always possible, so you're forced to go with the best guess blacklist. Likewise, you want to use parametrized stored procs in everything, but once again, that's not always possible, so you're forced to use sp_execute with parameters.
There are ways around any usable blacklist you can come up with (and some whitelists too).
A decent writeup is here: http://www.owasp.org/index.php/Top_10_2007-A2
If you need to do this as a quick fix to give you time to get a real one in place, do it. But don't think you're safe.
There are two ways to do it, no exceptions, to be safe from SQL-injections; prepared statements or prameterized stored procedures.
If you have parameterised queries available you should be using them at all times. All it takes is for one query to slip through the net and your DB is at risk.
Patrick, are you adding single quotes around ALL input, even numeric input? If you have numeric input, but are not putting the single quotes around it, then you have an exposure.
Yeah, that should work right up until someone runs SET QUOTED_IDENTIFIER OFF and uses a double quote on you.
Edit: It isn't as simple as not allowing the malicious user to turn off quoted identifiers:
The SQL Server Native Client ODBC driver and SQL Server Native Client OLE DB Provider for SQL Server automatically set QUOTED_IDENTIFIER to ON when connecting. This can be configured in ODBC data sources, in ODBC connection attributes, or OLE DB connection properties. The default for SET QUOTED_IDENTIFIER is OFF for connections from DB-Library applications.
When a stored procedure is created, the SET QUOTED_IDENTIFIER and SET ANSI_NULLS settings are captured and used for subsequent invocations of that stored procedure.
SET QUOTED_IDENTIFIER also corresponds to the QUOTED_IDENTIFER setting of ALTER DATABASE.
SET QUOTED_IDENTIFIER is set at parse time. Setting at parse time means that if the SET statement is present in the batch or stored procedure, it takes effect, regardless of whether code execution actually reaches that point; and the SET statement takes effect before any statements are executed.
There's a lot of ways QUOTED_IDENTIFIER could be off without you necessarily knowing it. Admittedly - this isn't the smoking gun exploit you're looking for, but it's a pretty big attack surface. Of course, if you also escaped double quotes - then we're back where we started. ;)
Your defence would fail if:
the query is expecting a number rather than a string
there were any other way to represent a single quotation mark, including:
an escape sequence such as \039
a unicode character
(in the latter case, it would have to be something which were expanded only after you've done your replace)
What ugly code all that sanitisation of user input would be! Then the clunky StringBuilder for the SQL statement. The prepared statement method results in much cleaner code, and the SQL Injection benefits are a really nice addition.
Also why reinvent the wheel?
Rather than changing a single quote to (what looks like) two single quotes, why not just change it to an apostrophe, a quote, or remove it entirely?
Either way, it's a bit of a kludge... especially when you legitimately have things (like names) which may use single quotes...
NOTE: Your method also assumes everyone working on your app always remembers to sanitize input before it hits the database, which probably isn't realistic most of the time.
I'm not sure about your case, but I just encountered a case in Mysql that Replace(value, "'", "''") not only can't prevent SQL injection, but also causes the injection.
if an input ended with \', it's OK without replace, but when replacing the trailing ', the \ before end of string quote causes the SQL error.
While you might find a solution that works for strings, for numerical predicates you need to also make sure they're only passing in numbers (simple check is can it be parsed as int/double/decimal?).
It's a lot of extra work.
It might work, but it seems a little hokey to me. I'd recommend verifing that each string is valid by testing it against a regular expression instead.
Yes, you can, if...
After studying the topic, I think input sanitized as you suggested is safe, but only under these rules:
you never allow string values coming from users to become anything else than string literals (i.e. avoid giving configuration option: "Enter additional SQL column names/expressions here:"). Value types other than strings (numbers, dates, ...): convert them to their native data types and provide a routine for SQL literal from each data type.
SQL statements are problematic to validate
you either use nvarchar/nchar columns (and prefix string literals with N) OR limit values going into varchar/char columns to ASCII characters only (e.g. throw exception when creating SQL statement)
this way you will be avoiding automatic apostrophe conversion from CHAR(700) to CHAR(39) (and maybe other similar Unicode hacks)
you always validate value length to fit actual column length (throw exception if longer)
there was a known defect in SQL Server allowing to bypass SQL error thrown on truncation (leading to silent truncation)
you ensure that SET QUOTED_IDENTIFIER is always ON
beware, it is taken into effect in parse-time, i.e. even in inaccessible sections of code
Complying with these 4 points, you should be safe. If you violate any of them, a way for SQL injection opens.