mysql group_concat自增主键问题

本文介绍了在 MySQL 中如何正确使用 group_concat 函数处理数字类型字段的问题,特别是通过 conv 函数解决八进制转换成十进制的需求。

在进行分组时,有时候需要将某一字段的值以逗号或其它符号拼接在一起,可以使用group_concat函数来完成,如果要拼的字段是字符型的,很好办,用group_concat(字段名 separator ",")就行.
今天在测试程序时,发现有问题,后来发现就是group_concat函数的问题,拼接的字段是主键ID,我设为自动增长,我使用 group_concat(oct(doId) separator ",")发现拼接的主键不对劲,如果不使用oct()函数,对于要拼接的字段是数字型的这种情况,产生的结果就会是一个BLOB数据,因此要使用函数来处 理一下,后来我查了查MYSQL手册,发现oct()函数是返回一个8进制的数,原因找到了就好解决了,于是就再找啊找啊,找到了conv()函数,再转 换成10进制的数字就OK了,返回的结果正如我意,group_concat(conv(oct(doId),8,10) separator ",") 和
group_concat(conv(conv(doId,10,8),8,10) separator ',') 产生的效果是一样的

 

转载

<think>我们正在讨论SQL注入攻击中用于获取数据库表名的查询语句。用户提供的查询语句是: `id=-2 union select group_concat(table_name),2 from information_schema.tables where table_schema='pikachu'` 这个查询的目的是从`information_schema.tables`表中获取数据库名为'pikachu'的所有表名,并将它们合并成一个字符串返回。 ### 理解查询语句 1. **`id=-2`**:这是一个条件,通常用于使原始查询不返回结果(假设id是主键且为正数),这样联合查询的结果就会显示出来。 2. **`union select`**:`UNION`操作符用于合并两个或多个SELECT语句的结果集。这里我们使用`UNION`将原始查询(被`id=-2`否定)和我们的注入查询合并。 3. **`group_concat(table_name)`**:`GROUP_CONCAT`函数将多个行的值连接成一个字符串。这里我们连接所有表名。 4. **`2`**:这是一个占位符,用于匹配原始查询的列数。在联合查询中,两个SELECT语句必须有相同数量的列。这里的2表示第二列(如果原始查询有两列,那么这里需要两个列,所以用2作为第二列的值)。 5. **`from information_schema.tables`**:`information_schema.tables`是系统表,包含了数据库中所有表的信息。 6. **`where table_schema='pikachu'`**:条件限制只查询数据库名为'pikachu'的表。 ### 关于`information_schema` `information_schema`是MySQL等数据库中的一个系统数据库,它提供了访问数据库元数据的方式。其中,`tables`表存储了关于数据库中的表的信息(例如表属于哪个数据库,表名,表类型等)。关键列: - `TABLE_SCHEMA`: 数据库名 - `TABLE_NAME`: 表名 ### 复现步骤 要复现这个SQL注入攻击,你需要: 1. 有一个存在SQL注入漏洞的Web应用程序,比如一个使用GET或POST参数直接拼接SQL查询的页面。 2. 构造一个类似上述的注入字符串,将其插入到原始查询中。 例如,假设原始查询可能是: ```sql SELECT id, title FROM articles WHERE id = {input} ``` 攻击者将输入替换为:`-2 union select group_concat(table_name),2 from information_schema.tables where table_schema='pikachu'`,那么整个查询变为: ```sql SELECT id, title FROM articles WHERE id = -2 union select group_concat(table_name),2 from information_schema.tables where table_schema='pikachu' ``` 这样,原本的查询由于`id=-2`可能没有结果,而联合查询的第二部分就会执行,返回数据库'pikachu'中所有表名的连接字符串。 ### 注意事项 1. **列数匹配**:使用`UNION`必须确保两个SELECT语句的列数相同。在注入中,如果原始查询有n列,那么注入的SELECT也必须返回n列。这里我们使用了`group_concat(table_name)`作为第一列,`2`作为第二列,所以假设原始查询有两列。 2. **占位符**:示例中的`2`是一个占位符,实际中可能需要根据原始查询的列类型和位置进行调整。有时可能需要使用`NULL`或字符串(如`'a'`)作为占位符。 3. **数据库权限**:执行此查询需要数据库用户有权限访问`information_schema`。 4. **防御措施**:SQL注入可以通过参数化查询(预编译语句)来防御。 ### 相关引用 在用户提供的引用中,有多个类似的注入示例: - 引用[2]:`?id=-1 union select 1,group_concat(column_name),3 from information_schema.columns where table_schema='pikachu' and table_name='users'--+`,这是获取列名的注入[^2]。 - 引用[5]:使用`updatexml`函数进行报错注入来获取表名,例如:`' and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='pikachu' limit 0,1),0x7e),1) and '`[^5]。 ### 相关问题 §§相关问题§§ 1. 如何确定原始查询的列数以构造正确的UNION注入? 2. 除了UNION注入,还有哪些方法可以获取数据库的表名? 3. 如何防御SQL注入攻击?</think>### SQL注入获取表名查询语句解析 您提供的SQL注入查询语句用于获取数据库表名: ```sql id=-2 union select group_concat(table_name),2 from information_schema.tables where table_schema='pikachu' ``` #### 语句分解说明: 1. **`id=-2`** - 故意使用不存在的ID值(`-2`),使原始查询返回空结果 - 确保`UNION`后的注入结果能显示在页面中 2. **`union select`** - 联合查询操作,要求前后列数一致 - 此处原始查询假设有2列(需通过探测确认) 3. **`group_concat(table_name)`** - 核心注入函数:将多行表名合并为单字符串 - 替代方案:`concat_ws(',', table_name)`或`limit`分页获取 4. **`from information_schema.tables`** - MySQL系统表,存储所有数据库的元数据 - 关键字段:`table_schema`(数据库名), `table_name`(表名) 5. **`where table_schema='pikachu'`** - 过滤指定数据库(此处目标为`pikachu`库) - 等效写法:`where table_schema=database()`(获取当前库) #### 实际攻击流程示例: 1. **确定列数**(必要前置步骤): ```sql id=1' order by 3--+ /* 通过错误回显判断列数 */ ``` - 若`order by 3`报错,说明原始查询只有2列[^4] 2. **获取表名**(如您提供的语句): ```sql id=-2' union select group_concat(table_name),2 from information_schema.tables where table_schema='pikachu'--+ ``` - 返回结果示例:`users,products,orders,...` 3. **获取列名**(接续操作): ```sql id=-2' union select group_concat(column_name),2 from information_schema.columns where table_schema='pikachu' and table_name='users'--+ ``` - 返回结果示例:`id,username,password,...`[^2] #### 防御建议: 1. 使用参数化查询(预编译语句) 2. 最小化数据库账号权限 3. 过滤特殊字符(如`'`、`--`、`#`) 4. 关闭错误详情回显 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值