原理
SQL注入的原理来说,其实还是很简单的,首先先来一段php代码:
1 |
|
就是获取用户传过来的id的值,然后到数据库里去找。比如URL栏里输入的是example.com/?id=1,那么构造的查询语句就变成了:
1 | SELECT * FROM users WHERE user_id = '1' |
因为id是由我们来进行控制的,所以就可以构造诸如 ' or '1' ='1 来进行注入。实际上构造的是下面这样的:
1 | SELECT * FROM users WHERE user_id = '' or '1' ='1' |
分类
这里的分类主要是针对注入使用的技巧来分的。
- 回显注入:可以直接在存在注入点的当前页面中获取返回结果。
- 报错注入:程序将数据库的返回错误信息直接显示在页面中,虽然没有返回数据库的查询结果,但是可以构造一些报错语句从错误信息中获取想要的结果。
- 盲注:程序后端屏蔽了数据库的错误信息,没有直接显示结果也没有报错信息,只能通过数据库的逻辑和延时函数来判断注入的结果。根据表现形式的不同,盲注又分为based boolean和based time两种类型。
- 堆叠注入:在一条sql语句之后可以使用分号进行分隔,然后继续输入新的sql语句来进行恶意破坏。
练手平台
https://github.com/Audi-1/sqli-labs 由于这个repo的php支持的版本比较老,所以需要修改下,到sqli-labs/sql-connections这个目录下面,然后使用如下的脚本即可:
1 | #!/usr/bin/env python3 |
其实就是把一些过时的函数替换成最新的,即可使用。
或者也可以使用docker来安装,更加简单方便:docker run -dt --name sqli-lab -p 80 acgpiano/sqli-labs:latest安装完成之后看一下是哪个端口映射了容器的80端口即可。
注入点
由上面的分析可知,其实只要你的sql语句中有能让用户决定的内容,而且你做的检查不够,就有可能会被SQL注入。常见的有这些:
- GET/PUT/header等参数,在原理中已经看到了使用GET进行注入的。
- 文件名字
MySQL举例
首先有一点是确定的,需要更好的理解SQL注入,肯定是需要你很好的掌握数据库的一些操作,或者理解它的一些概念的;还需要了解那些编写CURD的程序员是怎么编写程序的,通俗地讲就是他们写出来的SQL语句是怎么样的,这样你才能进行注入。下面是通过Mysql版本5.7进行的一些演示。
基础表格
装完MySql之后,通过查看数据库可以发现有以下四个数据库:
- information_schema
- mysql
- performance_schema
- sys
这里最重要的就是information_schema这个数据库,这个数据库里面存了数据库和数据表的元信息。当然这个数据库里面有非常多的表格,这里主要分析一个叫TABLES的表格。
首先查看一下我们所有的数据库的所有表格:
1 | select table_schema from `TABLES` |
会找出所有的表格所属的数据库,所以量会很大。
一些tricks
- 查看版本
select @@version;
如何防范
对付SQL注入的最佳方法应该是:使用静态占位符,使用这个方法可以根治SQL注入。
其他的一些辅助性策略:不显示错误信息(解决报错注入)、检验输入值的有效性(从网上找一些正则表达式过滤掉一些字符)、设置数据库的权限(有效减少损失)。