How to prevent 'DROP BOBBY TABLES' when user enters a password with special characters? - sql

In our ancient Classic ASP environment, we utilize OWASP to get the password from the request object and encrypt non-alphanumeric characters. This is a first line of defense to preventing sql injection. We use other methods for full sql injection prevention.
The problem is, when we are collecting data to put together an HTTP post message and just grab the password from the user input, OWASP it and send it along. The password is therefore incorrect.
Example: Password freddie$cougar becomes freddie&36;cougar
What we ended up doing was assuming that a 50 character text field was not enough space to do much sql injection and changed the code so we didn't OWASP the password coming in. This feels a bit scary.
Is their a better way?
The code is written in vbScript.

A better solution is to convert all queries to parameterized ones.
Here is a 12 year old article explaining how :)

Why are you sending the password in clear text? Calculate a hash value for the password and send that one. This would allow you to prevent SQL injection and to avoid man-in-the-middle type attacks.
In any case, you have to also clean up the data as it comes to your server. Even if your vbscripts does client-side validation, it would be trivial to attack your service by bypassing your script and hand-crafting a packet with malicious input in it.

Consider moving your SQL statements to stored procedures, and ensure that you don't use dynamic SQL within those stored procs.
Dim userPwd = Trim(Request.QueryString("userPwd"))
'--- Create and append parameter for Password
Set pwdParameter = cmd.CreateParameter("#UserPassword", ad_nVarChar, adParamInput, 50, userPwd)
cmd.Parameters.Append pwdParameter
Aside, it's definitely best to not even store the pwd in your database, but rather a salted hash.
The method above is preferred, no matter what string you're sending to your database, as it'll avoid executing directly as an adhoc statement, and will avoid SQL injection, as long as you're not using the parameter with dynamic SQL within the stored proc.

A lot of sites limit the set of characters that can be used in passwords - choose a set that is not going to cause you grief. That probably means alphanumerics, and some punctuation (comma, full stop, dash). Having suggested that, those sites annoy me - I use a rich set of characters in my passwords when given the chance to do so, and on the alphanumeric-only sites I usually end up using nonsense like 'IHateNoPunctSites' as the password.
What about shipping the password as a hex-encoded string, or a base-64 encoded string? You can then decode the string at the end, being as careful as necessary to prevent any injection without limiting the character set that is used in the password. When you need to check the password, you can ensure you are doing it cleanly using a parameterized query. Or you can hash the password with its salt before sending the query off to the password file. You should not be doing much with passwords anyway.

Related

Error in SQL query when special characters used in password field

I am using Visual Studio 2008 and Access 2013 as my database.
When I use special characters in a password field, my VB.Net code produces an SQL query error, especially when I am using a special char at the last chat.
For example, if I use jdjdj' as the password then an error occurs.
Normal passwords work. For example:
Admin123
123admin
123
admin
Where is the problem and how can I fix it?
You need to pass the password to the query as a parameter rather than concatenate it into the query string.
It doesn't just stop issues like this, it's also to stop malicious users deliberately taking advantage of your shortcut, to easily gain access to the database.
Check out How do I create a parameterized SQL query? Why Should I?

cgi generic sql injection problems

I was scanning a site when the following vulnerability popped up: CGI Generic SQL Injection
nessus sais that An attacker may exploit this flaw to bypass authentication, read confidential data, modify the remote database, or even take control of the remote operating system.
So i continued reading and found out that the vulnerability sits in this piece of code:
Using the POST HTTP method, Nessus found that :
The following resources may be vulnerable to SQL injection :
The '_codeTextBox' parameter of the /LoginTeacherForm.aspx CGI :
/LoginTeacherForm.aspx [loginButton=Login&_VIEWSTATE=dDwtMTU2NDIxMDkwN
Ts7Pg%3d%3d&btnChangePassword=Wijzig%20Pincode&_pinCodeTextBox=&_codeTex
tBox='+convert(int,convert(varchar,0x7b5d))+']
-------- output --------
Exception Details: System.Data.SqlClient.SqlException: String or
binary data would be truncated.
The statement has been terminated.
But i'm wondering how an attacker can exploit this vulnerability, because when i paste that piece of code it just give me the error.
So my question is how would an attack be able to actually hack into the site and bypass login etc. (Educational purpose only of course)
It looks like a false positive caused by the Nessus request causing your page to insert too long a string into a field. Nessus has detected the error was a SQL server error and has said that it may be a SQL injection vulnerability.
To test yourself try the request with _codeTextBox= set to a single quote to see if you still get a SqlException. If so amend this to two single quotes and if the error then goes away you are probably vulnerable.
The error System.Data.SqlClient.SqlException indicates an error in your SQL query statement. This implies that value stored in the _codeTextBox parameter is not validated or otherwised sanitized before being put into the query.
This would have varying implications depending on the query and logic surrounding its return value. It is impossible to determine the worst case scenario without a thorough understanding of the web application. Suffice it to say, this issue should be fixed by the developer. Fortunately, it is usually easy to fix once identified.
In this case, it looks like the _codeTextBox parameter is being passed to the convert function. I doubt anyone could exploit this. But, this indicates insecure coding practices that probably appear in other areas that Nessus is not aware of. Read below for more info.
I see this most often when the programmer simply concatenates the values with the SQL query string:
Unsafe Example (java) (Source OWASP)
String query = "SELECT account_balance FROM user_data WHERE user_name = "
+ request.getParameter("customerName");
try {
Statement statement = connection.createStatement( … );
ResultSet results = statement.executeQuery( query );
}
Since the value simply gets appended to the end of the query, the user can change query to do something nefarious like login as any user or view all transactions. In the above example, the user could change the customer name parameter to something like '' or 1=1 or worse.
Expected query:
SELECT account_balance FROM user_data WHERE user_name = someuser
Bad query:
SELECT account_balance FROM user_data WHERE user_name = '' OR 1=1
OWASP recommends the following defensive measures. Your situation will dictate what is appropriate:
Primary Defenses:
Use of Prepared Statements (Parameterized Queries)
Use of Stored Procedures
Escaping all User Supplied Input
Additional Defenses:
Also Enforce: Least Privilege
Also Perform: White List Input Validation
You really need to check out OWASP's site and read more about SQL injection.

query string sql injection

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.

Mysql change delimiter for better SQL INJECTION handling?

I am using mysql and trying to block unwanted queries injection of people who will try to use my single query to run several ones. ie, for example when i have the parameter "?id=3", people can try to run it with ="id=3;drop table users"
Now, i know that the best way to avoid this is by parsing and checking the parameter, but is there a way to change the concatenated queries delimiter from ";" to something like "%^#$%##$^$"?
Security through obscurity is useless. Take the time to write the proper code to protect against the SQL injection attacks. Doing it up front will cost you a lot less than doing it after you've had a successful attack run against your code!
The best way to defend against injection attacks is to use Prepared Statements.
By using Prepared Statements, you are immune to most injection attacks (which of course aren't the only security vulnerability you need to think about, but they're a pretty major one.)
The statement DELIMITER configuration is a built-in command only in the mysql client tool. You can't change the delimiter for multi-statements. It's always semicolon.
Also, the MySQL API allows execution of only one statement at a time, by default. The example you're talking about doesn't work unless you explicitly enable multi-statements.
Furthermore, multi-statements isn't the only vector for SQL injection. Even if you could change the statement delimiter, it wouldn't do anything to protect against SQL injection that modifies a single given statement.
UPDATE Accounts SET PASSWORD = '...' WHERE account_id = $id
In this example, if $id has a value of "1234 OR 1=1" then the attacker has changed the password for all accounts, including probably a privileged user. And yet no multi-statements were involved.
You still need to be mindful of security issues when you write code. There's no silver bullet to protect against SQL injection.
Even query parameters aren't a cure-all for SQL injection. Parameters take the place only of values in SQL expressions. There are many common cases where it's still necessary to interpolate application variables into an SQL string. For example, when parameterizing an IN() predicate, or when choosing ORDER BY expressions. Don't listen to people who say prepared queries are 100% proof against security flaws.
See also my presentation SQL Injection Myths and Fallacies, or the chapter on SQL Injection in my book, SQL Antipatterns Volume 1: Avoiding the Pitfalls of Database Programming.
When you call mysql_query or mysql_real_query, it won't run multiple statements anyway, so the statement delimiter doesn't really matter. You can enable multiple statements per query when you connect, but since you're trying to avoid that ability, simply don't enable it.
An even better option for avoid SQL injection is to use prepared statements. Start with mysql_stmt_init and mysql_stmt_prepare with placeholders for your statement's parameters, and then fill in the parameters with mysql_stmt_bind_param before mysql_stmt_execute. If you're not calling the API directly, then whatever wrapper library you have should also provide support for prepared statements. (If it doesn't support them, then consider switching to a better wrapper.)

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.