[数据库] 软件安全测试之 SQL 注入

这些年我们发现越来越多的公司开始注重安全测试了,为什么?因为安全测试可以在某种程度上可以排查掉你项目的一些安全漏洞,这样你的系统上线后才会相对安全,才有可能尽量避免来自外部的攻击。每一年互联网都会发生一些重大的安全事件,而且每一次带来的后果也是很严重的,而这些教训恰恰都说明了安全测试的重要性。

那什么是安全测试呢?百度百科上给出来的解释是:安全测试是在 IT 软件产品的生命周期中,特别是产品开发基本完成到发布阶段,对产品进行检验以验证产品符合安全需求定义和产品质量标准的过程 。按照小编的理解,简单点来讲,其实安全测试可以这么理解:安全测试其实就是测试你的系统是否有安全漏洞,普通测试以发现 BUG 为目标,安全测试以发现安全隐患为目标。

那么安全测试有哪些东西可以测呢?我们在对一个系统进行安全测试的时候其实是有很多应该考虑进去的,像表单攻击,SQL 注入,XSS 攻击,CSRF 攻击,暴力破解等。

小编今天要讲的是安全测试下的 SQL 注入,通过学习,了解什么是 SQL 注入,同时小编我会结合项目中的几种情况来为大家讲解常见的 SQL 注入场景以及如何去执行 SQL 注入攻击。首先我们来看一下什么是 SQL 注入,解释:SQL 注入就是通过构建一些特殊的表达式或这一些特殊的 SQL 命令,通过表单提交到后台服务器,最终达到欺骗服务器执行恶意的 SQL 命令,或者达到一个绕过服务器校验的一个效果。

第一种比较常见的注入场景是系统的登录功能,当然现在很多大公司的项目在这一块是做的很好,也做的非常安全的,很少会留下 SQL 注入这样的漏洞,而一些小的系统,小的项目或者自己写着玩的系统可能会存在这样的安全漏洞。这里我就写了一个简单的登录注册功能,来帮助大家了解什么是 SQL 注入,大概逻辑是这样的:通过在登录页面输入用户名和密码来完成登录,后台会拿到前台表单提交的数据去数据库做校验匹配,如果存在此用户就让登录成功,如果匹配不到就提示“错误的用户名或者密码”。然后我们这里呢会通过构建一些特殊的数据或者表达式来实现 SQL 注入。现在小编就先把这个登录功能的前台页面和后台的几行关键代码贴出来:
以下是前台登录页面:

image.png

以下是后台登录关键代码:

image.png

   其实我们看到这个后台的核心代码其实就是拿到前台用户名和密码去数据库做了检索,看是否存在,存在就放行,不存在就提示错误信息。然后接下来我们来测试一下登录,首先我们拿数据库表里已经注册的用户“001@qq.com/111111”来登录:

image.png

   前台登录界面输入用户名“001@qq.com”,密码“111111”,点击登录,然后我们发现成功登录了,这个结果是正常的。

image.png

image.png

image.png

   然后我们接着来试一下错误的用户名或者密码,这里我们直接拿一个上面用户表不存在的用户“007@qq.com/111111”来进行登录,最后结果提示“用户名或者密码错误”,这个结果也是正常的。

image.png

image.png

   正确的用户名密码能登录成功,错误的用户名密码就登录失败,看上去没有任何问题,那是不是就意味着这个登录功能就没有bug没有漏洞了呢?现在下决定还为时尚早,前面我们做测试都是拿的正常的数据,不是特殊,极端的数据。后面我们将输入一些特殊的数据来继续完成测试。测试之前,我们来分析一下登录的一行核心代码,我们稍微有点编程基础的同学都看得懂下面登录逻辑里的数据库查询代码:

image.png

   这一行代码其实就是拿到前端传进来的用户名和密码来拼接得到一条sql,然后在后台执行这条拼接的sql去查询用户表是否存在这样的用户,看上去似乎没啥问题,其实不然,我们看到这条sql里的条件字段的跟它的值拼接的时候用了一对单引号包起来了,这个也很好解释,因为数据库中字符串类型的条件字段后面带值的时候需要带一对单引号(这里需要一定的数据库基础,没有这部分基础的同学可以加我们的测试群,找相关管理员要数据库基础这一部分视频来学习),而正是因为这样的拼接写法导致了sql注入漏洞的存在,因为我们可以通过在前端登录页面用户名一栏输入:’ or ‘1’=’1这样一个特殊的表达式,密码的话随便填一个,比如还是填111111,那最后服务器后台拿到前台传入的用户名和密码去做sql拼接的时候,得到的最终sql将会是这样一条:select count(*) from nm_user where password=’111111’ and username=’’ or ‘1’=’1’;而这样一条sql因为存在一个恒等的条件表达式:’1’=’1’,所以无论如何都可以从user表查到数据的(只要user表有数据),所以最后就通过了服务器后台的校验,登录成功了,如下图:

image.png

   但是,我们的数据库其实是没有这样的用户的。这里再次附上我们用户表的数据:

image.png

   而这样的一个用户名却登录成功了,这个就是sql注入,通过构建一些特殊的表达式或者特殊的sql然后通过表单提交到后台服务器,骗过后台服务器去执行这样一条恶意的sql或者别有用心的sql来绕过服务器的校验。

好的,简单的举例说明了一下什么是 SQL 注入,我相信大家也对于这个概念有了一定的理解,这里其他的一些 SQL 注入场景这里就不再另行举例了,例子是变的,但是思想是不变的,大家把握住 SQL 注入的概念和思想就可以了。大家可以写个简单的 demo 去验证下,或者拿自己公司的项目去验证下,不保证能复现这样的问题,因为这样的 SQL 注入漏洞还是很好去避免的,直接使用 ibatis,MyBatis,hibernate 数据库等框架的相关 API 就能规避这样的安全漏洞,因为这些框架里操作数据库的 API 底层都是使用的 PreparedStatement 而不是 Statement,前者相对于后者的一个好处是它提供了一个 SQL 预编译的机制和防注入的一个功能。

回帖
请输入回帖内容 ...