在 OWASP Juice Shop 中登录注入

在 OWASP Juice Shop 中登录注入


目录

  1. 引言:什么是“登录注入”(SQL Injection)
  2. 为什么 '' OR '1'='1' 有时“不好使”?(以 Juice Shop 为例)
  3. 演示:不安全的登录实现(说明为什么会被利用)
  4. 安全实现:参数化查询与 ORM 的正确用法(含示例代码)
  5. 在 Juice Shop 上调试与验证(新手可跟着做)
  6. 常见误区与注意事项
  7. 总结
  8. 参考与延伸阅读
  9. 具体操作

1. 引言:什么是“登录注入”

SQL 注入(SQL Injection) 是一种经典的 Web 漏洞:攻击者把恶意的 SQL 片段当作输入,服务器把它拼入 SQL 语句后执行,从而实现绕过认证、读取或修改数据库等行为。

举例(理论上):

  • 表单里把 email 填成 anything' OR '1'='1
  • 若后台直接拼接字符串生成 SQL:
    SELECT * FROM Users WHERE email = 'anything' OR '1'='1' AND password = '...';
    
    因为 '1'='1' 永远为真,查询可能返回第一条记录,实现“绕过登录”。

2. 为什么 '' OR '1'='1' 有时“不好使”?(以 Juice Shop 为例)

如果在 Juice Shop 中输入传统的 '' OR '1'='1' 类 payload,却得到错误 SQLITE_ERROR: unrecognized token 或登录失败,那通常说明:

  • 后台没有直接拼接原始 SQL 字符串,而是使用了参数化查询ORM(如 Sequelize),这些做法会把用户输入当成数据而不是 SQL 代码,从而阻止经典注入方法。
  • 报错 unrecognized token 多半表示 SQL 在解析时碰到语法问题(例如字符串引号未正确配对),而不是“注入成功”。

总结:现代应用通常采用更安全的数据绑定方式,所以老方法在这类环境里常常无效或被拦截。


3. 演示:不安全的登录实现(仅用于说明)

下面演示一个非常不安全的做法,目的是帮助理解为什么会被利用。

Node.js(不安全示例)

// 非常不安全的写法:直接把用户输入拼接到 SQL
app.post('/login', async (req, res) => {
  const email = req.body.email;
  const password = req.body.password;

  const sql = `SELECT * FROM Users WHERE email = '${email}' AND password = '${password}'`;
  const row = db.get(sql); // 假设 db.get 能执行 SQL 并返回行

  if (row) {
    req.session.user = row;
    res.send('登录成功');
  } else {
    res.send('账号或密码错误');
  }
});
  • 如果 emailanything' OR '1'='1,拼接后 SQL 的结构被破坏,攻击者可能借此绕过认证。
  • 这是拼接字符串生成 SQL的典型易被利用场景。

4. 安全实现(防护示例) — 参数化查询 & ORM

4.1 参数化查询(以 sqlite3 为例)

参数化查询把用户输入作为“数据”,不会改变 SQL 的语法结构,从而防止注入。

const sqlite3 = require('sqlite3').verbose();
const db = new sqlite3.Database('mydb.sqlite');

app.post('/login', (req, res) => {
  const { email, password } = req.body;

  // 使用 ? 占位符,并把参数作为数组传入
  const sql = `SELECT * FROM Users WHERE email = ? AND password = ?`;
  db.get(sql, [email, password], (err, row) => {
    if (err) {
      res.status(500).send('服务器错误');
      return;
    }
    if (row) {
      req.session.user = row;
      res.send('登录成功');
    } else {
      res.send('账号或密码错误');
    }
  });
});

注释说明

  • ? 是占位符,数据库驱动会把 emailpassword 当作数据安全插入,而不是拼接成 SQL 片段。
  • 即便用户输入包含 ' OR 1=1 -- 之类的文本,也只会被当成字符串数据,不会改变 SQL 的逻辑。

4.2 使用 ORM(Sequelize)示例

ORM 常常提供更高层的接口,且内部默认做参数绑定。

// 假设已定义 User 模型
const { User } = require('./models');

app.post('/login', async (req, res) => {
  const { email, password } = req.body;

  try {
    // ORM 的 where 子句会安全地把值当作参数
    const user = await User.findOne({ where: { email: email, password: password } });

    if (user) {
      req.session.user = user;
      res.send('登录成功');
    } else {
      res.send('账号或密码错误');
    }
  } catch (err) {
    res.status(500).send('服务器错误');
  }
});

5. 在 Juice Shop上调试与验证

前提:在 Juice Shop 实例的练习环境中操作。

步骤 1:打开浏览器开发者工具(Network 面板)

  • 填入想测试的 emailpassword,点击登录。
  • 切换到 Network → 找到 /rest/user/login(或相关请求)→ 查看 Request Payload
    • 会看到发送的 JSON,例如:
      { "email": "' OR 1=1--", "password": "123" }
      

步骤 2:观察响应与控制台错误

  • 如果后端返回 SQLITE_ERROR: unrecognized token:说明在底层 SQL 的解析阶段出现语法错误(可能是引号不匹配或非法字符)。
  • 如果后端返回 Invalid email or password:说明查询执行但未匹配到任何用户(注入未成功)。

步骤 3:尝试不同 payload

  • 常见尝试(请在 Juice Shop 本地环境中试验):
    • admin'--
    • admin' OR '1'='1
    • URL 编码版本:%27%20OR%201%3D1--
  • 在使用 ORM 时,传统 payload 常常失效或报错;Juice Shop 的多个关卡设计了不同的防护或故意弱点,所以需要有针对性地尝试。

步骤 4:注意错误栈和提示

  • 如果错误堆栈里出现 Sequelize,说明应用通过 ORM 操作数据库,经典注入方式往往被阻止。
  • 如果错误堆栈里直接出现 SQL 语句字符串,说明可能存在拼接 SQL 的风险区域(但仍需谨慎判断)。

6. 常见误区与注意事项

  • 误区:所有网站都能用 OR 1=1 绕过
    事实:现代应用广泛使用参数化查询或 ORM,经典 payload 很多时候不起作用。
  • 误区:出现 SQLITE_ERROR 就是成功注入
    事实:这是 SQL 解析错误,说明 payload 形成了非法 SQL 语法,而不是注入成功。
  • 误区:学会注入就能“入侵任何站点”
    事实:未经授权的测试是违法的;学习仅限靶场/授权范围内。
  • 防护要点
    1. 使用参数化查询 / ORM(安全绑定参数)。
    2. 密码使用强哈希(bcrypt/argon2),不要明文保存。
    3. 对输入做最小必要的校验(白名单优先),但不要把校验当作惟一防线。
    4. 使用安全审计与 WAF 作为补充手段。

7. 总结

  • 你在 Juice Shop 中尝试的 ' OR '1'='1' 类 payload 无效,极可能因为后端使用了 ORM(Sequelize)或参数化查询,这些会把输入当成数据而非 SQL 代码。
  • 出现 SQLITE_ERROR: unrecognized token 多为语法/解析问题,而不是注入成功。
  • 进行安全测试时,应先理解目标应用如何构造 SQL(拼接 vs 参数化 vs ORM),然后选择合适的测试策略。
  • 始终在被授权的环境中学习并遵守法律与道德规范。

8. 参考与延伸阅读

  • OWASP SQL Injection — https://owasp.org/www-project-top-ten/ (请在浏览器中搜索“OWASP SQL Injection”)
  • OWASP Juice Shop 官方仓库与文档(查看其挑战说明和源码)
  • 关于密码存储:bcrypt / argon2 文档

9. 具体操作

输入

`

发现报错显示了SQL语句,说明email输入框存在SQL注入漏洞

截屏2025-10-16 05.41.44

输入

' OR 1=1--

截屏2025-10-16 05.42.15
结果

截屏2025-10-16 05.43.00

posted @ 2025-10-16 05:57  Yu_OvO  阅读(23)  评论(0)    收藏  举报