query string sql injection - sql

Examining some logs in my web site, I discovered that a bunch of querystring variables contains sql injection snippets:
'myvalue AND CHAR(124) USER CHAR(124)=0 AND ='
'myvalue AND 1=2'
How do you sanitize the querystring variables?
The platform is ASP.NET, fm 4.0, SQL Server 2008. So go with the parametrized query. But there is a part of the application (an old one) running classic ASP. There is no parametrized query in classic ASP...

You shouldn't worry about sanitizing query string values.
You should worry about writing code that doesn't have SQL Injection vectors to begin with. Parameterized Queries are the way to go. Depending on your platform, the exact SQL can vary a bit.
As it seems you already know how to work with parameterized queries in .NET, I'll skip that.
As for the Classic ASP page, you should take a look at How To Call a Parameterized Query with ADO (paying special attention to the change at the bottom to use a SQL Statement rather than a Stored Procedure).

I think I had two websites of mine hacked by such a hack! The way to stop the hack is to check the data being read before it hits the database.
If the value is a number check the string has only chars 0-9 in it, if not send them to the page not found!
If you are using strings like 'yes', 'no', 'true', 'false', values that you define don't add them to the database string directly, check for them with an if such as,
If(request("dog").equals("true")){...
finally if the value is a string that the client has entered then watch for ' char. An insertion hack works by first closing the string with ' then the expression with ; and then adding and update, insert or delete statement. so if ' ; and for good luck " is escaped the string cannot be closed.
Note: the same thing is true for text boxes, form sends and Ajax.
Always do these checks on the server as a hacker can always fake a page.

Related

SQL Parameters - where does expansion happens

I'm getting a little confused about using parameters with SQL queries, and seeing some things that I can't immediately explain, so I'm just after some background info at this point.
First, is there a standard format for parameter names in queries, or is this database/middleware dependent ? I've seen both this:-
DELETE * FROM #tablename
and...
DELETE * FROM :tablename
Second - where (typically) does the parameter replacement happen? Are parameters replaced/expanded before the query is sent to the database, or does the database receive params and query separately, and perform the expansion itself?
Just as background, I'm using the DevArt UniDAC toolkit from a C++Builder app to connect via ODBC to an Excel spreadsheet. I know this is almost pessimal in a few ways... (I'm trying to understand why a particular command works only when it doesn't use parameters)
With such data access libraries, like UniDAC or FireDAC, you can use macros. They allow you to use special markers (called macro) in the places of a SQL command, where parameter are disallowed. I dont know UniDAC API, but will provide a sample for FireDAC:
ADQuery1.SQL.Text := 'DELETE * FROM &tablename';
ADQuery1.MacroByName('tablename').AsRaw := 'MyTab';
ADQuery1.ExecSQL;
Second - where (typically) does the parameter replacement happen?
It doesn't. That's the whole point. Data elements in your query stay data items. Code elements stay code elements. The two never intersect, and thus there is never an opportunity for malicious data to be treated as code.
connect via ODBC to an Excel spreadsheet... I'm trying to understand why a particular command works only when it doesn't use parameters
Excel isn't really a database engine, but if it were, you still can't use a parameter for the name a table.
SQL parameters are sent to the database. The database performs the expansion itself. That allows the database to set up a query plan that will work for different values of the parameters.
Microsoft always uses #parname for parameters. Oracle uses :parname. Other databases are different.
No database I know of allows you to specify the table name as a parameter. You have to expand that client side, like:
command.CommandText = string.Format("DELETE FROM {0}", tableName);
P.S. A * is not allowed after a DELETE. After all, you can only delete whole rows, not a set of columns.

SQL injection in Symfony/Doctrine

Using parameters instead of placing values directly in the query string is done to prevent SQL injection attacks and should always be done:
... WHERE p.name > :name ...
->setParameter('name', 'edouardo')
Does this mean that if we use parameters like this, we will always be protected against SQL injections? While using a form (registration form of FOS), I put <b>eduardo</b> instead and this was persisted to the database with the tags. I don't really understand why using parameters is preventing against SQL injections...
Why are the tags persisted to the database like this? Is there a way to remove the tags by using Symfony's validation component?
Is there a general tip or method that we should be using before persisting data in the database in Symfony?
Start with reading on what's SQL injection.
SQL injection attack takes place when value put into the SQL alters the query. As a result the query performs something else that it was intended to perform.
Example would be using edouardo' OR '1'='1 as a value which would result in:
WHERE p.name > 'edouardo' OR '1'='1'
(so the condition is always true).
"<b>eduardo</b>" is a completely valid value. In some cases you will want to save it as submited (for example content management system). Of course it could break your HTML when you take it from the database and output directly. This should be solved by your templating engine (twig will automatically escape it).
If you want process data before passing it from a form to your entity use data transformers.
If you use parameters instead of concatenation when creating a request, the program is able to tell SQL keywords and values apart. It can therefore safely escape values that may contain malicious SQL code, so that this malicious does not get executed, but stored in a field, like it should.
HTML code injection is another problem, which has nothing to do with databases. This problem is solved when displaying the value, by using automatic output escaping, which will display <b>eduardo</b> instead of eduardo. This way, any malicious js / html code won't be interpreted : it will be displayed.

PDO prepare statements: Do we need to escape?

public function receiveDomainNames($keyword)
{
try
{
$stmt = $this->_dbh->prepare("SELECT d.someField FROM domain d WHERE d.someField LIKE :keyword");
$someField = '%'.$keyword.'%';
Do we need to escape $keyword on this case?
On php manual we can read:
If an application exclusively uses prepared statements, the developer can
be sure that no SQL injection will
occur (however, if other portions of
the query are being built up with
unescaped input, SQL injection is
still possible).
Is this the case on your opinion, are, on this case, build up unescaped input (no prior treatment has been made to our $keyword parameter) ?
Thanks in advance,
MEM
Given the above SQL statement, I see no rational possibility of a SQL injection.
What the warning about "other parts" would be a SQL query like:
$binds = array(":id"=>$_GET['id']);
$myPDO->prepare("SELECT {$_GET['columns']} FROM {$_GET{['table']} WHERE id = :id");
$statement = $myPDO->execute($binds);
The example is a worst case/explicit example of what they mean, that naively someone might think since they're escaping the where argument, that everything is safe.
With your example above, there is no un-escaped input so you're safe.
If an application exclusively uses prepared statements, the developer
can be sure that no SQL injection will occur (however, if other
portions of the query are being built up with unescaped input, SQL
injection is still possible).
I'd figure variables you create shouldn't have to be escaped because you know what they're doing.
Only escape content gotten from the user, such as $_COOKIE, $_POST, $_GET and other parameters such as the URL.

Can you explain this SQL injection?

The website i worked was recently attempted to be hacked by the following SQL injection script
boys' and 3=8 union
select 1,
concat(0x232425,ifnull(`table_name`,0x30),char(9),ifnull(`table_rows`,0x30), char(9),0x252423),
3,4,5,6,7,8,9
from `information_schema`.`tables`
where table_schema=0x62646B3032 limit 44,1 -- And '8'='8
This injection returned the mysql table name. This was reported by the error reporting system on that website and we managed to fix that part however I am not able to understand what does the above injection mean?
Anyone can explain this?
Penuel
They're using a select from the Information Schema views in mysql server :
http://dev.mysql.com/doc/refman/5.0/en/information-schema.html
They use some clever hacks to rout out simple sql injection prevention techniques.
According to this the MySQL concat()
Returns the string that results from
concatenating the arguments. May have
one or more arguments. If all
arguments are nonbinary strings, the
result is a nonbinary string. If the
arguments include any binary strings,
the result is a binary string. A
numeric argument is converted to its
equivalent binary string form
So 0x232425 is converted to #$% which is simply added to the begining and end of the table_name field. Maybe just to make it easier for them to pull out the Table names later using Regex.
Later on the char(9) is equivalent to a tab as you can see here and is just there to format the output nicer.
The 3,4,5,6,7,8,9 is just there so that the columns match the boys table that they are performing the Union on.
This injection returned the mysql table name.
Do you mean that your website displayed the table name when you gave it this input, or that the query returns that when run from the mysql client? If it showed on your website, then the attacker has the ability to inject much more harmful queries. Check your data.

How much sanitizing is needed for Web Services that call Stored Procedures?

I am building a series of web services in VB.Net
Each of the web services takes multiple string values, performs some validation/processing then calls a Stored Procedure using Linq to SQL. Some of the string contains user data that is stored in the database:
These string values passed from the web service are escaped to trap single quote characters, semi colons and the various bracket types.
I am calling the SP using the datacontext.spname(parameter1, parameter2) method.
The aim is to ensure that the web services are as resilient as possible, while still being performant.
Have I done enough to prevent SQL injection attacks?
Usually you are good, but there are a few caveats:
Careful of stored procs that use sp_executesql or exec. You can pass in a query in the param and end up executing it.
Careful with LIKE sections of queries cause they can be widened with % if likened to a param.
Fields used in webpages may need some extra processing before being sent in, to avoid cross site scripting. (which you should also defend against when pulling information out)
I know for a fact that LINQ to SQL queries all the data send to the database via SQL parameters -- which keeps you safe from SQL injection. I'm not entirely sure, but since LINQ abstracts the stored procedure, it too most likely passes the arguments to the stored procedures in the same manner.
What does that mean? You don't have to worry about sanitizing your data because LINQ will take care of it. You could of course test it out with a simple SQL injection type attack -- something like a harmless insert or select.
If you're using parameters then you don't need to sanitise at all as single quotes and the other sql injection nasties get escaped for you.
It's probably a bad idea to sanitise on input depending on the data you're storing. If you're storing things that end up embedded in a web page and you encode/sanitise them on data entry what happens if your sanitation code has a bug? You end up with data in the database that will cause problems on output and no easy way to fix it without an update over all your data. It's better to sanitise when you output data as corrections to the sanitation code will then run against all data. You also have the advantage of easier searching in SQL should that be a concern.
I'd limit the web service to obvious things, null and range checks.