##SQL注入简介:
所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。具体来说,它是利用现有应用程序,将(恶意)的SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句。
## SQL注入方法:
### 一、拼接字符串(通过输入框输入SQL语句使其改变原意)
`Select * from T_User where UserID =’txtUserID.Text’andPassword=’ txtPassword.Text ’ `
其原理是通过查找T_User 表中的用户名(UserID) 和密码(Password) 的结果来进行授权访问, 在txtUserID.Text为mysql,txtPassword.Text为mary,那么SQL查询语句就为:
Select * from users where username =’ mysql ’ and password =’ mary ’
如果分别给txtUserID.Text 和txtPassword.Text赋值’ or ‘1’ = ‘1’ --和abc。那么,SQL 脚本解释器中的上述语句就会变为:
Select * from T_User where UserID =’’or ‘1’ = ‘1’ -- and Password =’abc’
该语句中进行了两个条件判断,只要一个条件成立,就会执行成功。而'1'='1'在逻辑判断上是恒成立的,后面的"--" 表示注释,即后面所有的语句为注释语句这样我们就成功登录。即SQL注入成功.
原来SQL语句:`insert into category(name) values(‘”+caName+”’) `
输入框中输入`:caName=娱乐新闻’)select category --‘) `
SQL语句变成:`insert into category(name) values(‘娱乐新闻’)Select category --‘) `
SQL语句改变后,将执行插入和查询两个操作(如果修改的不是查询而是删除将会更加可怕),即SQL注入成功。
###二、查看错误页信息(SQL Server有一些系统变量,如果我们没有限制错误信息的输出,那么注入着可以直接从出错信息获取)
Web中的网址:http://www.xxx.com/Login.aspx?id=49 and user>0首先,前面的语句是正常的,重点在and user>0,我们知道,user是SQL Server的一个内置变量,它的值是当前连接的用户名 ,类型为nvarchar。拿一个nvarchar的值跟int的数0比较,系统会先试图将nvarchar的值转成int型,当然,转的过程中肯定会出错,SQL Server的出错提示是:将nvarchar值 ”abc” 转换数据类型 为 int 的列时发生语法错误,abc正是变量user的值,这样,注入着就拿到了数据库的用户名,即SQL注入成功。
## SQL注入防范:
### 一、简单防范:
1.输入框中限制特殊字符以及长度
2.Web中设置错误提示页即:
在Web.Config文件中设置
~~~
<!--出现错误的时候自动导向("~/error.html"是弹出页面的路径)-->
<customErrors mode="On" defaultRedirect ="~/error.html" ></customErrors>
~~~
3.URL重写:
URL重写就是首先获得一个进入的URL请求然后把它重新写成网站可以处理的另一个URL的过程。举个例子来说,如果通过浏览器进来的URL是“UserProfile.aspx?ID=1”那么它可以被重写成“UserProfile/1.aspx”
### 二、SQL语句中的防范
1.参数化查询:参数化查询(Parameterized Query 或 Parameterized Statement)是指在设计与数据库链接并访问数据时,在需要填入数值或数据的地方,使用参数 (Parameter) 来给值。
例如:
不使用参数化查询:
`string sql = "select * from comment where newsId = "txtnewsId" order by createTime desc"; `
因为上面SQL语句中的"txtnewsId"是不确定的,每次调用的时候需要将SQL语句重新编译,这就能用上面的拼接字符串实现SQL注入。
使用参数化查询:
~~~
string sql = "select * from comment where newsId = @newsId order by createTime desc";
SqlParameter[] paras = new SqlParameter[]{new SqlParameter ("@newsId",newsId)};
~~~
因为上面SQL语句是固定的,调用的时候只需要将@newsId的值传上去就可以,所以即便用户输入任何信息也会当成一个值传递进去,防止SQL注入。
2.通过写存储过程:
其实在存储过程里面也需要用到参数化查询并且存储过程本身没有SQL注入这两点同时满足才能防止SQL注入。
3.限制数据库的访问权限:
设立不同用户的特殊权限,例如:用户名为1的用户只允许查询操作,然而用户1的信息被盗取登陆之后就不能对表进行别的操作,这样就一定程度上保证了数据的安全性。