PHP代码审计系列基础文章(一)之SQL注入漏洞篇

1.SQL注入原理

SQL注入就是攻击者通过把恶意的SQL语句插入到Web表单的输入页面中,且插入的恶意语句会导致原有的SQL语句发生改变,从而达到攻击者的目的去让它执行一些危险的数据操作,进一步欺骗服务器去执行一些非本意的操作。简单来讲,所有可以涉及到数据库增删改查的系统功能点都有可能存在SQL注入漏洞

一个简单的攻击原理举例:

PHP代码审计系列基础文章(一)之SQL注入漏洞篇_第1张图片

在SQL注入中,我们更应该关注的是业务逻辑,例如业务中可能设计到的增删改查操作,下面通过一个简单的代码小demo来进行SQL注入的演示:




   
   SQL注入小demo


用户名:
//form表单通过get方式接收数据 //通过name参数接收数据

1.1 PHP  MySQLi基本函数

PHP  MySQLi 函数允许访问 MySQL 数据库服务器。通俗来说MySQLi 下的函数用来处理PHP中关于数据增删改查的操作。

mysqli_connect()

PHP代码审计系列基础文章(一)之SQL注入漏洞篇_第2张图片

mysqli_query()

PHP代码审计系列基础文章(一)之SQL注入漏洞篇_第3张图片

mysqli_fetch_array()

PHP代码审计系列基础文章(一)之SQL注入漏洞篇_第4张图片

mysqli_close()

PHP代码审计系列基础文章(一)之SQL注入漏洞篇_第5张图片

为了方便演示实际的业务流程,我们创建demo数据库,并且创建user表,在表中插入演示数据。

PHP代码审计系列基础文章(一)之SQL注入漏洞篇_第6张图片

这里简单演示了一下通过查询来获取数据的操作原理。

PHP代码审计系列基础文章(一)之SQL注入漏洞篇_第7张图片

1.2 问题引申:

我们知道某些业务功能会涉及到数据库交互,如上所示,我们是不是可以通过正常功能插入恶意SQL语句来实现我们想要达到的目的呢?

例如这样:

1' union select 1,2,user(),database();#

2.SQL注入分类

SQL注入大致分为以下五大类,下面我们通过实际的PHP代码进行分析。

PHP代码审计系列基础文章(一)之SQL注入漏洞篇_第8张图片

2.1 报错注入

2.2.1 示例代码

通过传入id参数且传入的id参数未做过滤直接拼接到SQL语句中执行,直接使用mysqli_error()进行报错处理没有对报错进行良好的错误处理,所以导致报错注入的产生。

";
   echo 'Your Password:' .$row['passwd'];  //查询到id为xxx的passwd字段值并输出
}
else
{
   echo mysqli_error($db); //如果语句出现错误直接输出错误
}
   mysqli_close($db); //关闭mysql连接
}
?>

2.1.2 PHP函数介绍

mysqli_erro

PHP代码审计系列基础文章(一)之SQL注入漏洞篇_第9张图片

2.1.3 测试

当正常查询id=1时输出user以及passwd字段的值php123456

PHP代码审计系列基础文章(一)之SQL注入漏洞篇_第10张图片

当输入id=1',mysqli_error()捕获错误信息,并将SQL语句报错。

我们闭合SQL语句中的单引号即可执行我们想要的查询的内容

测试语句:

1' and (select extractvalue("anything",concat('~',( user()))))%20--%20dsddsa

PHP代码审计系列基础文章(一)之SQL注入漏洞篇_第11张图片

2.2 宽字节注入

2.2.1 代码示例

mysql中有一个特性,由于gbk是多字节编码,两个字节代表一个汉字,所以%df和后面的转义字符\也就是%5c会组成了一个汉字,而'就逃逸了出来造成SQL注入。在审计SQL注入时,要着重注意MySQL中设置的字符编码,如果为gbk,那么很可能存在宽字节注入。


"; $result=mysqli_query($db,$sql); $row = @mysqli_fetch_array($result); if($row) // { echo 'Your Login name:'. $row['user']; echo "
"; echo 'Your Password:' .$row['passwd']; } else { echo mysqli_error($db); } mysqli_close($db); } ?>

2.2.2 PHP函数介绍

addslashes()

PHP代码审计系列基础文章(一)之SQL注入漏洞篇_第12张图片

2.2.3 测试

我们发现输入'时,'被addslashes()转义。

PHP代码审计系列基础文章(一)之SQL注入漏洞篇_第13张图片

我们使用%df和前面的\闭合也就是%5c,然后我们的%27也就是'直接逃逸出来,这时我们就能构造自己想要执行的SQL语句,造成SQL注入。

测试语句:

1%df%27 and extractvalue(1,concat(0x7e,(select user()),0x7e)) -- qwe

PHP代码审计系列基础文章(一)之SQL注入漏洞篇_第14张图片

2.3  盲注

在盲注中不管是布尔盲注还是时间型盲注,页面显示不会有明显的变化,代码审计中只能通过查看源代码闭合原有的SQL语句,然后利用MySQL中延时的方式来判断是否存在SQL注入。

2.3.1 代码示例

这里为了进行盲注的演示,在代码中特意加入了一条if判断,当mysqli_fetch_array()查询的结果集为NULL的时候,返回id=1的数据内容,这就让我们无法判断插入的SQL语句是否执行成功,只能通过延时来进行测试。

";
       echo 'Your Password:' .$row['passwd'];
  }
   mysqli_close($db);
}
?>

2.3.2 测试

当我们查询数据库中存在的数据时返回指定字段的内容

PHP代码审计系列基础文章(一)之SQL注入漏洞篇_第15张图片

当我们查询数据库中不存在的数据时,由于mysqli_fetch_array()查询结果为NULL,所以返回id=1的指定字段内容。

由于我们在代码审计时可以一目了然看到SQL语句的构造情况,所以我们只需闭合相应的特殊字符,通过sleep()函数使页面延时,从而判断此处是否存在注入点,进而进行下一步的注入。

测试语句:

2312'%20or%20sleep(5)%20--%20qwe

2.4 二次注入

2.4.1 代码示例

二次注入的逻辑是在第一次insertupdate操作时代码存在转义而无法造成注入,但数据在被插入数据库时转义会消失,正常的SQL语句将会被存储到数据库中,在第二次调用插入的数据时被还原的SQL语句将被拼接到正常的SQL语句中造成二次注入。

PHP代码审计系列基础文章(一)之SQL注入漏洞篇_第16张图片


"; $result=mysqli_query($db,$sql); //第二次查询操作 $sql = "select * from user where id=1"; $result=mysqli_query($db,$sql); $row = @mysqli_fetch_array($result); $sql = "select * from user where user = '$row[2]'"; //查询结果集中下标为2(name)的一行数据 echo "输出第二次查询的SQL语句:".$sql."

"; $result=mysqli_query($db,$sql); var_dump(mysqli_fetch_row($result)); //取出查询到的结果集并以数组的形式返回 mysqli_close($db); } ?>

2.4.2 PHP函数介绍

mysqli_fetch_row()

PHP代码审计系列基础文章(一)之SQL注入漏洞篇_第17张图片

2.4.3 测试

输入'时,'addslashes()转义,这里无法造成注入

但在数据库中存储时转义\被清除

PHP代码审计系列基础文章(一)之SQL注入漏洞篇_第18张图片

但在第二次调用时转义后的SQL语句被拼接在正常的SQL语句中,造成二次注入。

测试语句:

' union select 1,2,database(),3 -- qwe

PHP代码审计系列基础文章(一)之SQL注入漏洞篇_第19张图片

3.SQL注入代码审计总结

在审计SQL注入的时候,我们首先要找到对应的传参点,更要多关注代码中正常SQL语句的规则和过滤情况,最重要的是要闭合正常的SQL语句来,最终执行我们想要执行的SQL语句。

你可能感兴趣的:(php,sql,数据库)