Related
I saw a query run in a log file on an application. and it contained a query like:
SELECT ID FROM CUST_ATTR49 WHERE 1=0
what is the use of such a query that is bound to return nothing?
A query like this can be used to ping the database. The clause:
WHERE 1=0
Ensures that non data is sent back, so no CPU charge, no Network traffic or other resource consumption.
A query like that can test for:
server availability
CUST_ATTR49 table existence
ID column existence
Keeping a connection alive
Cause a trigger to fire without changing any rows (with the where clause, but not in a select query)
manage many OR conditions in dynamic queries (e.g WHERE 1=0 OR <condition>)
This may be also used to extract the table schema from a table without extracting any data inside that table. As Andrea Colleoni said those will be the other benefits of using this.
A usecase I can think of: you have a filter form where you don't want to have any search results. If you specify some filter, they get added to the where clause.
Or it's usually used if you have to create a sql query by hand. E.g. you don't want to check whether the where clause is empty or not..and you can just add stuff like this:
where := "WHERE 0=1"
if X then where := where + " OR ... "
if Y then where := where + " OR ... "
(if you connect the clauses with OR you need 0=1, if you have AND you have 1=1)
As an answer - but also as further clarification to what #AndreaColleoni already mentioned:
manage many OR conditions in dynamic queries (e.g WHERE 1=0 OR <condition>)
Purpose as an on/off switch
I am using this as a switch (on/off) statement for portions of my Query.
If I were to use
WHERE 1=1
AND (0=? OR first_name = ?)
AND (0=? OR last_name = ?)
Then I can use the first bind variable (?) to turn on or off the first_name search criterium. , and the third bind variable (?) to turn on or off the last_name criterium.
I have also added a literal 1=1 just for esthetics so the text of the query aligns nicely.
For just those two criteria, it does not appear that helpful, as one might thing it is just easier to do the same by dynamically building your WHERE condition by either putting only first_name or last_name, or both, or none. So your code will have to dynamically build 4 versions of the same query. Imagine what would happen if you have 10 different criteria to consider, then how many combinations of the same query will you have to manage then?
Compile Time Optimization
I also might add that adding in the 0=? as a bind variable switch will not work very well if all your criteria are indexed. The run time optimizer that will select appropriate indexes and execution plans, might just not see the cost benefit of using the index in those slightly more complex predicates. Hence I usally advice, to inject the 0 / 1 explicitly into your query (string concatenating it in in your sql, or doing some search/replace). Doing so will give the compiler the chance to optimize out redundant statements, and give the Runtime Executer a much simpler query to look at.
(0=1 OR cond = ?) --> (cond = ?)
(0=0 OR cond = ?) --> Always True (ignore predicate)
In the second statement above the compiler knows that it never has to even consider the second part of the condition (cond = ?), and it will simply remove the entire predicate. If it were a bind variable, the compiler could never have accomplished this.
Because you are simply, and forcedly, injecting a 0/1, there is zero chance of SQL injections.
In my SQL's, as one approach, I typically place my sql injection points as ${literal_name}, and I then simply search/replace using a regex any ${...} occurrence with the appropriate literal, before I even let the compiler have a stab at it. This basically leads to a query stored as follows:
WHERE 1=1
AND (0=${cond1_enabled} OR cond1 = ?)
AND (0=${cond2_enabled} OR cond2 = ?)
Looks good, easily understood, the compiler handles it well, and the Runtime Cost Based Optimizer understands it better and will have a higher likelihood of selecting the right index.
I take special care in what I inject. Prime way for passing variables is and remains bind variables for all the obvious reasons.
This is very good in metadata fetching and makes thing generic.
Many DBs have optimizer so they will not actually execute it but its still a valid SQL statement and should execute on all DBs.
This will not fetch any result, but you know column names are valid, data types etc. If it does not execute you know something is wrong with DB(not up etc.)
So many generic programs execute this dummy statement for testing and fetching metadata.
Some systems use scripts and can dynamically set selected records to be hidden from a full list; so a false condition needs to be passed to the SQL. For example, three records out of 500 may be marked as Privacy for medical reasons and should not be visible to everyone. A dynamic query will control the 500 records are visible to those in HR, while 497 are visible to managers. A value would be passed to the SQL clause that is conditionally set, i.e. ' WHERE 1=1 ' or ' WHERE 1=0 ', depending who is logged into the system.
quoted from Greg
If the list of conditions is not known at compile time and is instead
built at run time, you don't have to worry about whether you have one
or more than one condition. You can generate them all like:
and
and concatenate them all together. With the 1=1 at the start, the
initial and has something to associate with.
I've never seen this used for any kind of injection protection, as you
say it doesn't seem like it would help much. I have seen it used as an
implementation convenience. The SQL query engine will end up ignoring
the 1=1 so it should have no performance impact.
Why would someone use WHERE 1=1 AND <conditions> in a SQL clause?
If the user intends to only append records, then the fastest method is open the recordset without returning any existing records.
It can be useful when only table metadata is desired in an application. For example, if you are writing a JDBC application and want to get the column display size of columns in the table.
Pasting a code snippet here
String query = "SELECT * from <Table_name> where 1=0";
PreparedStatement stmt = connection.prepareStatement(query);
ResultSet rs = stmt.executeQuery();
ResultSetMetaData rsMD = rs.getMetaData();
int columnCount = rsMD.getColumnCount();
for(int i=0;i<columnCount;i++) {
System.out.println("Column display size is: " + rsMD.getColumnDisplaySize(i+1));
}
Here having a query like "select * from table" can cause performance issues if you are dealing with huge data because it will try to fetch all the records from the table. Instead if you provide a query like "select * from table where 1=0" then it will fetch only table metadata and not the records so it will be efficient.
Per user milso in another thread, another purpose for "WHERE 1=0":
CREATE TABLE New_table_name as select * FROM Old_table_name WHERE 1 =
2;
this will create a new table with same schema as old table. (Very
handy if you want to load some data for compares)
An example of using a where condition of 1=0 is found in the Northwind 2007 database. On the main page the New Customer Order and New Purchase Order command buttons use embedded macros with the Where Condition set to 1=0. This opens the form with a filter that forces the sub-form to display only records related to the parent form. This can be verified by opening either of those forms from the tree without using the macro. When opened this way all records are displayed by the sub-form.
In ActiveRecord ORM, part of RubyOnRails:
Post.where(category_id: []).to_sql
# => SELECT * FROM posts WHERE 1=0
This is presumably because the following is invalid (at least in Postgres):
select id FROM bookings WHERE office_id IN ()
It seems like, that someone is trying to hack your database. It looks like someone tried mysql injection. You can read more about it here: Mysql Injection
I am querying some data from the database and inserting data. Whenever the user inserts with ' I have a problem that the query does not regconize.
How can I get rid of that? should I use: string.replace(''', '"') ? or any other trick?
Thanks in advance.
You should be using parameterized queries. It's dangerous to insert unprocessed user input on a query, it's an open door to SQL-Injection attacks.
Those are queries in the form
SELECT * FROM USERS where USER_ID = ?
The value of ? is set programmatically with a query.setString(1, userId) call, and the driver takes care of escaping everything correctly. It's not a burden you want to have on your shoulders.
Besides to what Xavi López has posted (and you really should keep that in mind), to have a single quote in a string you need to write two single quotes, e.g.:
myString := 'I''m writing an answer';
This represents the string I'm writing an answer.
When I started to write the first SQL-Statements in my programs I felt quite comfortable with protecting myself against SQL-Injection with a very simple method that a colleague showed me. It replaced all single quotes with two single quotes.
So for example there is a searchfield in which you can enter a customername to search in the customertable. If you would enter
Peter's Barbershop
The SELECT Statement would look like
SELECT *
FROM Customers
WHERE Customername = 'Peter''s Barbershop'
If now an attacker would insert this:
';DROP TABLE FOO; --
The statement would look like:
SELECT *
FROM Customers
WHERE Customername = ''';DROP TABLE FOO;--'
It would not drop any table, but search the customertable for the customername ';DROP TABLE FOO;-- which, I suppose, won't be found ;-)
Now after a while of writing statements and protecting myself against SQL-Injection with this method, I read that many developers use parameterized statements, but I never read an article where "our" method was used. So definitely there is a good reason for it.
What scenarios would parameterized statements cover but our method doesn't? What are the advantages of parameterized statements compared to our method?
Thanks
Philipp
The parametrized queries has more proc than the defence to sql-injection.
It solves problem with date & time formating & parsing.
You can prepare execution plan for parametrized query.
The sql-injection protection.
I can't remember now for another pros :).
However the way "double every quotes" has problem with fields with limited character length.
For example:
The page has box for "nickname" which can be 10 character long.
The user insert "Don't care" - the exact 10 characters.
Now if you double the quotes, the value has 11 characters and the database will "cut" it, and you got another value in db than user typed.
So I recommend the parameters.
One big dis-advantage is that your solution relies on a developer remembering to add the character, obviously the compiler won't complain. That is dangerous.
Secondly, performance should be enhanced with parameterized SQL statements, as Jeff points out here (in 2005!!!).
One advantage is that the driver itself will determine what he has to escape and what doesn't need to be escaped. Your method could be broken with an input like this:
\'; DROP TABLE foo;--
Which would result in
SELECT *
FROM Customers
WHERE Customername = '\'';DROP TABLE FOO;--'
The first quote gets escaped, the second doesn't and closes the string.
Short answer:
You should use parameterized queries simply because the database server knows better than you do which characters need to be escaped.
Long answer:
' is not necessarily the only special character that needs escaping. These special characters differ from DB server to DB server. MySQL, for example, uses \ as an escape character as well (unless sql_mode=NO_BACKSLASH_ESCAPES is set). Therefore, '' and \' mean the same thing.
This is not true of, say, Oracle.
What are the advantages of
parameterized statements compared to
our method?
The advantage is that it's harder to make a mistake; you can't do the parameterized method, and forget to replace the quotes. Also, replacing quotes is vulnerable if you do it twice.
The disadvantage of parameterized queries (and the reason I never use them) is complexity. You can write ten times as many ad-hoc queries before you get RSI.
I know it's a simple question, but in everything I've read, I've never seen this spelled out specifically.
If you do a query on a page, do you need to worry about SQL injection attacks? Or is it only a problem when you ask the user for input?
Thanks!
You don't have to have user input to suffer a SQL injection attack.
Let's say you have a product page that is called using a URL such as this:
product.aspx?ID=123
And in your code you have a query constructed such as this:
string sql = "SELECT * FROM Products WHERE ID = " + Request.Querystring["ID"];
Someone could call your page with this url:
product.aspx?ID=123;DROP Table Students;
And bam, you've just been had.
In addition to ANYTHING that can be passed in via a user, querystring, post, cookie, browser variable, etc. I think it is just good practice to always use parameters, even if you have the literals in your code. For example:
if(SomeCondition)
{
sql = "Select * from myTable where someCol = 'foo'";
}
else
{
sql = "Select * from myTable where someCol = 'bar'";
}
this may be injection safe, but your RDBMS will cache them as two different queries.
if you modiy it to this:
sql = "Select * from myTable where someCol = #myParam";
if(SomeCondition)
{
myCommand.Parameters.Add("#myParam").value = "foo";
}
else
{
myCommand.Parameters.Add("#myParam").value = "bar";
}
You achieve the same result but the RDBMS will only cache it as one query, substituting the parameter at runtime. I use it as a rule of thumb to ALWAYS use parameterized queries, just to keep things consistent, not to mention a slight cache improvement.
SQL injection is caused by unsanitized data. You should always always always sanitize data going into a database. Not just for SQL injection, but also for making your app just work.
For example, some systems won't use my name because it has a ' character in it, and their database is not sanitized. I did not enter my name, my name was taken from another database. Doesn't matter -- the data should be sanitized.
SQL Injection snippets can also come in from the QueryString (aka "URL arguments") passed in with the GET method instead.
As hinted by Billy O'Neal [single quote intended ;-) ], any piece of data that is not intrinsic to the program (or to its very trusted back-end), should be "sanitized". The Sanitizing term seems to imply to be a sophisticated process, but in effect it typically means little more than:
[may vary with your specific SQL server make]
remove (or escape) single quotes characters embedded within a string
watch from strings exceeded the length of the underlying SQL column (in particular if such length is readily long)
A possible reason for the idea that HTTP Forms would be the only source of SQL injection snippets is that a -valid- recommendation is to ensure that one gets the user-supplied submitted text from the Request's form exclusively. Several Web Application frameworks expose the HTTP request as an object which exposes, by default, all key-values pairs from either the QueryString, from a Form, or even from cookies, accessible as from a single hash. While this can be practical for applications that sometimes get the info from a form an sometimes from the querystring, this can facilitate the work of would-be-injectors, because it is easier to craft a URL than a Form. (But with the proper tool, one can also fake a POST request as well...)
No, there are several other cases. For example, you may have some of the variables as a querystring passed into a php page. The 'user' could modify that string to include some dodgy scripting.
http://en.wikipedia.org/wiki/SQL_injection includes a large section on the types of vulnerabilities and how to combat them effectively.
To summarize - any type of input from the user that is used in SQL queries is a potential target of sql injection
Also consider preventing against cross-site-scripting ("XSS").
SQL Injections is possible if you use any kind of data that comes from the browser. It could be form data, querystring data, cookie values, or even data from the request header.
The obvious and easy ways in is the form data and querystring data, but anything that comes from the browser could be spoofed.
Anything that the code takes as input from the HTTP request can be a SQL injection vector:
POST/PUT content
GET URL parameters
Cookies
At a higher level these show up as $_REQUEST or Page.Request values, session variable, it all depends on a miriad of factors. but ultimately, is not just POST forms. Although probably the most prvalent vector is form POST content and GET URL variables.
When the user can modify the values of the parameters of a query, then it can become a threat.
You need to worry about cross site scripting (XSS) attacks in this case if the data you are displaying on the page came from user submitted data.
ESCAPE INPUT, FILTER OUTPUT
As I concern you should never trust this variables: $_POST, $_GET, $_REQUEST, $_COOKIE even $_SERVER can contain malicious code. So ALWAYS make sure that inserted data match your expectation.
For example as an extra paranoid measure on validation email address you can encrypt email address with md5 like this:
"SELECT username FROM users WHERE MD5(email)='" . md5($_POST['email']) . "' AND active=1"
As a general rule parameterized queries should always be used.
It prevents malicious user input from being executed against your database (SQL injection attacks). [You should do user input validation as well to ensure that malicious code isn't rendered on the page and that JavaScript can be run against your server.]
It enables you to re-use your queries.
You can precompile your queries.
It organizes your input and makes it more readable. You might want to use the same parameter in more than one location.
It has better support for different data type such as dates, strings and the like. You won't run into problems with weird characters when you use parameterized queries.
In my use case I always generate parameter based queries. I have a wrapper that will always compile them so that if a second query gets executed in the same request path, it will run that much faster on the same connection. This takes a fair bit of work to setup, but is worth the performance gain in any medium to enterprise level system.
I agree that parameterisation is the best approach.
As an alternative (which might be easier to retro fit into your code, at least initially) doubling the single quotes in a string will prevent SQL Injection.
To take Neil N's example:
sql = "Select * From Products Where ID = " + Request.Querystring["ID"];
wrap the variable in a function that doubles the quotes, and wrap the varible with single quotes too.
sql = "Select * From Products Where ID = "
+ fnSQLSafeParam(Request.Querystring["ID"]);
The function would be something like (VBscript example):
Function fnSQLSafeParam(ByVal strStr)
If IsNull(strStr) or IsEmpty(strStr) then strStr = ""
fnSQLSafeParam = "'" & replace(Trim(CStr(strStr)), "'", "''") & "'"
End Function
If I remove all the ' characters from a SQL query, is there some other way to do a SQL injection attack on the database?
How can it be done? Can anyone give me examples?
Yes, there is. An excerpt from Wikipedia
"SELECT * FROM data WHERE id = " + a_variable + ";"
It is clear from this statement that the author intended a_variable to be a number correlating to the "id" field. However, if it is in fact a string then the end user may manipulate the statement as they choose, thereby bypassing the need for escape characters. For example, setting a_variable to
1;DROP TABLE users
will drop (delete) the "users" table from the database, since the SQL would be rendered as follows:
SELECT * FROM DATA WHERE id=1;DROP TABLE users;
SQL injection is not a simple attack to fight. I would do very careful research if I were you.
Yes, depending on the statement you are using. You are better off protecting yourself either by using Stored Procedures, or at least parameterised queries.
See Wikipedia for prevention samples.
I suggest you pass the variables as parameters, and not build your own SQL. Otherwise there will allways be a way to do a SQL injection, in manners that we currently are unaware off.
The code you create is then something like:
' Not Tested
var sql = "SELECT * FROM data WHERE id = #id";
var cmd = new SqlCommand(sql, myConnection);
cmd.Parameters.AddWithValue("#id", request.getParameter("id"));
If you have a name like mine with an ' in it. It is very annoying that all '-characters are removed or marked as invalid.
You also might want to look at this Stackoverflow question about SQL Injections.
Yes, it is definitely possible.
If you have a form where you expect an integer to make your next SELECT statement, then you can enter anything similar:
SELECT * FROM thingy WHERE attributeID=
5 (good answer, no problem)
5; DROP table users; (bad, bad, bad...)
The following website details further classical SQL injection technics: SQL Injection cheat sheet.
Using parametrized queries or stored procedures is not any better. These are just pre-made queries using the passed parameters, which can be source of injection just as well. It is also described on this page: Attacking Stored Procedures in SQL.
Now, if you supress the simple quote, you prevent only a given set of attack. But not all of them.
As always, do not trust data coming from the outside. Filter them at these 3 levels:
Interface level for obvious stuff (a drop down select list is better than a free text field)
Logical level for checks related to data nature (int, string, length), permissions (can this type of data be used by this user at this page)...
Database access level (escape simple quote...).
Have fun and don't forget to check Wikipedia for answers.
Parameterized inline SQL or parameterized stored procedures is the best way to protect yourself. As others have pointed out, simply stripping/escaping the single quote character is not enough.
You will notice that I specifically talk about "parameterized" stored procedures. Simply using a stored procedure is not enough either if you revert to concatenating the procedure's passed parameters together. In other words, wrapping the exact same vulnerable SQL statement in a stored procedure does not make it any safer. You need to use parameters in your stored procedure just like you would with inline SQL.
Also- even if you do just look for the apostrophe, you don't want to remove it. You want to escape it. You do that by replacing every apostrophe with two apostrophes.
But parameterized queries/stored procedures are so much better.
Since this a relatively older question, I wont bother writing up a complete and comprehensive answer, since most aspects of that answer have been mentioned here by one poster or another.
I do find it necessary, however, to bring up another issue that was not touched on by anyone here - SQL Smuggling. In certain situations, it is possible to "smuggle" the quote character ' into your query even if you tried to remove it. In fact, this may be possible even if you used proper commands, parameters, Stored Procedures, etc.
Check out the full research paper at http://www.comsecglobal.com/FrameWork/Upload/SQL_Smuggling.pdf (disclosure, I was the primary researcher on this) or just google "SQL Smuggling".
. . . uh about 50000000 other ways
maybe somthing like 5; drop table employees; --
resulting sql may be something like:
select * from somewhere where number = 5; drop table employees; -- and sadfsf
(-- starts a comment)
Yes, absolutely: depending on your SQL dialect and such, there are many ways to achieve injection that do not use the apostrophe.
The only reliable defense against SQL injection attacks is using the parameterized SQL statement support offered by your database interface.
Rather that trying to figure out which characters to filter out, I'd stick to parametrized queries instead, and remove the problem entirely.
It depends on how you put together the query, but in essence yes.
For example, in Java if you were to do this (deliberately egregious example):
String query = "SELECT name_ from Customer WHERE ID = " + request.getParameter("id");
then there's a good chance you are opening yourself up to an injection attack.
Java has some useful tools to protect against these, such as PreparedStatements (where you pass in a string like "SELECT name_ from Customer WHERE ID = ?" and the JDBC layer handles escapes while replacing the ? tokens for you), but some other languages are not so helpful for this.
Thing is apostrophe's maybe genuine input and you have to escape them by doubling them up when you are using inline SQL in your code. What you are looking for is a regex pattern like:
\;.*--\
A semi colon used to prematurely end the genuine statement, some injected SQL followed by a double hyphen to comment out the trailing SQL from the original genuine statement. The hyphens may be omitted in the attack.
Therefore the answer is: No, simply removing apostrophes does not gaurantee you safety from SQL Injection.
I can only repeat what others have said. Parametrized SQL is the way to go. Sure, it is a bit of a pain in the butt coding it - but once you have done it once, then it isn't difficult to cut and paste that code, and making the modifications you need. We have a lot of .Net applications that allow web site visitors specify a whole range of search criteria, and the code builds the SQL Select statement on the fly - but everything that could have been entered by a user goes into a parameter.
When you are expecting a numeric parameter, you should always be validating the input to make sure it's numeric. Beyond helping to protect against injection, the validation step will make the app more user friendly.
If you ever receive id = "hello" when you expected id = 1044, it's always better to return a useful error to the user instead of letting the database return an error.