Classic ASP SQL Injection - asp-classic

I recently inherited a classic asp website with a ton of inline SQL insert statements that are vulnerable to SQL injection attacks.
These insert statements are executed via the ADO command object.
Will setting the ADO Command Object's Prepared property to true ensure that the query is parameterized before execution, thus mitigating the risk of SQL injection?

This Link should prove useful.
Classic ASP SQL Injection Protection

No, if you build a SQL string with values that you get directly from "outside", then a "prepared statement" will not help you.
a
sSQL = "SELECT * from mytable where mycolumn = '" + querystring("value") + "'"
is still asking for trouble.
The only way to solve this is by using parameters in your query.

You can also look at an asp classic open source project called 'Owasp stinger'. That not only helps with Sql injection, but header injection and lots of other security issues common to all web apps.
http://www.owasp.org/index.php/Classic_ASP_Security_Project

Here's another good link and example.
http://blogs.iis.net/nazim/archive/2008/04/28/filtering-sql-injection-from-classic-asp.aspx
In the past we just created a couple functions to handle any outside input for SQL injections and XSS. Then slowly we converted all the inline SQL to stored procedures.

What I would suggest you do is write a function to sanitize the user input, then run all the request variables through that. When I wrote mine I did stuff like:
escape single quotes,
remove ; and other special characters and
make sure that you couldn't -- (comment) out the end of the statement.
Most SQL injection would try something like ' or 1=1 or a='
so the SQL code would be :
SELECT * from mytable where mycolumn = '' or 1=1 or a=''
So escaping single quotes is the real big one you need to worry about.

Related

Prepared Statements and sanitizing data

When using a prepared statement with Classic ASP such as this:
SQL = "SELECT user_name, user_sign_up_date FROM tbl_users WHERE this = ? AND id = ? "
Set stmt01 = Server.CreateObject("ADODB.Command")
stmt01.ActiveConnection = oConn
stmt01.Prepared = true
stmt01.commandtext = SQL
stmt01.Parameters.Append stmt01.CreateParameter("#x1", adVarChar, adParamInput, 255, card_pwd)
stmt01.Parameters.Append stmt01.CreateParameter("#x2", adInteger, adParamInput, , this_id)
set myRS = stmt01.Execute
Apart from doing the usual sense checking to e.g. make sure that a number is a number and so on, does the process of using this kind of Parameterised Statement mean that I no longer have to worry about, e.g. for a varchar or text field, sanitising the data input from users - e.g. would I no longer need to use a function to push everything input by a user through Server.HTMLencode?
I'm not sure if the parameterised statement route means I can be less strict re. sanitizing user data now?
You are conflating two different types of sanitisation. SQL parameterization prevents the “Bobby Tables” vulnerability — a maliciously written bit of data that tricks SQL into ending the current query and executing a separate query of the attacker’s choosing.
https://bobby-tables.com
Even with SQL parameters, an attacker could try to run a script on your page by (for example) entering “alert(‘Gotcha!’)” in a field. Display the field data on an HTML page and that script is written out and executed. To prevent that you use Server.HTMLencode
If your concern is SQL injection attacks then parameterization should remove the possibility of the SQL string being tampered with because the values are supplied at execution time.
Others are correct that you don't need to worry about the contents of the parameters. You do have to worry about the length of strings. I would pass Left(card_pwd, 255) to CreateParameter() to avoid exceptions crashing your script. I tend to not worry about calling IsNumeric() on integer parameters but that might be worthwhile (try passing nonsense and see what happens).

Server.HtmlEncode is causing error to ODP.NET

I am migrating a Framework v3.5 version to v4.5 and updating the System.Data.OracleClient with ODP.NET from Oracle.
In one part of the app, it is getting some value from QueryString, doing a Server.HtmlEncode and pushing into an oracle select statement where clause and running the statement through ODP.NET.
Now the problem is, it was working previously with the System.Data.OracleClient, but getting invalid identifier from Oracle with ODP.NET. Runs fine if I remove the Server.HtmlEncode but I am not allowed to expose the raw data to Oracle for security.
Need help!
Imports Oracle.DataAccess.Client
strStateIDs = Trim(Server.HtmlEncode(Context.Request.QueryString("STATE_IDS")))
strLVQuery = "SELECT <some columns> WHERE <some condition> AND <some column> IN (" & strInitStateIDs & ") ORDER BY <some columns>"
OracleDA.SelectCommand.CommandType = CommandType.Text
OracleDA.Fill(dataTable)
Sample Data in strStateIDs:
Without Server.HtmlEncode:
'ABC','XYZ','BLAH_BLAH'
After Server.HtmlEncode:
'ABC','XYZ','BLAH_BLAH'
SOLUTION:
Posting it as it might help someone later.. As Antonio Bakula pointed out, HtmlEncode encodes single quotes since ASP.NET 4.0
So, I did strStateIDs = strStateIDs.Replace("'", "'") after HtmlEncode to work around this issue.
I really don't see any need for HtmlEncode for string that will be used in SQL select. So my advice would be remove HtmlEncode.
Reason why this is not working anymore is documented here:
http://www.asp.net/whitepapers/aspnet4/breaking-changes#0.1__Toc256770143
btw. your code is open to SQL injection, please use parameters, details here:
https://msdn.microsoft.com/en-us/library/ff648339.aspx
Once you HtmlEncode the content it becomes
"'ABC','XYZ','BLAH_BLAH'"
As you can see there are semi colons in your query as it will look like this now.
"SELECT <some columns> WHERE <some condition> AND <some column> IN ("'ABC','XYZ','BLAH_BLAH'") ORDER BY <some columns>"
That makes the db assume you are terminating your statements and starting new ones.
I assume there is a reason you are not using SqlParameters or their Oracle equivalent. Assuming you want to push on with this string based options, I would do this in C#.
strLVQuery = string.Format(#"SELECT <some columns> WHERE <some condition> AND <some column> IN ('{0}') ORDER BY <some columns>",strStateIDs);
Maybe that will help you come up with a VB solution.

Need a quick and simple classic asp page to query records from a sql server database

I know this seems elementary, but I have been looking for 2 days and all i find is snippets that dont work. I am simply trying to have a web page dynamically display the contents of a table with 4 columns.
Need by tomorrow!
Help!
Thank you!
Here's the simplest way to do it. This is assuming your server is SQL Server. If not, head to http://connectionstrings.com and look up the specifics for your server. That site is awesome and I find myself on it all the time.
set rs = server.CreateObject("ADODB.Recordset")
rs.open "select col1 from table1", "provider=sqloledb.1;uid=user;pwd=password;database=database;Server=server;"
do while rs.EOF = false
response.write rs("col1")
rs.MoveNext
loop
What's going on here is we're using Microsoft's ADO database library. I'm creating a Recordset object and calling its open method. Provided to the open method are the sql statement I want to execute and the specifics on how to connect to that database. The specifics on how to connect to the database is commonly referred to as a "Connection String." The site mentioned above is an invaluable resource in figuring out exactly what this should look like. 99% of the time, any problems I've run into have been an invalid connection string. Once opened, I loop through the returned records in the while loop and write out the data to the page.
DON'T FORGET THE CALL TO rs.MoveNext!!! I've done this a handful of times over the years and you'll wind up with an infinite loop.

classic ASP protection against SQL injection

I've inherited a large amount of Classic ASP code that is currently missing SQL injection protection, and I'm working on it. I've examined in detail the solutions offered here: Classic ASP SQL Injection Protection
On the database side, I have a Microsoft SQL server 2000 SP4
Unfortunately stored procedures are not an option.
After studying php's mysql_real_escape_string ( http://www.w3schools.com/php/func_mysql_real_escape_string.asp ) , I've replicated its functionality in ASP.
My question(s) are:
1) Does Microsoft SQL server 2000 have any other special characters that need to be escaped that are not present in MySQL ( \x00 , \n , \r , \ , ' , " , \x1a )
2) From an answer in Can I protect against SQL Injection by escaping single-quote and surrounding user input with single-quotes? I read "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."
How can this be used for an attack (I really can't imagine such a scenario) and what would be the right way of protecting against it?
3) Are there any other issues I should be aware of? Any other way of injecting SQL?
Note: A 30-min internet search said that there are no libraries for classic ASP to protect against SQL injection. Is this so, or did I really fail at a basic task of searching?
The best option is to use parameterized queries. On how that is done, you must check out:
SQL Injection Mitigation: Using Parameterized Queries
In PHP also, the PDO (and prepared statements) allows developers to use parameterized queries to avoid sql injection.
Update
Yes you can specify parameters in WHERE clause and for that you can use ADODB.Command object like below example:
' other connection code
set objCommand = Server.CreateObject("ADODB.Command")
...
strSql = "SELECT name, info FROM [companies] WHERE name = ?" _
& "AND info = ?;"
...
objCommand.Parameters(0).value = strName
objCommand.Parameters(1).value = strInfo
...
For more information, see the article link that I have posted above or you may want to research a little more on the topic if you want.
I use two layers of defense:
create a 'cleanparameter' function, and every call that gets from querystring or form values, use it calling that function. The function at the very least should replace simple quotes, and also truncate the string to a value you pass. So, for example, if the field can't be longer than 100 chars, you would call it like x = cleanparameter(request.querystring("x"), 100). That's the first line of defense
Use parameterized queries to run SQL instructions

Looking for a SQL injection demonstration

I'm a web applications developer, using Classic ASP as server side script.
I always protect my apps from SQL injection by using a simple function to double single apostrophe for string parameters.
Function ForSQL(strString)
ForSQL = Replace(strString, "'", "''")
End Function
For numeric parameters, I use the CInt, CLng and CDbl functions.
I often write concatenated query; I don't always use stored procedure and I don't always validate user inputs.
I'd like to ask you if someone can show me a working attack against this line of code:
strSQL = "SELECT Id FROM tUsers WHERE Username='" & _
ForSQL(Left(Request.Form("Username"),20)) & "' AND Password='" & _
ForSQL(Left(Request.Form("Username"),20)) & "'"
It could be a banality but I've never found a kind of attack that works.
I've always found "sqli helper 2.7" (you can download it) to find most/all SQL injections. I'm not sure if this will help at all, but it will at least help test for all of the SQL comments and everything. I remember on one of my sites it found a main SQL injection to dumb all of my database data. It's not exactly what you're looking for, but it might be able to find a way through.
There is no functioning SQL injection for input sanitized this way. The downside is retrieving data from the database is you have to replace on double apostrophes.
sDataRetrievedFromDatabase = Replace(sDataRetrievedFromDatabase, "''", "'")

Resources