设为首页 收藏本站
查看: 277|回复: 0

[经验分享] Preventing SQL Injections in ASP

[复制链接]

尚未签到

发表于 2016-11-10 00:39:02 | 显示全部楼层 |阅读模式
SQL Injection attacks have drawn a lot of attention in the last few months . While there has been a lot of information on best practices to prevent SQL Injection vulnerabilities in ASP.NET and TSQL, there is comparatively very little information on preventing them in ASP code. This paper discusses the common coding mistakes in ASP code that can lead to SQL Injections, the best practices to prevent them and ways to detect these vulnerabilities
1. SQL injection issues in ASP code
When you combine untrusted user input and code, you need to be careful about injection issues. If you embed user supplied data within SQL statements then you can run into SQL Injection issues and similarly if you embed user supplied data with HTML script, then you can run into HTML scripting issues, commonly referred to as XSS, Cross Site Scripting issues.
There are two common kinds of SQL injection issues:


  • First-order SQL Injection and
  • Second-order SQL Injection
If the user-supplied data comes from ASP’s Request.Form or Request.Querystring and that data is used to construct dynamic SQL statements without any data validation, then attackers can inject SQL commands into the SQL statement and misuse it. These are generally referred to as a First Order SQL Injection vulnerability.
If user input is stored in a database via one ASP page and then retrieved from the database and used to construct dynamic SQL statements in a different ASP page, this is referred to as a Second Order SQL Injection vulnerability.
Let’s look at some examples that demonstrate these two kinds of SQL injection vulnerabilities.
First Order SQL injection issues
As I mentioned in the previous section, first-order SQL injection vulnerabilities exist when the user supplied data is directly used in the construction of dynamic SQL statement. Let’s have a look at the following example
ASP
strAuthor = Request.QueryString("authorname")
strConnectString = "Provider=SQLOLEDB; Data Source=sqlmac;Initial Catalog=test; Integrated Security=SSPI;"
Set objConn = Server.CreateObject("ADODB.CONNECTION")
Set objCommand = Server.CreateObject("ADODB.COMMAND")
' Connect to SQL Server
objConn.Open(strConnectString)
' Execute the command
strCmd = "select title, description from books where author_name = '" & strAuthor & "'" Set objCommand.ActiveConnection = objConn
objCommand.CommandText = strCmd
objCommand.CommandType = adCmdText
Set objRS = objCommand.Execute()
' Process the resultset
' Close the objects
  If you observe the code, author name is read from a GET parameter (through Request.QueryString) and is then used directly in the construction of a SQL statement (sqlCmd) without any input validation. If the author name is some valid string such as Michael then the query returns the books authored by Michael. But what if the end user supplies the author name as Michael'; drop table books;--? In this case the final SQL command becomes select title, description from books where author_name='Michael';drop table books;-- ' This not only selects the books authored by Michael but also drops the table named books. The problem here is that the developer simply assumed that the input is going to be a string without any single quotes but never validated the input string for that. In fact this code doesn’t work if the author name is some thing like O'Neil.
The best way to fix this problem is to use parameterized queries. In the previous example, assuming that the maximum length of an author name at the database is 50. You can fix the code as below
ASP
' Execute the command
strCmd = "select title, description from books where author_name = ?"
Set objCommand.ActiveConnection = objConn
objCommand.CommandText = strCmd
objCommand.CommandType = adCmdText
Set param1 = objCommand.CreateParameter ("author", adWChar, adParamInput, 50)
param1.value = strAuthor
objCommand.Parameters.Append param1
Set objRS = objCommand.Execute()
' Process the resultset
' Close the objects

As you can see, author name value is now passed to SQL Server as a parameter. Since the value is not used in the construction of a SQL statement, there is no scope for injection issues.
Let’s look at another example that gets the user input from Request.Form instead of Request.QueryString.
ASP
strUserName = Request.Form("username")
strPassword = Request.Form("password")
strConnectString = "Provider=SQLOLEDB; Data Source=sqlmac;Initial Catalog=test; Integrated Security=SSPI;"
Set objConn = Server.CreateObject("ADODB.CONNECTION")
Set objCommand = Server.CreateObject("ADODB.COMMAND")
' Connect to SQL Server
objConn.Open(strConnectString)
' Execute the command
strCmd = "select user_id, user_name from users where user_name='" + strUserName + "' AND password='" + strPassword + "'"
Set objCommand.ActiveConnection = objConn
objCommand.CommandText = strCmd
objCommand.CommandType = adCmdText
Set objRS = objCommand.Execute()
' Process the resultset
' Close the objects

Just like the previous example, the username and password values received from the end user are used in the construction of a dynamic SQL statement without any input validation. This can easily be exploited by entering username as admin'— and a dummy password and make the final sql statement as select user_id, user_name from users where user_name='admin';--' AND password='dummy'. The only difference is that the values are read from Request.Form. Just like the previous example, this can easily be fixed using parameterized queries as shown here.
ASP
' Execute the command
strCmd = "select user_id, user_name from users where user_name=? AND password=?"
Set objCommand.ActiveConnection = objConn
objCommand.CommandText = strCmd
objCommand.CommandType = adCmdText
Set param1 = objCommand.CreateParameter ("user", adWChar, adParamInput, 20)
param1.value = strUserName
objCommand.Parameters.Append param1
Set param2 = objCommand.CreateParameter ("password", adWChar, adParamInput, 50)
param1.value = strPassword
objCommand.Parameters.Append param2
Set objRS = objCommand.Execute()
' Process the resultset
' Close the objects


Second Order SQL injection issues
Now that we have looked at few first order SQL injection issues, let’s take a look at the following example where the data comes from the database.
ASP
strBookID = Request.QueryString("bookid")
strConnectString = "Provider=SQLOLEDB; Data Source=sqlmac;Initial Catalog=test; Integrated Security=SSPI;"
Set objConn = Server.CreateObject("ADODB.CONNECTION")
Set objCommand = Server.CreateObject("ADODB.COMMAND")
Set objCommand1 = Server.CreateObject("ADODB.COMMAND")
Set rsBook = Server.CreateObject("ADODB.RECORDSET")
Set rsBooks = Server.CreateObject("ADODB.RECORDSET")
' Connect to SQL Server
objConn.Open(strConnectString)
' Execute the command
strCmd = "select title, description, author_name from books where book_id=?"
objCommand.CommandText = strCmd
objCommand.CommandType = adCmdText
Set objCommand.ActiveConnection = objConn
Set param1 = objCommand.CreateParameter ("id", adInteger, adParamInput)
param1.value = strBookID
objCommand.Parameters.Append param1
' Open the recordset, another way of executing SQL statements
rsBook.Open objCommand
' Process the resultset
If rsBooks.EOF = False Then
' Get other books authored by the same person
strAuthorName = rsBook.Fields("author_name")
strCmd = "select * from books where author_name='" + strAuthorName + "'"
' Execute this query and process the results
Set objCommand1.ActiveConnection = objConn
objCommand1.CommandText = strCmd
objCommand1.CommandType = adCmdText
rsBooks.Open objCommand1
' Process the books
rsBooks.MoveNext
End If
' Close the objects
You will notice that in the prior code example I used the Open method of the RecordSet object to execute dynamic SQL. This is another way of executing dynamic SQL in ASP. Let’s look at how the SQL statements are constructed. The first statement, select title, description, author_name from books where book_id=? is a parameterized query as the user input bookid is not used in the construction of the dynamic SQL statement. So there is no SQL injection issue there. But if you look at the second statement, the code uses author_name value which is read from the books table. This can result in a SQL injection issue if an untrusted user controls this data through some other ASP page. If the web site has another page which lets end users to enter book details, then a bad guy can provide some malicious author name like dummy’; <sql statement of his choice>-- and misuse this vulnerability.
The fix is similar to the first two examples. Since this is a simple SELECT statement, you can use parameterized SQL statement to mitigate the second order SQL injection issue.
ASP
If rsBooks.EOF = False Then
' Get other books authored by the same person
strAuthorName = rsBook.Fields("author_name")
strCmd = "select * from books where author_name=?"
' Execute this query and process the results
Set objCommand1.ActiveConnection = objConn
objCommand1.CommandText = strCmd
objCommand1.CommandType = adCmdText
Set authParam = objCommand.CreateParameter ("author", adWChar, adParamInput, 50)
authParam.value = strAuthorName
objCommand1.Parameters.Append authParam
rsBooks.Open objCommand1, objConn
' Process the books
rsBooks.MoveNext
End If
Even if the author_name value is validated before inserting it into the database, you should use parameterized SQL queries as a defense in depth step.
Other SQL Injections
Now that we have seen the most common sql injection issues in ASP, let’s see another example where user supplied data is used in the derivation of a table name.
ASP
strUserName = Request.Form("username")
strPassword = Request.Form("password")
strConnectString = "Provider=SQLOLEDB; Data Source=sqlmac;Initial Catalog=test; Integrated Security=SSPI;"
Set objConn = Server.CreateObject("ADODB.CONNECTION")
Set objCommand = Server.CreateObject("ADODB.COMMAND")
' Connect to SQL Server
objConn.Open(strConnectString)
' Execute the command
strCmd = "select user_id, user_name from users where user_name=? AND password=?"
Set objCommand.ActiveConnection = objConn
objCommand.CommandText = strCmd
objCommand.CommandType = adCmdText
Set param1 = objCommand.CreateParameter ("user", adWChar, adParamInput, 20)
param1.value = strUserName
objCommand.Parameters.Append param1
Set param2 = objCommand.CreateParameter ("password", adWChar, adParamInput, 50)
param1.value = strPassword
objCommand.Parameters.Append param2
Set objRS = objCommand.Execute()
If objRS.EOF = True Then
' Sorry user name doesn't exist with these credentials.
End If
' Get users mails from his table.
strCmd = "select * from " + strUserName + "_emails"
Set objEmails = objConn.Execute strCmd(strCmd)
' Process the emails

A quick look at the above code snippet shows that the web page verifies a user account and then displays emails related to that user. It looks like there is one table for each user that is derived from the user’s name. So the variable in the second SELECT statement is actually the table name. While you write parameterized SQL queries that use varying values as column data, you cannot use parameterized queries for object names, such as table and column names. You can fix potential SQL injection vulnerabilities of this nature by using proper delimiters and escaping characters. For Microsoft SQL Server object identifiers, you must enclose the object names in square brackets and replace all the occurrences of right square brackets with two right square brackets. This is explained in detail at http://msdn.microsoft.com/en-us/magazine/cc163523.aspx.
Here is how you fix it.
ASP
strCmd = "select * from [" + Replace(strUserName, "]", "]]") + "_emails]"
Set objEmails = objConn.Execute strCmd(strCmd)
So if the user name contains any spaces or other special characters they will all be treated as part of a table name and there won’t be any syntax errors or SQL injection opportunities. For example, if the username is some thing like admin_emails; drop table admin_emails; --, then the whole statement will become select * from [admin_emails; drop table admin_emails; --_emails]. SQL Server would treat the expression admin_emails; drop table admin_emails; --_emails as one table name because the whole string is enclosed inside square brackets. One note of caution, there should not be any data transformations done after the escaping. If you escape the string and then do some valid unencoding then that can lead to SQL Injections. So make sure you perform all valid unencoding or validation prior to calling the Replace method.
You may have noticed I used the Execute method of the Connection object in the previous example. This is the third way of executing dynamic SQL in ASP code.
2. Identifying SQL Injection issues in ASP code
As I mentioned in the previous section, there are three methods that let you execute SQL statements in ASP.


  • Using the Execute() method of the ADODB.Command object
  • Using the Open() method of the ADODB.RecordSet object
  • Using the Execute() method of the ADODB.Connection object
Use the following steps to identify SQL injection issues in your source code.


  • Identify all the instances of the above mentioned methods and any wrapper functions for these methods in your source code.
  • For each instance of these function calls, observe the way the SQL statement is constructed. Carefully review to find out if the user supplied data is used in the query construction either directly or indirectly.
3. Mitigating SQL Injection issues in ASP
Follow these guidelines to mitigate SQL injection issues in ASP code


  • Validate user input. Use RegExp.Test() method[3] to reject all invalid input.
  • Use parameterized queries for data manipulation language (DML) statements (SELECT/INSERT/UPDATE/DELETE).
  • For SQL object names, escape right square brackets and delimit them with square brackets.
  • For string literals inside data definition language (DDL) statements, escape single quotes and delimit them in single quotes.
http://msdn.microsoft.com/en-us/library/cc676512.aspx

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-297956-1-1.html 上篇帖子: sql安全登录配置修改方法 下篇帖子: 抽象SQL参数化查询
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表