结构化查询语言(Structured Query Language,缩写︰SQL),是一种特殊的编程语言,用于数据库中的标准数据查询语言。
SQL注入(SQL Injection)是一种常见的Web安全漏洞,主要形成的原因是在数据交互中,前端的数据传入到后台处理时,没有做严格的判断,导致其传入的“数据”拼接到SQL语句中后,被当作SQL语句的一部分执行。 从而导致数据库受损(被脱库、被删除、甚至整个服务器权限陷)。
sql注入在安全问题中排行第一
sql注入攻击是输入参数未经过滤,然后直接拼接到sql语句当中解析
sql注入是一种将sql代码添加到输入参数中,传递到服务器解析并执行的一种攻击手法
注入流程:由于关系型数据库系统,具有明显的库/表/列/内容结构层次,所以我们通过SQL注入漏洞获取数据库中信息的时候,也依据这样的顺序。首先获取库名,其次获取表名,然后获取列名,最后获取数据。
web应用程序在接收相关数据参数时未做好过滤,直接将其带入到数据库中查询,从而攻击者可以拼接执行构造的sql命令,导致了sql注入的发生。其成因可以归结外以下原因叠加造成的:
攻击者在页面提交恶意字符(例如单引号、空格、1=1等)
服务器未对提交参数进行过滤或过滤不足
攻击者利用拼接sql语句方式获取数据库敏感信息
攻击者利用SQL注入漏洞,可以获取数据库中的多种信息(例如︰管理员后台密码),从而脱取数据库中内容(脱库)。在特别情况下还可以修改数据库内容或者插入内容到数据库,如果数据库权限分配存在问题,或者数据库本身存在缺陷,那么攻击者可以通过SQL注入漏洞直接获取webshell(脚本木马,是通过服务器开放的端口获取服务器的某些权限)或者服务器系统权限
获取web网页数据库--数据泄露
用户数据被非法买卖
危害web应用安全
sql注入漏洞根据不同的标准,有不同的分类。
从数据类型分类来看,sql注入分为数字型和字符型。
数字型注入:注入点的数据,拼接到sql语句中是以数字型出现的,即数据两边没有被单引号、双引号包括。
字符型注入:注入点的数据两边有单引号、双引号括起来
根据注入手法分类,大致可分为以下几个类别:
UNION query SQL injection (可联合查询注入) union联合查询注入
Error-based SQL injection(报错型注入) 报错注入 这两种属于正常注入
Boolean-based blind SQL injection(布尔型注入) 布尔盲注
Time-based blind SQL injection(基于时间延迟注入) 延时注入 这两种属于盲注类别
Stacked queries SQL injection(可多语句查询注入) 主要目的是增删改,也叫堆叠查询
union查询注入:union查询注入是最基础的注入。在SQL中, UNION 操作符用于合并两个或多个 SELECT 语句的结果。union 查询注入利用 UNION 关键字可以追加一条或者多条额外的 SELECT 查询,并将结果追加到原始查询中
报错注入:攻击者在攻击时常根据错误回显进行判断,都是现在很多web应用程序没有正常得错误回显,我们就需要利用报错注入来进行sql注入
盲注:指的是在不知道数据库返回值的情况下对数据中的内容进行猜测,实施SQL注入,主要分为基于布尔的盲注和基于时间的盲注
堆叠查询注入:堆叠查询注入为攻击者提供了很多的攻击手段,通过添加一个新的查询或者终止查询,可以达到修改数据和调用存储过程的目的
根据提交数据的位置进行分类:
可以分为get注入、post注入、cookie注入 GPC
根据SQL注入漏洞的原理,在用户“可控参数"中注入SQL语法,也就是说web应用在获取用户数据的地方,只要带入数据库查询,都有存在SQL注入的可能,这些地方通常包括:
GET 数据
POST 数据
HTTP 头部(HTTP 请求报文其他字段)
Cookie 数据
?id=1 变换id参数+1/-1,前提是有sql注入漏洞,页面发生变化则考虑为联合查询
也就是说,数据库中的内容会回显到网页中来。
初步判定,id参数会带入数据库查询,根据不同的id查询数据库,得到不同的网页内容。
猜测后台执行的SQL语句大致结构为:
select * from tbName where id=1;
【?id=1'】 判断sql注入类型,是字符型还是数字型
执行的SQL主语则变为
select * from tbName where id=1'
(报错显示有1是字符型注入,未显示1则是数字型注入)
页面报错,并且报错信息会回显在页面中,报错信息如下:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''1'' LIMIT 0,1' at line 1
错误信息提示单引号位置出现错误,由此说明,SQL语句是由单引号包裹的
因此,此注入点(可能)为字符型注入。
[?id=1' and 1=1 --+]
可能得SQL语句为
select * from tbName where id=1' and 1=1 --+
页面正常。
[?id=1' and 1=2 --+]
可能得SQL语句
select * from tbName where id=1' and 1=2 --+
页面没有内容,并且数据库没有报错。由于1=2是恒假式,也就是查询条件[where id=35and 1=2--+]恒假,这样的SQL语句在数据库中执行后,没有返回结果,没有网页内容。
反过来看,页面没有内容,也就是SQL语句查询条件为假。也就是说,我们写的语句[and1=2 --+],起到了将查询条件置为假的作用。
那么,可以通过构造语句来控制SQL语句的查询结果并且,SQL语句查询条件真假性,在页面回显中有体现。
?id=35 and 1=1 是否有布尔类型的状态(如果是布尔类型的状态,则
?id=35 and 1=2 这两次页面的状态不同,如果相同则没有布尔类型 )
select * from tbName where id=35 and 1=1 True
select * from tbName where id=35 and 1=2 False
[?id=1' and sleep(5)] 是否有延时响应
注入sleep(5)语句,可以通过网络时间线看到延时。
说明sleep(5)语句起到了作用
综上,此连接存在SQL注入漏洞(除了变换id参数之外,其他判断条件出现其中任意一个,则存在sql注入)。
结构化查询语言(Structured Query Language)简称SQL,1974年由Boyce和Chamberlin提出,是一种关系型数据库查询的标准编程语言,用于存取数据以及查询、更新、删除和管理 关系型数据库。为什么强调标准语言?我们知道关系型数据的主要三大实现者分别是,Mysql,MS SQLServer,Oracle。
它们实现数据存储的底层引擎或许不同,但提供出来管理数据的编程语言必须遵循 SQL 规范,但可以定制添加属于自己的额外语法,这些额外的、SQL 之外的语法又被称作它们各自的『SQL方言』。
所以如果你拿着 SqlServer 的方言跑到 Mysql 里去执行,那很大程度上是会报错的。因为sqlserver和mysql虽然都遵循着sql规范,但是它们又添加了属于自己的语法。所以语法是有区别的
关系型数据库系统:具有非常明显的层次结构,库名/表名/字段名/字段内容.
MySQL数据库注释大概有以下几种:
#
--(杠杠空格) (注入中经常用到的)
/* ..... */
/*! .... */ 内联查询
MySQL基础详情——>MySQL基础
MySQL 5.0版本之后产生了一个虚拟数据库information_schema,在这个数据库中有三个很重要的表:
information_schema: 该数据表存储了mysql数据库中的所有数据库的库名
information_schema.tables: 该数据库存储了mysql数据库中的所有数据库的表名
information_schema.columns: 该数据库存储了mysql数据库中的所有列的列名
=/>/>=/<=/<> 例:select 1<>2; 比较运算符(等于、大于、大于等于、小于等于、不等于)
and(&/&&/与运算)/or(|/||/或运算) 逻辑运算符(例:select true and false;)
select version() 返回MySQL数据库版本
select database() 返回当前数据库名
select user() 返回用户名
select current_user() 返回当前用户名
select system_user() 返回系统用户名
select @@datadir 返回数据库路径
select @@version_compile_os 返回操作系统版本
select length()例:select('123456'); 返回字符串的长度{例:select length(database());}
select substring() 返回截取字符串
substr()例:select substr(database(),1,1) 截取字符串{例:select substr(database(),1,1)
mid() 截取字符串
1.截取的字符串
2.截取起始位置,从1开始计数
3.截取长度
left()例:select left("123456",4); 从左侧开始取指定字符个数的字符串
concat()例: select concat('a','b','c'); 没有分隔符的连接字符串
concat_ws()例:select concat_ws("-",'a','b','c'); 含有分隔符的连接字符串
group_conat()例:select group_conat(id) from student; 连接一个组的字符串
select ord()例:select ord('a'); 返回ASCII码
select rand()例: select rand(); 返回0-1之间的随机浮点数 最近的那个整数
select left(rand(),3);
hex() 将字符串转换为十六进制
unhex() hex的反向操作
select md5() 返回MD5值
select floor(x) 返回不大于x的最大整数 向下取值
select round() 返回参数x接近的整数
load_file(文件的绝对路径) 读取文件,并返回文件内容作为一个字符串
sleep()例:select sleep(5); 睡眠时间为指定的秒数
if(true,t,f)例:select if(true,1,2); if判断
select find_in_set() 返回字符串在字符串列表中的位置
benchmark() 指定语句执行的次数
select name_const() 返回表作为结果
@逻辑运算
在SQL语句中逻辑运算与(and)比或(or)的优先级高
【select 1=2 and 1=2 or 1=1;】
注入流程:
由于关系型数据库系统,具有明显的库/表/列/内容结构层次,所以我们通过SQL注入漏洞获取数据库中信息时候,也依据这样的顺序
首先获取数据库名,其次获取表名,然后获取列名,最后获取数据。
ascii(str) : 返回给定字符的ascii值 如 ascii("a")=97
length(str) : 返回给定字符串的长度,如 length("string")=6
substr(string,start,length) 对于给定字符串string,从start位开始截取,截取length长度 ,如 substr("chinese",3,2)="in"
substr()、stbstring()、mid() 三个函数的用法、功能均一致
concat(username): 将查询到的username连在一起,默认用逗号分隔
group_concat(字段1,'*',字段2): 将字段1和字段2的数据查询到一起,中间用*连接
count(table_name) 返回表的个数
if(expr1,expr2,expr3) 如果expr1的值为true,则返回expr2的值,如果expr1的值为false,则返回expr3的值。