1、浅析浅析浅析浅析SqlSql注入注入注入注入(SqlSql Injection Injection)什么是什么是Sql注入注入 随着随着B/S模式应用开发的发展,使用这模式应用开发的发展,使用这种模式编写应用程序的程序员也越来越多。种模式编写应用程序的程序员也越来越多。但是由于这个行业的入门门槛不高,程序员但是由于这个行业的入门门槛不高,程序员的水平及经验也参差不齐,相当大一部分程的水平及经验也参差不齐,相当大一部分程序员在编写代码的时候,序员在编写代码的时候,没有对用户输入数没有对用户输入数据的合法性进行判断据的合法性进行判断,使应用程序存在安全,使应用程序存在安全隐患。隐患。用户可以提交一
2、段数据库查询代码,根用户可以提交一段数据库查询代码,根据程序返回的结果,获得某些他想得知的数据程序返回的结果,获得某些他想得知的数据,这就是所谓的据,这就是所谓的SQL Injection,即,即SQL注注入。入。2SQL注入是从正常的注入是从正常的WWW端口访问,而且表面看起来跟一般的端口访问,而且表面看起来跟一般的Web页面访问没什么区别,所以目前市面的防火墙都不会对页面访问没什么区别,所以目前市面的防火墙都不会对SQL注入发出警报,如果管理员没查看注入发出警报,如果管理员没查看IIS(Web服务器)日志的习惯,服务器)日志的习惯,可能被入侵很长时间都不会发觉。可能被入侵很长时间都不会发觉
3、但是,但是,SQL注入的手法相当灵活,在注入的时候会碰到很多意外注入的手法相当灵活,在注入的时候会碰到很多意外的情况。能不能根据具体情况进行分析,构造巧妙的的情况。能不能根据具体情况进行分析,构造巧妙的SQL语句,语句,从而成功获取想要的数据,是高手与从而成功获取想要的数据,是高手与“菜鸟菜鸟”的根本区别。的根本区别。为什么会用为什么会用Sql注入注入31.没有使用没有使用PreparedStatement对象的对象的setString()等方法进行传参,等方法进行传参,而是使用的而是使用的“拼串拼串”方式。方式。例如:例如:Sql注入是怎样产生的注入是怎样产生的(Java Web)publ
4、ic public foodBeanfoodBean getFoodById(StringgetFoodById(String id)id)con=con=this.getConthis.getCon();();String String sqlsql=select*from=select*from foodinfofoodinfo where where foodIdfoodId=+id+;=+id+;System.out.println(sqlSystem.out.println(sql););stmt=stmt=con.prepareStatement(sqlcon.prepareSta
5、tement(sql););rsrs=stmt.executeQuerystmt.executeQuery();();2.导致非法参数传入,构造成非法的导致非法参数传入,构造成非法的sql语句!语句!例如在此处给例如在此处给id传入值为传入值为“20;(任意任意sql语句语句);-”,构造成构造成 select*from select*from foodinfofoodinfo where where foodIdfoodId=20 20 ;(;(任意任意sqlsql语语句句);-);-4怎样进行怎样进行Sql注入注入(Java Web)如何测试是否存在如何测试是否存在Sql注入(一)注入(一
6、示例:示例:如如 http:/localhost:8080/restrantNew/details.jsp?foodID=021.在此在此URL尾处加上单引符号尾处加上单引符号“”2.最终执行的最终执行的sql语句则是语句则是 select*from select*from foodinfofoodinfo where where foodIdfoodId=2020 3.3.页面出现错误,因为语句中出现未闭合的单引号。页面出现错误,因为语句中出现未闭合的单引号。结论:结论:加单引号加单引号和和不加此单引号不加此单引号返回显示的页面不相同,可判断为返回显示的页面不相同,可判断为此处存在此处存在
7、SqlSql注入漏洞!注入漏洞!5怎样进行怎样进行Sql注入注入(Java Web)如何测试是否存在如何测试是否存在Sql注入(二)注入(二)有些程序中简单的过滤掉了单引号,如果你用单引号测试,是测不到注入点的有些程序中简单的过滤掉了单引号,如果你用单引号测试,是测不到注入点的 那么,什么样的测试方法才是比较准确呢?答案如下:那么,什么样的测试方法才是比较准确呢?答案如下:http:/localhost:8080/restrantNew/details.jsp?foodID=02http:/localhost:8080/restrantNew/details.jsp?foodID=02 and
8、 1=1 and 1=1 http:/localhost:8080/restrantNew/details.jsp?foodID=02http:/localhost:8080/restrantNew/details.jsp?foodID=02 and 1=2 and 1=2 这就是经典的这就是经典的1=1、1=2测试法了,怎么判断呢?测试法了,怎么判断呢?返回正常页面,返回正常页面,出现错误,则出现错误,则此处存在此处存在SqlSql注入漏洞!注入漏洞!6怎样进行怎样进行Sql注入注入(Java Web)SQL注入的一般步骤注入的一般步骤(一)(一)1.判断环境,寻找注入点,判断数据库类型判断
9、环境,寻找注入点,判断数据库类型 2.根据注入参数类型,在脑海中重构根据注入参数类型,在脑海中重构SQL语句的原貌,按参数类型主要分为语句的原貌,按参数类型主要分为下面三种下面三种 ID=20 这类注入的参数是数字型,这类注入的参数是数字型,SQL语句原貌大致如下:语句原貌大致如下:Select*from 表名 where 字段=49 注入的参数为ID=49 And 查询条件,即是生成语句:Select*from 表名 where 字段=49 And 查询条件 type=Student 这类注入的参数是字符型,这类注入的参数是字符型,SQL语句原貌大致概如下:语句原貌大致概如下:Select*
10、from 表名 where 字段=Student 注入的参数为type=Student and 查询条件-,即是生成语句:Select*from 表名 where 字段Student and 查询条件 搜索时没过滤参数的,如搜索时没过滤参数的,如keyword=关键字,关键字,SQL语句原貌大致如下:语句原貌大致如下:Select*from 表名 where 字段 like%关键字%注入参数省略7怎样进行怎样进行Sql注入注入(Java Web)SQL注入的一般步骤注入的一般步骤(二)(二)3.将查询条件替换成将查询条件替换成SQL语句,猜解表名、字段名语句,猜解表名、字段名猜测是否存在此表、
11、和字段猜测是否存在此表、和字段 1.And(Select Count(*)from 表名)=0 2.表名猜出来后,将Count(*)替换成Count(字段名),用同样的原理猜解字段名。如果存在,返回正常页面。如果不存在,返回错误页面。有人会说:这里有一些偶然的成分,如果表名起得很复杂没规律的,那根本就没得玩下去了。说得很对,这世界根本就不存在100%成功的。黑客技术,苍蝇不叮无缝的蛋,无论多技术多高深的黑客,都是因为别人的程序写得不严密或使用者保密意识不够,才有得下手。8怎样进行怎样进行Sql注入注入(Java Web)SQL注入的一般步骤注入的一般步骤(三)(三)4.猜测字段内内容猜测字段内
12、内容 1.得到字符内容长度得到字符内容长度举个例子:已知表Admin中存在username字段,首先,我们取第一条记录,测试长度?id=49;and(select top 1 len(username)from Admin)0-原理:如果top 1的username长度大于0,则条件成立,返回正常页面;接着就是1、2、3这样测试下去,一直到条件不成立为止。比如7成立,8不成立,就是len(username)=8 9怎样进行怎样进行Sql注入注入(Java Web)SQL注入的一般步骤注入的一般步骤(四)(四)5.猜测字段内内容猜测字段内内容 2.得到字符内容得到字符内容在得到username的
13、长度后,用unicode(substring(username,N,1)截取第N位字符再unicode(substring(username,N,1)得到ASCII码,比如:and(select top 1 unicode(substring(username,1,1)from Admin)0 同样也是用逐步缩小范围的方法得到第1位字符的ASCII码,注意的是英文和数字的ASCII码在1-128之间,可以用折半法加速猜解,如果写成程序测试,效率会有极大的提高。常用函数补充 Access:asc(字符)SQLServer:unicode(字符)作用:返回某字符的ASCII码 Access:chr
14、数字)SQLServer:nchar(数字)作用:与asc相反,根据ASCII码返回字符 10怎样进行怎样进行Sql注入注入(Java Web)利用存储过程、内置变量利用存储过程、内置变量 更方便更方便SA用户权限,调用系统存储过程用户权限,调用系统存储过程 执行命令执行命令exec master.xp_cmdshell net user name password/add 数据库名数据库名db_name()表名表名Select Top 1 name from sysobjects where xtype=U and status0字段名字段名Select Top 1 col_name(ob
15、ject_id(foodInfo),1)from sysobjects 11经验小结经验小结 1.有些人会过滤有些人会过滤Select、Update、Delete这些关键字,但偏偏忘记区这些关键字,但偏偏忘记区分大小写,所以大家可以用分大小写,所以大家可以用selecT这样尝试一下。这样尝试一下。2.在猜不到字段名时,不妨看看网站上的登录表单,一般为了方便起在猜不到字段名时,不妨看看网站上的登录表单,一般为了方便起见,字段名都与表单的输入框取相同的名字。见,字段名都与表单的输入框取相同的名字。3.特别注意:地址栏的特别注意:地址栏的+号传入程序后解释为空格,号传入程序后解释为空格,%2B解释为
16、解释为+号,号,%25解释为解释为%号,具体可以参考号,具体可以参考URLEncode的相关介绍。的相关介绍。12附录附录附件一:附件一:URLUnicode表表(节选节选,主要是非字母的字符,主要是非字母的字符,RFC1738)字符特殊字符的含义字符特殊字符的含义URL编码编码#用来标志特定的文档位置用来标志特定的文档位置%23%对特殊字符进行编码对特殊字符进行编码%25&分隔不同的变量值对分隔不同的变量值对%26 +在变量值中表示空格在变量值中表示空格%2B /表示目录路径表示目录路径%2F%5C =用来连接键和值用来连接键和值%3D?表示查询字符串的开始表示查询字符串的开始%3F 空格空格%20.句号句号%2E:冒号冒号%3A 13Thank you14