sql注入学习笔记

基础sql命令

  • select database()查看当前数据库名
  • select version()查看当前数据库版本
  • concat()将多个字符串拼接成一个字符串
  • group_concat(列名)将返回的多行结果合并成一行——使用示例:select group_concat(name) from users where sex=male()包裹要返回的列,就可以将返回的该列全部变成一行,也可以select group_concat(name,'~',passwd) from users where sex=male将所有的name、passwd拼接成一行,并且每个name、passwd间用~分割

sql注入

※ 总流程
    1.查找注入点
    2.判断是字符型还是数字注入(用and 1=1 and 1=2 或2-1),如果是字符型注入,找到闭合方式
    3.判断网页自带sql查询列数,group by、order by
    4.查询回显位置(先把原有查询设置成无结果的,如id=-1,再用1,2,3,4,5)
※注意事项
    1.在实际的注入过程中经常会用到where 1=1或者where true,如果判断条件是where true就会输出所有的结果
        如SELECT * FROM table WHERE TRUE就会输出table中所有内容
  • sql注入分类
    • 按查询字段
      • 字符型
      • 数字型
    • 按注入方法
      • union注入
      • 报错注入
      • 布尔注入
      • 时间注入
  • 1.判断字符型和数字型注入
    • 使用and 1=1 和and 1=2判断
      • 对于字符型select * from user where id="1 and 1=1"
      • 对于数字型select * from user where id=1 and 1=1
      • 字符型不会对“”中的内容做判断,而是当成一个字符串处理,但是数字型会对其中内容做判断,因此使用1=2时,字符型可以显示内容,数字型会出错。
    • 使用运算判断
      • 对于数字型id=1和id=2-1是一样的,也就是说可以通过id=2-1是否和id=1相同判断是否是数字型(注意要用-而不是+因为+有时会被判断成空格)
      • 字符型则无法作此运算
  • 2.字符型常见闭合方式
    • 常见闭合方式包括" ' ') ")
    • 判断闭合方式
      • 在id=1后面加" ' ') ")查看报错信息等方式
  • 3.注释
    • 单行注释(常用)
      • 单行注释一般包括#和-- ,单行注释会把一行里后面所有的内容都注释掉
        • #由于在url中#有其他用途,因此在get请求中想使用#注释应该使用%23替代
        • 在很多数据库和防护中空格都杯认为是下一句的开始,因此-- 并不适用,这种情况下往往+代表空格,因此转而使用–+做注释
    • 注释一般用来在手动写了闭合后,把后面多余的会导致报错的地方注释掉,所以一般注入语句的最后都会加上一个注释符号
  • 4.union联合注入
    • union联合注入很关键的一点在于union前后的两个查询语句查询出来的结果列数需要一致(因为结果会显示在一个表格中),因此需要在使用union联合注入之前判断列数
      • 判断列数一般用group by n和order by n,n即为列数
      • 可以union联合的两句中列多的一句用limit,或者给列少的一句补1,2,3
    • 回显:一般情况下网页往往只回显前面的一两个查询结果,导致union搜索语句被正常执行了,但是结果没有被显示出来。还有一种情况是selsct * from user where id=n假设搜索结果有10列,但是只希望显示第2和第5列,这种时候网页上也会有筛选,因此也需要确定回显位置,把想要看到的东西放到对应的第2和第5位上,才能顺利的看到想要的数据。
      • 可以给前面的语句加一个搜不到结果的参数,如id=-1这样整个结果就会前提,后面的结果就可以被显示出来
      • 可以给union后面的语句写select 1,2,3,4,5…这些数字不会做搜索处理而是直接显示输出,因此可以确定回显位
  • 5.查找表名和列名
    • mysql中有一个系统自带的数据库information_schema其中包含两个数据表-tables表名集合表-columns列名集合表
    • 查找表名:
      • tables表中的列table_name列专门记录所有表名,而还有一个列table_schema标识表所属的数据库名
      • 通过union select table_name(或其他列名)from information_schema.tables可以找到数据库中的表名(但是这里返回的是所有的表名,由于回显问题一般看不到想要的),可以用union select table_name from information_schema.tables where table_schema=database()(或直接写当前数据库名)使用上述命令返回当前数据库下的所有表名。
      • 由于回显位的问题,得到当前数据库下的所有表明还是往往只能显示第一个,这里用到group_concat()命令,将返回的多行table_name变成一行,可以在一个回显位全部显示
    • 查找列名:
      • columns表中有一列column_name记录所有列的名字,还有一个列table_schema标识column_name所属的数据库名,以及一个列table_name标识column_name所属的表名
      • 通过union select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name=此前查到的表名
    • 有了表名和列名就可以随意查询了
  • 6.报错注入
    • 本质上是网站执行sql语句后不回显,通过人为的一些错误输入,引导系统报错,并且在导致报错的语句上连接想要数据库执行的语句,通过报错信息得到想要得到的输出,主要有floor(),extractValue(),updateXml()等几种功能导致的报错
    • 需要注意的一点是报错注入只能返回32个字符,需要使用substring解决只能返回32个字符的问题,substring(要显示的字符串,从第几位开始显示(第一位下标是1),显示多少位),在实际场景中可以使用union select extravalue(1,concat('~',substring((select group_concat(table_name)from information_schema.tables where table_schema=database()))),1,30)显示当前数据库下所有表格名,从1开始,显示30个字符
    • 报错注入除了可以使用union select来导致报错之外,直接在原始的搜索语句基础上and可能是一种更好的方法,这样也省去了查看原始数据列数的过程
      • extractValue()报错注入:
        • extractValue()是一个用于从数据库某一列的内容中查询信息的功能select extractvalue(列名,'路径名(xpath格式)') from 表名,举例说明在这里插入图片描述
          ![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=image.png&pos_id=img-t4b4QpKB-1702029698917例如查询每本书的标题则可以用select extractvalue(doc,'/book/title') from xml
        • extractvalue()最主要的报错原因是路径有问题,例如没有以/开头,而是以例如~开头就会报错;在实际的注入时,列名其实不重要,重要的时路径名上做文章
        • 报错的时候会把路径的内容回显出来,因此,可以在路径上写一些想要他执行的语句来得到想要的信息,通常是在路径上写concat(‘~’,要执行的语句),例如想要查看当前数据库名可以union select extractvalue(1,concat('~',(select database())))就可以得到类似这样的回显在这里插入图片描述
          https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=image-1.png&pos_id=img-a9j7HNTj-1702029698918)然后就可以用union select extravalue(1,concat('~',(select group_concat(table_name)from information_schema.tables where table_schema=database())))得到当前数据库下所有表格名,以此类推
      • updatexml()报错注入
        • updatexml()是用于更新数据库中xml文档的功能,updatexml()有三个参数updatexml(xml文件名,xml要更新的内容的路径(xpath格式),要更新的数据)具体怎么使用不必过多关注
        • updatexml()报错和extractvalue()报错原理几乎完全一样,也是修改第二个参数即路径参数,改成union select updatexml(1,concat('~',(select ...)),3)
      • floor()报错注入
        • floor()报错注入是一种比较复杂的报错注入。需要用到很多功能,具体的需要用到的如下:
          • rand()随机生成一个0-1之间的小数,rand()*2随机生成一个0-2之间的数;select rand() from 表名,表有多少行就随机生成多少次;再实际使用中,为了有足够多的结果来产生报错,一般选一个表象比较多的表,如information_schema.tablesrand()并不是真正的完全随机,rand(0),rand(1)…生成的随机数序列都是固定的,有一个随机种子,种子为0的时候,floor(rand(0))的结果永远是0,1,1的循环
          • floor()小数向下取整
          • concat_ws()将括号内的数据用第一个字段连接起来concat_ws('~','abc','123')结果为'abc~123'
          • as取别名select concat_ws('-',(select database()),floor(rand()*2)) as a from users group by a先成成database名——随机数取整的结果,将这个结果叫做a,按a分组,as的意义其实当要用一个复杂的语句排序时,可以直接as a,order by或者group by a
          • count()汇总数量,在上面语句的基础上加count(),注意count()后面要有逗号select count(*),concat_ws('-',(select database()),floor(rand()*2)) as a from users group by a会先按a进行分组,然后统计每个分组内有多少个
          • 上面的语句写成rand(0),即select count(*),concat_ws('-',(select database()),floor(rand(0)*2)) as a from users group by a就会报错,报错的原因在于进行count操作的时候会生成一张key-count的统计表(这个很好理解),初始时统计表是空的,而每次有新的key值要加入表中的时候不会直接拿之前值直接加入key,而是会在入表前再进行一次计算,将计算的值作为新的key加入表格中。
            具体来讲floor(rand(0)*2)生成0,1,1,0,1,1...具体执行过程中:
            首先进行第一次计算得0,因此将0加入表中,这里表中key值没有0,因此要进行第二次计算,计算的结果是1因此实际上是加入了1到表格中
            然后进行第三次计算得1,因此将1加入表中,这里表中key值已经有1,因此可以直接加入表中,现在表key只有1,count为2
            再进行第四次计算得0,因此将0加入表中,现在表中key依旧没有0,因此进行第五次计算,将结果作为key加入表中
            然而第五次计算的结果是1,但是表中已经有了1这个key值,无法再加入了,因此key值出现了冲突导致报错
            #所以报不报错其实是取决于随机序列的,rand(1)就不会报错
            
          • 实战过程中一般使用concat_ws(‘~’,‘abc’,‘123’)中的后一个字符串作为floor(rand(0)*2) ,将中间的字符串写成自己想要数据库执行的查询语句,例如and select count(*),concat_ws('-',(select database()),floor(rand(0)*2)) as a group by a就可以查看当前数据库
  • 19
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值