2-Mysql注入

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.schemata
  • information_schema下面的所有数据库名所在的表
  • SHOW DATABASES;命令从这个表获取数据
    • schema_name:#该表下的数据库名字段名
+--------------------+----------------------------+
| SCHEMA_NAME        | DEFAULT_CHARACTER_SET_NAME |
+--------------------+----------------------------+
| information_schema | utf8                       |
| challenges         | gbk                        |
| mysql              | latin1                     |
| performance_schema | utf8                       |
| security           | gbk                        |
+--------------------+----------------------------+
information_schema.tables
  • 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.columns
  • information_schema下面所有的列名所在的表,包括表有多少列、每个列的类型等
  • SHOW COLUMNS FROM schemaname.tablename 命令从这个表获取结果。
    • table_name:#该表下的表名字段名
    • column_name:#该表下的列名字段名
    • table_schema:#该表下的数据库名字段名
+---------------+--------------------+----------------+
| TABLE_CATALOG | TABLE_SCHEMA       | TABLE_NAME     |
+---------------+--------------------+----------------+
| def           | information_schema | CHARACTER_SETS |

+---------------+--------------------+----------------+???
information_schema.user_priviliges???
  • 用户权限表。内容源自 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相当于引号。
posted @ 2025-03-27 21:36  micryfotctf  阅读(28)  评论(0)    收藏  举报