sql server 拼接换行符 sqlserver语句拼接字符串_sql server 拼接换行符

SQL注入是将Web页面的原URL、表单域或数据包输入的参数,修改拼接成SQL语句,传递给Web服务器,进而传给数据库服务器以执行数据库命令。

比如,网页一般需要根据用户名和密码去查询数据库,如果数据库中含有相应记录,则返回登录成功,否则返回登录失败。在该场景中,web服务器需要根据用户输入的信息动态查询数据库。即用户输入的信息,将直接放到服务器查询数据库的SQL语句中。这意味着后台的操作,会受用户输入影响。如果后端没有对输入信息进行必要的检查,便可能发生数据库信息泄露的问题。

01、SQL注入举例

1. 猜解和篡改后台数据库


举例:某网站可以根据用户输入的id来查询对应的用户名,即对输入的user_id,执行下面的SQL语句: select name from users where id = 'user_id' xxx(其他的一些逻辑) 这便存在注入风险。比如,用户可以填写user_id为 1' order by 1 # ,这样后端的SQL就变为: select name from users where id = '1' order by 1 #xxx (#会将后面的逻辑给注释掉 这样,便会查找id = 1 且根据表中的第一个字段来进行排序 如果返回成功,那说明表中存在第一个字段,同理可以用 order by 2,3,4...依次去试,例如试到4时发现网页报错,说明数据库存储用户信息的表只有3个字段。在此基础上,可以查询到更多的数据库信息。 查询也可以用来返回所有表信息,如输入 1' or 1=1 # select name from users where id = '1' or 1 = 1 #' xxx(其他的一些逻辑) 由于or后面的语句恒为真,因此where语句失效,数据库返回整个表信息 如果通过输入 1' and 1;delete from users # 拼接出如下的SQL语句,那么会删除整个表 select name from users where id = '1' or 1 = 1 ; delete from users #' xxx 2. 欺骗验证 举例:在登录时,一般要求验证用户名和密码,对应后台的验证逻辑是: select * from users where name = 'name1' and passward = 'ps1' 正常情况下,当查询数据表得到满足条件的记录时,会返回登录成功 很显然,我们可以修改输入的用户名和密码,如用户名框输入 a' or 1=1# ,密码框输入 xx ,则后台拼接成的SQL语句为: select * from users where name = 'a' or 1 = 1 #' and passward = 'xx' 由于#号的注释,上面语句等效为: select * from users where name = 'a' or 1 = 1 该语句恒为真,直接就绕过了登录验证

02、判断SQL注入点和注入类型

一般比较明显的SQL注入漏洞的URL有:http://xxx.xxx.xxx/abcd.php?id=1,这种从字面就能读出来后端是根据输入id的值来做判断。一般而言,所有有用户输入的动态页面+有查询数据库的操作,都有注入风险。

常见的测试方法是单引号测试法,如输入id的值为 1',那么对应的SQL语句为
// id类型为数字
select * from users where id = 1'  
// id类型为字符串
select * from users where id = '1''

如果网页报错,说明存在注入风险,因为无论后端采用的是数字类型还是字符串类型,都会因为单引号不匹配而报错

判断注入类型,例如页面输入的信息可能被当作数字型,也可能字符串类型,那么可以用and条件来测试:

第一次输入id:1 and 1=1
第二次输入id:1 and 1=2
如果后端采取的是数字型,则SQL语句为:
select * from users where id = 1 and 1=1 
select * from users where id = 1 and 1=2 
第一次成功,第二次失败
如果后端采取的是数字型,则SQL语句为:
select * from users where id = '1 and 1=1'
select * from users where id = '1 and 1=2'

第一次和第二次都会返回失败

类似的,也可以用该原理来测试是否为字符串类型的注入

03、SQL注入的预防

从上面的例子可以看到预防SQL注入的必要性,一般的防范措施如下:

1. 过滤和强校验

对输入的参数进行强限制,如数字类型的必须全为数字,字符串类型的必须符合规定的正则表达式。去掉字符串中容易造成注入的分号和单引号(Trim)

2. 使用存储过程

使用更安全的数据库操作接口,而非直接执行一条拼接的SQL语句

存储过程(Stored Procedure)是在大型数据库系统中,一组为了完成特定功能的SQL 语句集,它存储在数据库中,一次编译后永久有效,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。存储过程是数据库中的一个重要对象。在数据量特别庞大的情况下利用存储过程能达到倍速的效率提升

3. 对用户密码进行强加密

即使用户密码被泄露,黑客拿到的也是加密后的密码,无法反解出原密码