| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 大数据 -> 2-3字符类基础与注入基础 -> 正文阅读 |
|
[大数据]2-3字符类基础与注入基础 |
在mysql的数据类型里面,使用的最广泛,也是最常用的类型,就是字符类型,也正是因为如此,字符类型在注入攻击中也是最常用的,发挥最好的一种 1.字符类型 字符类型包括:char(固定长度字符串),varchar(可变长度字符串),binary(固定长度二进制字符串),varbinary(可变长度二进制字符串),blob(相对应保存二进制字符串类型),text(相对应保存明文的字符串,相当于文本),enum(枚举类型),set(集合类型) 接下来,通过实际的操作,给大家看一下,这些字符串类型是如何使用的 我们打开一个终端,我们输入mysql hxf 我们show tables;看一下当前有什么表 我们创建一个表,uname用un替代,char类型,3个字符,un2定义为varchar类型,也是3个字符,un3我们定义为二进制的字符串,它保存3个字符,un4,我们定义为varbinary,也是3个字符,好,我们回车,create table testc(un char(3),un2 varchar(3),un3 binary(3),un4 varbinary(3)); 接下来,我们就对这个表插入一条记录,第一个字段,我们使用hxf,我们要注意字符串要使用单引号括起来,后面的几个字段也使用hxf,回车,insert into testc values(‘hxf’,‘hxf’,‘hxf’,‘hxf’); 那我们把它select 出来看一下,select * from testc; 这样,我们就插入一条定义各种数据类型的数据,我们还可以看一下这个表,show create table testc; un是固定3个长度的字符,这就意味着,我们只插入一个字符,那么固定长度的类型,在mysql底层中,仍然以3个字节的长度来保存这个un的值,可变长度不一样,如果它是一个字符,那它保存的长度就是占了一个字节,如果是3个字节,那么保存的就是3个字节的长度,它是可变长的 相对应的,固定长度的二进制字符串,如果只有一个字节,那么在mysql存储中,它的固定长度仍然是占用了3个字节的长度,相对应的可变长度的二进制字符串,如果只有一个字节,那么存储的时候,只占一个字节,如果是3个字节,那存储所占的空间仍然是3个字节,这是字符串的特点 另外一个特点是,所有字符串在传参的时候,或者是插入数字的时候,字符串应该使用单引号括起来,字符串中的单引号起到闭合的作用,这也是我们经常利用的一个特点 我们先概括一下基本使用 2.Char和varchar, Binary和varbinary 1.保存少量字符串时使用 Char固定长度字符串 Varchar变长字符串 2.保存少量二进制字符串时使用 Binary固定长度二进制字符串 Varbinary可变长度二进制字符串 前面四种都是用于长度不长的明文字符串和二进制字符串,如果我们需要保存大量的字符串,这时候我们需要blob、text两种类型 Create table testa(uname char(10),idcard varchar(10),login binary(10),pic varbinary(10)) 我们创建testa表,所有的字段都是按照Char和varchar, Binary和varbinary来定义的 Insert into testa values(‘abc’,‘bdc’,‘abc’,‘bcd’) 插入的数据都在我们定义的范围之内 3.字符类型越界报错 我们看到我们刚才的插入都是3个字符,因为,我们希望在我们定义的范围之内插入3个字符,先插入huang,那么这里有5个字符,回车,insert into testc values(‘huang’,‘huang’,‘huang’,‘huang’); 看到有四个警告,show warnings;看一下 我们看到有un字段名,un2、un3、un4,这些都是字段名,类似这种信息,对我们开发者和产品设计者来说,都是常规的信息,但是对于有意的注入者来说,我们能得到字段名,那么是有相当的用途,我们可以通过字段名含义来推断,字段是干什么用的,表的用途是什么 这是越界报错的一个应用,我们可以概括一下 insert into testc values(‘abcdef’,‘abcdef’,‘x012345’,‘x012345’); Query OK, 1 row affected, 4 warnings (0.01 sec) 我们故意输入更长的字符串,以便在数据插入的时候,发出警告,或者报错信息 越界报错的目标是得到字段名,进而推测字段名涵义和表的功能是什么 mysql> show warnings; ±--------±-----±------------------------------------------+ | Level | Code | Message | ±--------±-----±------------------------------------------+ | Warning | 1265 | Data truncated for column ‘uida’ at row 1 | | Warning | 1265 | Data truncated for column ‘uidb’ at row 1 | | Warning | 1265 | Data truncated for column ‘uidc’ at row 1 | | Warning | 1265 | Data truncated for column ‘uidd’ at row 1 | ±--------±-----±------------------------------------------+ 4 rows in set (0.00 sec) 这些单引号包裹的就是字段名,我们的目标就是把他暴露出来,因此,这就取决于我们的程序,对这些警告信息的处理到底是怎么样的,警告信息过于普通,实际上,大多数程序,越来越聪明,可能都会把它屏蔽掉,我们可以利用它报更高级别的错误,比如类型转换错误 4.类型转换报错 其它的类型都会隐式的或强制的转换为字符类型,那么字符串的类型,又怎么会有错误呢,我们看看是怎么回事 正常的查询中,我们查询uname等于aunt,select * from users where uname=‘aunt’; 我们看到有一条记录,类似于这种,是没有问题的,但是对于我们注入者攻击而言,我们不希望输入aunt,我们看看先输入两个单引号,然后输一个等号,在输入两个单引号,我们回车,select * from users where uname=’’=’’; 我们看到这个结果,得到全集的逻辑,这个等式就是true,所以尤其在网页中,暴露出了所有的字段信息,或者所有商品的记录信息,这种情况对于我们注入攻击,获得具体的值,相当重要,甚至是敏感信息 但是这种还不是类型转换,而相当于,把数据直接转换为逻辑比较值,也就是把整个值,不是字符串,而是逻辑转换的一个比较 另外一种,我们可以把aunt,如果注入的时候,我们希望把uname转换一下,我们回车,select * from users where !uname=‘aunt’; 我们发现发生6个warnings 我们show warnings;看一下 我们看到之所以是6个,原因是,我们条件中一个aunt,剩下5个就是5条记录中的uname值,我们看到aunt,还有其它的字段名,它之所以发生错误,是因为不正确的double值 我们看到使用了逻辑非,逻辑非的结果转换之后,实际上是一个整数,而把它这个字符串转换为整数的结果,注意报错的double值 我们还可以通过一个感叹号,输入字符串试一下,我们看它的结果是什么,select !‘aunt’; 我们看到它就是一个1,1实际上就是true 这里还有1个warnings,我们可以看一下,show warnings; 我们看到这个aunt,对他进行一个转换,这就是一个报错的原理 我们概括一下 select * from users where uname=’=’; 等于号后面是两个单引号,一个等号,它这个不是字符串,而是把整个表达式,变成逻辑的一个判断,就是true,得到全集逻辑 select * from users where !uname=‘admin’; 我们希望把uname进行转换,一个转换就把它变成整数,最终的结果就是保证它发送一个整数,整数为字符串之间报错,最终的结果 目标:(1)获得字段具体值,如密码,用户名字段值。 ? (2)获得该表的所有记录 ? (3)进而推测字段涵义,表功能等 mysql> show warnings; ±--------±-----±----------------------------------------------+ | Level | Code | Message | ±--------±-----±----------------------------------------------+ | Warning | 1292 | Truncated incorrect DOUBLE value: ‘admin’ | | Warning | 1292 | Truncated incorrect DOUBLE value: ‘Chirstian’ | | Warning | 1292 | Truncated incorrect DOUBLE value: ‘Anneke’ | | Warning | 1292 | Truncated incorrect DOUBLE value: ‘Tzvetan’ | | Warning | 1292 | Truncated incorrect DOUBLE value: ‘Saniya’ | ±--------±-----±----------------------------------------------+ 5 rows in set (0.00 sec) 类似于上面就是爆出来的字段具体值是什么,这是长度不长的字符类型 5.Text和blob Text 保存明文较大文本 Blob保存较大的二进制数据时使用 往往是在post传参的时候,有发挥的余地 Text类型最大的应用是留后门脚本注入到web服务器,其它字符类型因长度原因难以发挥。 Insert into testc(blog) values(‘gogogo’) 所以我们在post传参的时候,往往传入的是,类似上面的那种,如果插入的时候,我们就会把这个脚本放到里面去,在后面条件适当的时候,我们在select到web服务器指定目录下,这样,我们就能实现留后门的结果 6.enum和set 在注入攻击中,使用最广泛的是集合类型 Enum:枚举类型,值只能是enum中的一个 Set:集合类型,值可以是set中的任意个 我们通过具体的操作给大家演示一下 我们可以创建一个表叫,teste表,uname1,我们就用enum,enum是a,b,c,包含了3个元素 uname2,我们用集合set,同样,它也包括a,b和c,我们回车,create table teste(uname1 enum(‘a’,‘b’,‘c’),uname2 set(‘a’,‘b’,‘c’)); show create table看一下这个表,show create table teste; 我们看到这个表,enum枚举类型,枚举类型的含义,就是后边有3个元素,插入数据的时候,只允许,选择后边所列举元素的三种元素中的其中一个,不能是两个,也不能是3个,也不能在这里列举之外的值 集合类型相对应的,也是只能选泽所列举的元素,但是跟枚举类型的区别是,可以选泽1个甚至多个,但是不能选泽所列举元素之外的值 我们插入一条记录看一下,insert into teste表,values,第一个我们输a,第二个我们输a、b,我们回车,insert into teste values(‘a’,‘a,b’); 我们select出teste表,看一下,select * from teste; 我们看到这里是插入了a,这里是插入了a、b 那我们就插入一个不在列表中的呢,我们看看,insert into teste values(‘d’,‘b,d’); kali的mysql报错了,我在这里用别人的图片 我们看到发出了两个警告信息,这个警告信息是因为第一个不存在,第二个d也不存在,我们在select出来,select * from teste; 这里也是用别人的照片 我们发现如果不存在,我们插入的是空,第二个,如果存在b插入,不存在的d是不插入的 我们在插入一条,insert into teste values(‘b’,‘c’); 我们在看一下,select * from teste; 类似这种情况,如何查找出集合中有b元素的记录呢 查找集合,我们使用一个函数,叫find_in_set(),查找b元素,从uname2查找,我们看看结果是怎么样的,select * from teste where find_in_set(‘b’,uname2); 我们看到uname2中,第一条,第二条都有b的记录 如果我们把a元素的查找出来,select * from teste where find_in_set(‘a’,uname2); 这个时候,我们查找到只有一条记录,类似于find_in_set(),这种函数的应用,对于我们注入攻击有什么启示呢 我们演示一下 正常的程序查询,比如users,select * from users where uname=‘aunt’; 我们看到这是正常的,没有什么问题,那么后面就是我们注入者,所注入的内容,我们注入一个find_in_set(),find_in_set()目标,我们想知道当前的用户名,它的第一个字符是什么,取用户名最左边的一个字符,1,取出来之后,它在这个集合里面,比如s、t、u、r,我们输入4个字符,假如它等于4,我们看一下它的结果,select * from users where uname=‘aunt’ and find_in_set(left(user(),1),‘s,t,u,r’)=4; 因为r处在第四个位置,所以它是4,这对于我们网页猜测来说,相当重要,因为它等于1,网页显示是不正常的,select * from users where uname=‘aunt’ and find_in_set(left(user(),1),‘s,t,u,r’)=1; 因为返回的集合中是空,只有输入4的时候,网页正常了 这就验证了用户名,最左边一位是r,而我们连接数据库的用户名是root,所以没有错 我们打开一个网页来实际注入,我们看一下是如何应用的 我们看一下这个网页 这个是正常的,我们看到图片和商品都是正常的 我们注入一下,我们希望输入find_in_set(),用户名最左边的一个字符,然后我们在s,t,x,y,z,我们在这里面字符中,等于那个呢,我们一个个猜,and find_in_set(left(user(),1),‘s,t,x,y,z’)=1 我们看到网页显示的并不正常,没有任何商品 一直输入到5,and find_in_set(left(user(),1),‘s,t,x,y,z’)=5 这个网页显示正常,那么就说明当前连接数据库的用户名的第一个字符,应该是z 这是对我们用户名的猜测起到验证的作用 我们概括一下 Find_in_set()在盲注中的应用: Select * from users where uname=’$uname’ and find_in_set(left(uname,1) ,‘a,b,c’)=1 find_in_set取得uname中的第一个字母,在abc中是等于几,如果是第一个说明是a Select * from users where uname=’$uname’ and find_in_set(left(version(),1) , ‘1,2,3,4,5,6’)>1 因此,在网页中,我们通常是通过find_in_set把版本或者用户名取出来,逐个的进行判断 7.小结 1.字符类型基础 2.字符类型越界报错 3.字符类型转换报错 4.留后门应用原理 5.find_in_set注入应用 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 14:29:44- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |