MySQL之SQL-Column-Truncation(长字符截断)

#1.介绍 mysql超长字符截断又名为“SQL-Column-Truncation”。 在mysql中的一个设置里有一个`sql_mode`选项,当`sql_mode`设置为default 时,即没有开启`STRICT_ALL_TABLES`选项或者`TRADITIO...

1.介绍

mysql超长字符截断又名为“SQL-Column-Truncation”。

在mysql中的一个设置里有一个sql_mode选项,当sql_mode设置为default 时,即没有开启STRICT_ALL_TABLES选项或者TRADITIONAL 选项或者加上的是ANSI选项时(MySQL sql_mode默认即default),MySQL对插入超长的值只会提示 warning,而不是error,这样就可能会导致一些截断问题。

比如:
第一种:没有开启STRICT_ALL_TABLES选项或者TRADITIONAL 选项

第二种:加上的是ANSI选项

在这里,usernamevarchar(5),即最大规定长度为5,而输入的值为admsddsff,长度为9,超过规定长度,可是并没有报错。通过查询可知被截断了。那么我们可以利用这个漏洞。
第一种和第二种都是如图这样的结果:

2.sql-mode的各项设置

MySQL5.0以上版本支持三种sql_mode模式:ANSITRADITIONALSTRICT_TRANS_TABLES

1、ANSI模式:
宽松模式,更改语法和行为,使其更符合标准SQL。对插入数据进行校验,如果不符合定义类型或长度,对数据类型调整或截断保存,报warning警告。对于本文开头中提到的错误,可以先把sql_mode设置为ANSI模式,这样便可以插入数据,而对于除数为0的结果的字段值,数据库将会用NULL值代替。

2、TRADITIONAL模式:
严格模式,当向mysql数据库插入数据时,进行数据的严格校验,保证错误数据不能插入,报error错误,而不仅仅是警告。用于事物时,会进行事物的回滚。 注释:一旦发现错误立即放弃INSERT/UPDATE。如果你使用非事务存储引擎,这种方式不是你想要的,因为出现错误前进行的数据更改不会“滚动”,结果是更新“只进行了一部分”。

3、STRICT_TRANS_TABLES模式:
严格模式,进行数据的严格校验,错误数据不能插入,报error错误。如果不能将给定的值插入到事务表中,则放弃该语句。对于非事务表,如果值出现在单行语句或多行语句的第1行,则放弃该语句。

STRICT_TRANS_TABLES:
在该模式下,如果一个值不能插入到一个事务表中,则中断当前的操作,对非事务表不做限制。必须设置,以后各项可能依赖于该项的设置

NO_ENGINE_SUBSTITUTION:
如果需要的存储引擎被禁用或未编译,那么抛出错误。不设置此值时,用默认的存储引擎替代,并抛出一个异常

ONLY_FULL_GROUP_BY:
对于GROUP BY操作,如果在SELECT中出现的单独的列,没有在GROUP BY子句中出现,那么这个SQL是不合法的

NO_AUTO_VALUE_ON_ZERO:
该值影响自增长列的插入。默认设置下,插入0或NULL代表生成下一个自增长值。如果用户希望插入的值为0,而该列又是自增长的,那么这个选项就有用了

NO_ZERO_IN_DATE:
在严格模式下,不允许日期和月份为零

NO_ZERO_DATE:
设置该值,mysql数据库不允许插入零日期,插入零日期会抛出错误而不是警告

ERROR_FOR_DIVISION_BY_ZERO:
在INSERT或UPDATE过程中,如果数据被零除,则产生错误而非警告。如果未给出该模式,那么数据被零除时MySQL返回NULL

NO_AUTO_CREATE_USER:
禁止GRANT语句创建密码为空的用户

PIPES_AS_CONCAT:
将“||”视为字符串的连接操作符而非或运算符,这和Oracle数据库是一样的,也和字符串的拼接函数Concat相类似

ANSI_QUOTES:
启用ANSI_QUOTES后,不能用双引号来引用字符串,因为它被解释为识别符
也可以在命令行查看和设置sql_mode变量

3.测试

新建一张表测试,表结构如下(mysql 5.1):

CREATE TABLE USERS(
                    id int(11) NOT NULL,
                    username varchar(7) NOT NULL,  //长度为7
                    password varchar(12) NOT NULL
)

分别插入以下SQL语句(注入提示消息)。

1.插入正常的SQL语句。

mysql> insert into users(id,username,password) values(1,'admin','admin');
Query OK,1 row affected (0.00 sec)  //成功插入,无警告,无错误

2.插入错误的SQL语句,此时的“admin ”右面有三个空格,长度为8,已经超过了原有的规定长度。

mysql> insert into users(id,username,password) values(2,'admin   ' ,'admin');
Query oK,1 row affected,1 warning (0.00 sec)    //成功插入,一个警告

3.插入错误的SQL语句,长度已经超过原有的规定长度。

mysql> insert into users(id,username,password) values(3 ,'admin   x','admin');
Query OK,1 row affected,1 warning (0.00 sec)    //成功插入,一个警告

MySQL提示三条语句都已经插入到数据库,只不过后面两条语句产生了警告。那么最终有没有插入到数据库呢?执行SQL语句查看一下就知道了。

mysql> select username from users;
+----------+
| username |
+----------+
|admin    |
|admin    |
|admin    |
+----------+
3 rows in set (0.00 sec)

可以看到,三条数据都被插入到数据库,但值发生了变化,此时再通过length来取得长度,判断值的长度。

mysql> select length(username) from users where id =1;
+------------------+
| length(username) |
+------------------+
|              5|
+------------------+
1 row in set (0.00 sec)

mysql> select length(username) from users where id =2;
+------------------+
| length(username) |
+------------------+
|              7|
+------------------+
1 row in set (0.00 sec)

mysql> select length(username) from users where id =3;
+------------------+
| length(username) |
+------------------+
|              7|
+------------------+

可以发现,第二条与第三条数据的长度为7,也就是列的规定长度,由此可知,在默认情况下,如果数据超出列默认长度,mysql会将其截断。

但这样何来攻击一说呢?下面查询用户名为'admin'的用户就知道了。

mysql> select username from users where username= 'admin';
+----------+
| username |
+----------+
|admin    |
|admin    |
|admin    |
+----------+

只查询用户名为admin 的用户,但是另外两个长度不一致的admin用户也被查询出,这样就会造成一些安全问题,比如,有一处管理员登录是这样判断的,语句如下:

$sql = "select count(*) from users where username='admin' and password='*****'";

假设这条SQL语句没有任何注入漏洞,攻击者也可能登录到管理页面。

假设管理员登录的用户名为admin,那么攻击者仅需要注册一个“admin “用户即可轻易进入后台管理页面,像某些著名的建站系统就被这样的方式攻击过。

4、预防方法

在sql-mode里加上STRICT_TRANS_TABLES或者TRADITIONAL
加上STRICT_TRANS_TABLES或者TRADITIONAL后,输入的数据超过规定长度就会报错,不能输入。

第一种:加上TRADITIONAL

第二种:加上STRICT_TRANS_TABLES

两种都是如下的结果:

  • 发表于 2021-06-24 21:18:51
  • 阅读 ( 6851 )
  • 分类:漏洞分析

0 条评论

请先 登录 后评论
Johnson666
Johnson666

19 篇文章

站长统计