• SQL注入简单总结


    一、SQL注入是什么

          SQL注入即:是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。

    本质上来说 SQL注入就是 将用户输入的数据当作代码来执行 

    这其中包含两个关键的条件:1、用户能够控制输入  2、原本程序要执行的代码 拼接了用户输入的数据。

    二、SQL注入会在那些地方出现

    如图  总结一句话:一切可以与数据库进行交互的地方

    三、SQL注入的分类

    根据数据的传输方式

    GET类型 POST类型 COOKIE类型

    根据数据的类型

    数字型 字符型

    根据注入的模式

    基于联合查询的注入模式  基于报错的注入模式  基于布尔的盲注  基于时间的盲注  推查询的注入模式

    四、SQL注入的一般步骤

    注:根据注入类型的不同 步骤也会有不同

    以下是联合查询会经常用到的语句 要记一下

    例如:

    1. select table_name from information_schema.tables where table_schema ='lizhi';//查询名为‘lizhi’的数据库的所有表
    2. select column_name from information_schema.columns where table_schema ='lizhi' and 'table_name'= 'lizhi_jett'//查询名为‘lizhi’的数据库中的名为‘lizhi_jett’的表中的所有列名

    SQL注入读写文件的根本条件:

    数据库允许导入导出(secure_file_priv)
    当前用户文件操作权限(File_priv)


    五、实战演练

    (不管何种注入模式 最开始都要先判断是否存在注入)

    1、基于联合查询的注入

    查列数

    id=1 order by 4 --+

    报错即没有这么多列 我们可以将4改为3 2 1以此类推根据回显得出有几列

    得到列数后我们需要知道那几列可以回显 那么我们可以根据回显看是第几列可以回显 这个时候我们只需要把回显的列数字改为我们想要查询的数据 如database() 就可以知道数据库名了

    id=1 and 1=2 union select 1,2,3,4 --+

    知道数据库名了我们就可以查表了

    例如:数据库名为 lizhi 那么 我们就可以用查询语句查出来我们的表名

    id=1 and 1 = 2 union select 1,group_concat(table_name),3,4 from information_schema.tables where table_schema = 'lizhi'

    表名知道了我们就可以查列名

    例如:表名为lizhi_jett

    id=1 and 1=2 union select 1,group_concat(column_name),3,4 from information.schema.column where table_schema='lizhi' and table_name='lizhi_jett' --+

    求字段内容

    例如:列名分别为 name password email

    id=1 and 1=2 union select 1,group_concat(name,0x23,password),3,4 from lizhi.lizhi_jett --+

    2、基于报错的注入

    页面有报错信息时优先考虑使用报错注入

    常用的报错函数

    实例

    SQL注入——sqli-labs第五关_sql注入第五关-CSDN博客

    重点也是floor报错注入

    select count(),(floor(rand(0)2))x from table group by x

    利用 select count(),(floor(rand(0)2))x from table group by x,导致数据库报错,通过 concat 函数,连接注入语句与 floor(rand(0)*2)函数,实现将注入结果与报错信息回显的注入方式。

    关键函数说明
    1.rand函数

    rand() 可以产生一个在0和1之间的随机数。

    可见,直接使用rand函数每次产生的数都不同,但是当提供了一个固定的随机数的种子0之后

    值就固定了  也可以称之为伪随机(产生的数据都是可预知的

    2.floor(rand(0)*2)函数

    floor() 函数的作用就是返回小于等于括号内该值的最大整数。

    而rand() 是返回 0 到 1 之间的随机数,那么floor(rand(0))产生的数就只是0,无法产生报错。

    因为我们刚才也看了 rand(0)出来的数字是固定的 且是0~1之间 floor函数是向下取整 这样我们就只能得到0
    所以 我们使用了floor (rand(0)*2)来让我们的返回值不全为0

    3.group by 函数

    group by 主要用来对数据进行分组(相同的分为一组)。


    首先我们在查询的时候是可以使用as(as可省略)用其他的名字代替显示的:

    然后就可以用group by函数进行分组,并按照x进行排序
    注意:最后x这列中显示的每一类只有一次,前面的a的是第一次出现的id值

    4.count(*)函数

    count(*)统计结果的记录数。

    与group by结合使用看一下:

    是对重复性的数据进行了整合,然后计数,后面的x就是每一类的数量。

    综合使用产生报错:

    select count(*),floor(rand(0)*2) x from users group by x;

    按照我们刚才对函数的理解 这句语句应该执行后是出现 0 1 1 0 1 1然后被分组后只有0 1 然后被计数 所以应该呈现给我们的表为

    0  2
    1  4

    但是最后却报错了

    报错分析

    这个整合然后计数的过程中,中间发生了什么我们是必须要明白的。 首先mysql遇到该语句时会建立一个虚拟表。该虚拟表有两个字段,一个是分组的 key ,一个是计数值 count()。也就对应于实验中的 user_name 和 count()。 然后在查询数据的时候,首先查看该虚拟表中是否存在该分组,如果存在那么计数值加1,不存在则新建该分组。
           然后mysql官方有给过提示,就是查询的时候如果使用rand()的话,该值会被计算多次,那这个"被计算多次"到底是什么意思,就是在使用group by的时候,floor(rand(0)*2)会被执行一次,如果虚表不存在记录,插入虚表的时候会再被执行一次,我们来看下floor(rand(0)*2)报错的过程就知道了,从上面的函数使用中可以看到在一次多记录的查询过程中floor(rand(0)*2)的值是定性的,为011011 (这个顺序很重要),报错实际上就是floor(rand(0)2)被计算多次导致的。

    我们还原一下具体的查询过程:

    建立虚拟表 取第一条记录执行floor(rand(0)*2)的时候发现结果为0(这里取前6次的数作为实验数据 前六次为 0 1 1 0 1 1)
    这个时候查询虚拟表 发现0的键值不存在 此时要插入键值则会再次执行floor(rand(0)*2) 注意这个时候取到的值就变为1了  所以1 作为键值插入了虚拟表

    PS:不知道为什么又执行了一次的话 再好好看一下报错分析

    继续查询第二条记录 发现还是1 1的键值存在 则count数加1 虽然只插入了两次但这是第三次计算floor(rand(0)*2)了

    再次查询虚表,(0 1 1 已经计算完了该第四个数了 又是0)发现键值没有0,则数据库尝试插入一条新的数据,在插入数据时floor(rand(0)*2)被再次计算, 算到第五个数字1 作为虚表的主键,其值为1(第5次计算),插入。

    这个时候就出问题了 

    然而1这个主键已经存在于虚拟表中,而新计算的值也为1(主键键值必须唯一),所以插入的时候就直接报错了。

    整个查询过程floor(rand(0)*2)被计算了5次,查询原数据表3次,所以这就是为什么数据表中需要最少3条数据,使用该语句才会报错的原因。

    3、布尔盲注

    核心思想:利用判断语句来证明推测是否正确 推测正确时,页面正常显示;错误时 页面异常

    一般来说猜值我们可以用到python写个脚本来爆库名表名

    4、时间盲注

    特点︰页面不存在异常,且即无回显也无报错信息
    利用∶只能利用条件语句结合执行时间的长短来判断payload是否正确

    六、WAF绕过

    1.大小写混合

    原因:服务器端检测时未开启大小写不敏感

    形式:Unlon SeLecT

    2.多重关键字/双写

    原因:服务器端检测到敏感字符时替换为空

    形式: ununionion selselectect

    3.编码

    原因:服务器端未检测或检测不严具有编码形式的关键字类型:十六进制编码、URL编码、Unicode编码
    形式:0x61646d696e、%20、%u0020

    4.注释

    原因:服务器端未检测或检测不严注释内的字符串

    形式:/*/,/*!*/,/*!12345*/,#,---等

    5.等价函数

    原因:服务器端黑名单不完整,过滤不严

    形式:Mysql查询: Union distinct、updatexml、Extractvalue、floor

    字符串截取函数: mid、substr、substring、left、reverse

    字符串连接函数:concat、group_concat、concat_ws

    字符串转换: char、hex、unhex

    替换逗号: limit 1 offset 0,mid(version() from 1 for 1)替换等号: like

    6.特殊符号

    原因:数据库中效果相同,服务器端却没有限制
    形式:
    科学记数法 and 1e0 = 1e0
    空白字符%0a %a0 %0b %20 %09
    反单引号‘table_name'
    括号 select *From (test.admin)

    七、SQL注入常用工具

    sqlmap 
    阿D
    穿山甲
    Havij(胡萝卜)

    SQLmap常用命令

    Python sqlmap.py -h显示基本帮助信息

    Python Sqlmap.py -hh显示高级帮助信息

    Web安全工具—Sqlmap常用命令和参数(持续更新)_sqlmap常用指令和参数-CSDN博客

  • 相关阅读:
    PHP 5 echo 和 print 语句
    LINUX 基础
    sql server导入表格出现错误
    Python学习——Day10
    C++11一些零碎的知识点介绍
    MyBatis 查询 MySQL 实现返回 List<Map> 或 Map 类型数据操作
    基于SSM的论文投稿系统
    企微hook框架
    ReentrantLock(可重入锁)
    Android Studio IDE安装指南
  • 原文地址:https://blog.csdn.net/lizhiiiii/article/details/137969302