文章目录
SQL简介
SQL注入漏洞是web层面最高为的漏洞之一。SQL注入就是将SQL命令提交到WEB表单递交或者输入域名或者页面请求查询字符串,达到欺骗服务器执行恶意代码的SQL命令,比如先前的很多影视网站泄露VIP会员密码大多就是通过WEB表单递交查询字符暴出的,这类表单特别容易受到SQL注入式攻击。当应用程序使用输入内容来构造动态sql语句以访问数据库时,会发生sql注入攻击。如果代码使用存储过程,而这些存储过程作为包含未筛选的用户输入的字符串来传递,也会发生sql注入。 黑客通过SQL注入攻击可以拿到网站数据库的访问权限,之后他们就可以拿到网站数据库中所有的数据,恶意的黑客可以通过SQL注入功能篡改数据库中的数据甚至会把数据库中的数据毁坏掉。做为网络开发者的你对这种黑客行为恨之入骨,当然也有必要了解一下SQL注入这种功能方式的原理并学会如何通过代码来保护自己的网站数据库。
漏洞产生的主要原因是服务器对用户输入的信息没有做过滤。攻击者通过构造特殊的 SQL 语句,入侵目标系统,致使后台数据库泄露数据的过程。
SQL注入原理
程序开发过程中,由于不重视书写规范,对sql关键字未进行过滤,导致客户端可以通过POST或GET提交sql语句到服务器端正常运行。SQL注入就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。具体来说,它是利用现有应用程序,将(恶意)的SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句。SQL注射能使攻击者绕过认证机制,完全控制远程服务器上的数据库。 SQL是结构化查询语言的简称,它是访问数据库的事实标准。目前,大多数Web应用都使用SQL数据库来存放应用程序的数据。几乎所有的Web应用在后台都使用某种SQL数据库。跟大多数语言一样,SQL语法允许数据库命令和用户数据混杂在一起的。如果开发人员不细心的话,用户数据就有可能被解释成命令,这样的话,远程用户就不仅能向Web应用输入数据,而且还可以在数据库上执行任意命令了。
SQL的危害
(1)攻击者未经授权可以访问数据库中的数据,盗取用户的隐私以及个人信息,造成用户的信息泄露。
(2)通过操作数据库对某些网页进行篡改。
(3)修改数据库一些字段的值,嵌入网马链接,进行挂马攻击;攻击者进而可以对网页进行篡改,发布一些违法信息等。
(4)服务器被远程控制,被安装后门。可以对数据库的数据进行增加或删除操作,例如私自添加或删除管理员账号。
(5)数据库被恶意操作:数据库服务器被攻击,数据库的系统管理员帐户被窜改。
(6)破坏硬盘数据,导致全系统瘫痪。
关键:查询数据、读取文件、执行敏感命令
攻击方法
SQL 注入即攻击者通过构造特殊的 SQL 语句,入侵目标系统,致使后台数据库泄露数据的过程。
将 SQL 代码插入或添加到应用(用户)的输入参数中的攻击,之后再将这些参数传递给后台的 SQL 服务器加以解析并执行。
防止SQL注入的10种办法
1.使用参数化查询
2.输入验证和过滤
3.使用存储过程
4.使用ORM框架
5.最小权限原则
6.使用准备语句
7.使用安全的数据库连接
8.避免动态拼接SQL语句
9.使用防火墙和入侵检测系统
10.定期更新和维护数据库软件
(详细细节待后续补充)
可参考:https://blog.csdn.net/qq_28245087/article/details/131453274
SQL注入漏洞检测方法
在发现有可控参数的地方使用 sqlmap 进行 SQL 注入的检查或者利用,也可以使用其他的 SQL 注入工具,简单点的可以手工测试,利用单引号、 and 1=1和 and 1=2以及字符型注入进行判断!推荐使用 burpsuite 的 sqlmap 插件,这样可以很方便,鼠标右键就可以将数据包直接发送到 sqlmap 里面进行检测了!
SQL漏洞修复建议
代码层最佳防御 SQL漏洞方案:采用 SQL语句预编译和绑定变量,是防御 SQL注入的最佳方法。
( 1 )所有的查询语句都使用数据库提供的参数化查询接口,参数化的语句使 用参数而不是将用户输入变量嵌入到 SQL 语句中。当前几乎所有的数据库系统 都提供了参数化 SQL 语句执行接口,使用此接口可以非常有效的防止 SQL 注 入攻击。
( 2 )对进入数据库的特殊字符( ’ <>&*; 等)进行转义处理,或编码转换。
( 3 )确认每种数据的类型,比如数字型的数据就必须是数字,数据库中的存 储字段必须对应为 int 型。
( 4 )数据长度应该严格规定,能在一定程度上防止比较长的 SQL 注入语句 无法正确执行。
( 5 )网站每个数据层的编码统一,建议全部使用 UTF-8 编码,上下层编码 不一致有可能导致一些过滤模型被绕过。
( 6 )严格限制网站用户的数据库的操作权限,给此用户提供仅仅能够满足其工作的权限,从而最大限度的减少注入攻击对数据库的危害。
( 7)避免网站显示 SQL 错误信息,比如类型错误、字段不匹配等,防止攻击者利用这些错误信息进行一些判断。
MySQL相关知识
相关知识
在 mysql5 版本以后,mysql 默认在数据库中存放在一个叫 infomation_schema 里 面 这个库里面有很多表 重点是这三个表 COLUMNS 、TABLES、SCHEMATA 表字段 CHEMA_NAME 存储着该用户创建的所有数据库的库名
TABLES表字段 TABLE_SCHEMA 、TABLE_NAME 存储着该用户创建的数据库表名。
COLUMNS存储该用户创建的表的字段名。
通过 infomation_schema 查询 www_dvwa_com 库里所有的表和字段
MySQL查询方式
1.查询所有数据库
show databases
2.查询指定数据库中所有表名
select table_name from information_schema.tables where table_schema='database_name' and table_type='base table';
3.查询指定表中的所有字段名
select column_name from information_schema.columns where table_schema='database_name' and table_name='table_name';
4.查询指定表中的所有字段名和字段类型
select column_name,data_type from information_schema.columns where table_schema='database_name' and table_name='table_name';
例如:
select*from 数据库名.表名 where TABLE_SCHEMA=' 'and TABLE_NAME=' '
select * from information_schema.COLUMNS where TABLE_SCHEMA='www_dvwa_com' and TABLE_NAME='users'
其他需要注意的内容
在不知道任何条件时,语句如下:
SELECT 要查询的字段名 FROM 库名.表名
在找到一条已知条件时,语句如下:
SELECT 要查询的字段名 FROM 库名.表名 WHERE 已知条件的字段名='已知条件的值'
在找到两条已知条件时,语句如下:
SELECT 要查询的字段名 FROM 库名.表名 WHERE 已知条件1的字段名='已知条件1的值' AND 已知条件2的字段名='已知条件2的值'
limit的用法
limit的用法格式是limit m,n,其中m是指记录开始的位置(从0开始表示第一条记录),n为取n条记录
常用函数名称:
database():查询当时网站使用的数据库
version():查询当前MySQL版本
user():查询当前MySQL的用户
可参考:link
判断是否存在注入
判断方法
最为经典的就是单引号判断法:在参数后面加上单引号,比如:http://xxx/abc.php?id=1’,如果页面返回错误,说明存在SQL注入(无论是字符型还是整型都会因为单引号个数不匹配导致报错,如果没报错不代表没有SQL注入,有可能对单引号进行了过滤,这时可以使用判断语句进行注入)
1.显错注入的判断方法
如这么一个网站www.example.com/index.php?id=1,首先第一步我们先进行是否存在注入的判断,先在数字1后加单引号 ',若页面出错,则存在Sql注入,但注入点是否可利用还和服务端代码和服务器配置息息相关(如过滤一些危险函数或者限制参数的长度时就不可以利用)。其次还可以使用逻辑符号来判断是否存在注入,参数后加and 1=1和and 1=2,若and 1=1页面返回正常,and 1=2返回错误时,则存在Sql注入(这是Sql语法运算符的特点,SQL AND & OR 运算符如果第一个条件和第二个条件都成立,则 AND 运算符显示一条记录。如果第一个条件和第二个条件中只要有一个成立,则 OR 运算符显示一条记录。),否则不一定存在注入。 同理也可以使用or来判断是否存在注入。需要注意的是,我们需要根据注入点的类型来判断是否需要在整个参数中添加注释符或引号。
2.不显错的判断方法
在单引号and和or下都不报错时,也可能存在注入,由于服务器可能配置在参数错误时依然返回原有页面,这样即使存在注入页面也不会发生变化了。我们可利用页面返回时间来判断是否存在注入,如and if(1=0,1, sleep(10)),注意是否需要使用单引号或者注释符。不同的数据库有不同的延时函数,需要结合具体情况来使用。
SQL注入类型
以注入的参数类型分类
注入类型分为数字型和字符型和搜索型
例如数字型语句:select * from table where id =3,则字符型如下:select * from table where name=’admin’。可见在测试时需要添加引号去闭合参数时才能使页面返回正确的是字符型注入,不需要添加的是数字型注入
数字型
select * from <表名> where id = x and 1=1
select * from <表名> where id = x and 1=2
检测回显是否有区别
类似结构 http://xxx.com/users.php?id=1 基于此种形式的注入,一般被叫做数字型注入点,缘由是其注入点 id 类型为数字,在大多数的网页中,诸如 查看用户个人信息,查看文章等,大都会使用这种形式的结构传递id等信息,交给后端,查询出数据库中对应的信息,返回给前台。这一类的 SQL 语句原型大概为 select * from 表名 where id=1 若存在注入,我们可以构造出类似与如下的sql注入语句进行爆破:
select * from 表名 where id=1 and 1=1
当输入的参数为整型时,如 ID、年龄、页码等,如果存在注入漏洞,则可以认为是数字型注入。
字符型
select * from <表名> where id = ‘x’ and ‘1’=‘1’
select * from <表名> where id = ‘x’ and ‘1’=‘2’
类似结构 http://xxx.com/users.php?name=admin 这种形式,其注入点 name 类型为字符类型,所以叫字符型注入点。这一类的 SQL 语句原型大概为 select * from 表名 where name=‘admin’ 值得注意的是这里相比于数字型注入类型的sql语句原型多了引号,可以是单引号或者是双引号。若存在注入,我们可以构造出类似与如下的sql注入语句进行爆破:
select * from 表名 where name=‘admin’ and 1=1 ’
我们需要将这些烦人的引号给处理掉
数字型与字符型注入最大的区别在于:数字型不需要引号闭合,而字符串类型一般要使用引号或其他符号来闭合。
搜索型
一般出现在查询搜索处,要进行搜索型注入,我们还得了解一下sql数据查询中where子句使用Like操作符的知识,Like操作符所起的作用就是模糊查询,要使用Like进行模糊查询必须还要配合通配符才能完成,”%”就是Like操作符中的一种通配符,它代表零个或多个任意字符:
Like ‘sina%’ //返回以sina开始的任意字符
Like ‘%sina’ //返回以sina结尾的任意字符
Like ‘%sina%’ //返回以包含sina的任意字符
a%’ and 1=1 – 正常
a%’ and 1=2 – 错误
这是一类特殊的注入类型。这类注入主要是指在进行数据搜索时没过滤搜索参数,一般在链接地址中有 “keyword=关键字” 有的不显示在的链接地址里面,而是直接通过搜索框表单提交。此类注入点提交的 SQL 语句,其原形大致为:select * from 表名 where 字段 like ‘%关键字%’ 若存在注入,我们可以构造出类似与如下的sql注入语句进行爆破:
select * from 表名 where 字段 like ‘%测试%’ and ‘%1%’=‘%1%’
可参考:[link]
(https://www.cnblogs.com/zzhoo/p/12358384.html)
当在搜索框注入的时候,称为搜索型。搜索类型一般要使用百分号进行闭合。
以注入的位置分类
GET 注入
可通过安装浏览器插件(hackbar)或直接通过浏览器地址栏提交。
POST 注入
可通过安装浏览器插件(hackbar)或 Burpsuite 来完成。
Cookie 注入
GET 和 POST 如果被过滤,可以试试。
一般通过 Burpsuite 来完成,修改 Cookie 进行注入。
UA 注入
一般通过 Burpsuite 来完成,修改 UA 进行注入。
…
以注入的技术分类
普通注入(union 联合注入)
概述
普通注入是根据后台数据库提示有价值的错误信息,进行注入操作,一般可以把攻击者需要获得的信息直接查询显示在页面中。
核心方法
使用 union 合并两个或多个 SELECT 语句的结果集,第二个语句中就包含我们想要查询的语句。
盲注
概述
当我们输入的注入语句被带入数据库查询,页面却不能回显结果时,如:应用程序只会返回一个通用的(对错信息或什么信息都不显示)页面或特定的语句,我们不能以此来判断注入是否成功,这种情况下就要用到 SQL 盲注的技巧。
目标网站的数据库是 Access,系统中没有类似 MySQL 的 Information_schema 库。
攻击者运用脚本通过仅有的判断信息对表中每个字段进行探测,从而实现注入。
分类
布尔型
概述
目标页面上没有显示数据内容的功能,仅有显示对错或有无(布尔值)的提示。
攻击方法
通过构造特殊 SQL 语句,观察页面返回的对错来判断 SQL 语句是否成立。
时间型
概述
对于某些页面,可能任何信息都不返回,甚至连记录是否存在都不告诉你,此时布尔型就失效了。
通过构造条件语句,条件语句判断为真则立即执行,否则延时执行。
攻击方法
通过 sleep() 函数,观察页面返回是否有延时来判断 SQL 语句是否成立。
报错注入
概述
当数据库的函数被传入错误参数时,会发生语法错误,正常情况下这类错误不应该回显到前端页面,但当中间件或程序未正常屏蔽时导致错误信息输出到屏幕上,就能用来进行报错注入了。
select/insert/update/delete 都可以进行报错注入。
报错注入条件
后台没有屏蔽数据库报错信息,在语法发生错误时会输出在前端。
运维人员设置中间件的时候,错误输出没有屏蔽。
程序员写网站代码的时候,没有屏蔽错误信息输出。
宽字节注入
漏洞产生和后端编码有关,如后端采用 GBK 编码。
数据库使用 GBK 编码时,两个字符为一个汉字。
ASCII 码只有 128 个,大于 128 的就会和第二个字符组成一个汉字。
二次注入
有些程序在进行数据库插入的时候,仅仅对特殊字符进行了转义,但仍然将数据写入了数据库,如果插入的数据包含恶意内容,此时在其他地方查询该数据时,如果没有对取出的数据做校验处理(即认为写入即可信),直接使用该数据,就会造成 SQL 二次注入。
二次编码注入
php 代码中用了 urldecode() 等编码函数,对 url 中的特殊字符进行转码,可以利用此函数与 php 自身编码转换,产生漏洞。
常见注入语句
id =1 and 1=1
id = 1 and 1=2
id = 1 or 1=1
id = ‘1’ or ‘1’=‘1’
id=" 1 "or “1”=“1”(注:一般SQL内有’,所以右单引号一般不打)
无回显是指根据输入的语句,页面没有任何变化,或者没有数据库中的内容显示到界面上
三种常见的SQL注释符
# 单行注释 注意与 url 中的#区分,常编码为%23
--空格(有空格才会生效) 单行注释 注意为短线短线空格
/ *()*/ 多行注释 至少存在俩处的注入
/*()*/常用来作为空格