【juice-shop】★★ Login Admin:SQL 注入绕过登录

通过 SQL 注入攻击绕过登录验证,使用 OR true 和 SQL 注释(--)成功登录管理员账户。

【juice-shop】★★ Login Admin:SQL 注入绕过登录

0x01 任务简报

💡 核心线索 (Hints)
1. 挑战说明可能已经透露了你应该采取何种形式进行攻击。
2. 若您恰巧已知晓管理员的电子邮箱地址,便可发起定向攻击。
3. 即使你对管理员邮箱地址一无所知,专用的攻击模式也可能让你走运。
4. 若已获取管理员密码哈希值,你当然可以尝试直接攻击该哈希值,而非使用 SQL 注入攻击。
5. 或者,您也可以将此挑战与以下挑战组合解决:使用管理员用户凭据登录(无需事先更改凭据)或应用 SQL 注入挑战。

0x02 前置条件

未登录


0x03 实战:复现漏洞

🔑 第一步:访问登录页面

通过"账户"菜单转到"登录"页面。

登录页面

🧪 第二步:探测 SQL 注入入口

为了绕过正常的登录流程,尝试使用 SQL 注入(SQLi)攻击。

对于简单的 SQL 注入而言,一个好的切入点是插入引号(如 '")。这些引号会扰乱不安全的拼接式查询的语法结构。

在电子邮件字段中输入 ',在密码字段中输入任意内容,点击登录按钮。

SQL 语法错误反馈

你会看到顶部的红色 [objectObject] 错误。检查浏览器网络标签页中的 500 响应,会发现包含 SQLITE_ERROR 错误信息以及完整 SQL 查询的提示信息。

网络标签页中的完整错误信息

💉 第三步:构造逻辑绕过语句

尝试在电子邮件字段中输入 ' OR true,再次点击登录按钮。

尝试 OR true 语句

查询仍然无效。从 HTTP 响应中的新错误可以看出,语句结构仍然不完整。

OR true 语句仍然存在语法错误

🔐 第四步:使用 SQL 注释绕过

在 SQLite 数据库中,可以使用 -- 来注释掉后续内容。

在电子邮件字段中输入 ' OR true--

使用 SQL 注释完成注入

✅ 第五步:成功登录

按下回车后成功登录管理员账户,挑战完成。

登录成功


0x04 编码挑战

🔍 找到它(15 行)

漏洞代码位置

修复它

原始漏洞代码

1
models.sequelize.query(`SELECT * FROM Users WHERE email = '${req.body.email || ''}' AND password = '${security.hash(req.body.password || '')}' AND deletedAt IS NULL`, { model: UserModel, plain: true })

攻击场景演示

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
用户输入:
  email = "' OR true--"
  password = "anything"

生成的 SQL:
SELECT * FROM Users 
WHERE email = '' OR true--' AND password = '...' AND deletedAt IS NULL

执行结果:
- OR true 使条件恒为真
- -- 注释掉后续的 AND password 条件
- 返回第一个用户(通常是 admin)
- 认证绕过成功

🛠️ 修复方案对比

方案 修复方式 安全性 评价
fix1 参数化查询 + hash 在绑定 ✅ 安全 正确但冗余
fix2 参数化查询 + hash 在 SQL ❌ 不安全 错误
fix3 黑名单过滤 ❌ 极不安全 错误
fix4 参数化查询 + hash 在绑定 ✅ 安全 最优

✅ 正确修复(fix4)

1
2
models.sequelize.query(`SELECT * FROM Users WHERE email = $1 AND password = $2 AND deletedAt IS NULL`,
  { bind: [ req.body.email, security.hash(req.body.password) ], model: models.User, plain: true })

核心原理:

  • $1, $2 占位符告诉数据库这是数据,不是 SQL 代码
  • bind 数组中的值被视为纯数据,不被解析为 SQL 语法
  • 即使输入 ' OR true--,也只被当作字符串值处理
  • SQL 注入被彻底阻止
使用 Hugo 构建
主题 StackJimmy 设计