bhadramenon/OWASP-SQL-Injection
GitHub: bhadramenon/OWASP-SQL-Injection
一个基于 OWASP Juice Shop 的 SQL 注入实战教程,演示如何利用注入漏洞绕过身份认证并给出修复方案。
Stars: 1 | Forks: 0
# SQL 注入:绕过 OWASP Juice Shop 的身份验证
**OWASP 类别:** A03:2025 – 注入
**难度:** 初级
**实验环境:** Kali Linux + Docker + OWASP Juice Shop
**日期:** 2026 年 6 月 19 日
**状态:** ✅ 已完成
## 🎬 视频演示
https://github.com/user-attachments/assets/0bd87eac-d906-4a6c-b1bb-2c5515ee7e9f
*观看完整的漏洞利用过程:登录页面 → SQL 注入 payload → 成功以 admin 身份登录 → Dev Tools 的 network 标签页*
## 🎯 我学到了什么
在此之前,我一直认为 Web 应用程序仅仅是“加载页面”。现在我明白了:
- Web 页面会发送**多个 API 调用**(不仅仅是一个请求)
- 每个 API 调用都会处理**用户输入**(例如邮箱和密码)
- 如果该 API 没有正确验证输入,就会**存在漏洞**
- 当 API 使用**直接拼接用户输入**的方式构建 SQL 查询时,就会发生 SQL 注入
我之前分析过的用于网络调用的同一个 `/api/login` endpoint 也容易受到 SQL 注入的攻击。
## 📋 前置条件
- Kali Linux(或任何安装了 Docker 的 Linux 系统)
- 已安装 Docker
- 用于克隆仓库的 Git
## 🏗️ 环境搭建
### 第一步:安装 Docker
```
sudo apt update
sudo apt install docker.io
```
### 第二步:运行 Juice Shop
```
sudo docker run --rm -p 3000:3000 bkimminich/juice-shop
```
### 第三步:访问 Juice Shop
打开浏览器并访问:`http://localhost:3000`
## 🔍 理解漏洞
### 在 API 层面发生了什么
当你在网站上点击“登录”时:
1. 你的浏览器会向 `/api/login` 发送一个 **POST 请求**
2. API 会接收你的**邮箱和密码**
3. API 会构建一个 **SQL 查询**来检查你是否有效
4. API 会返回一个**响应**(成功或失败)
**漏洞所在:** API 在构建该 SQL 查询时,使用了与你输入内容进行的**字符串拼接**。
```
// VULNERABLE CODE:
const query = `SELECT * FROM Users WHERE email = '${email}' AND password = '${password}'`;
```
当你输入 `admin' OR '1'='1'--` 时,它就会成为 SQL 查询的一部分。
## 🎯 漏洞利用步骤
### 第一步:导航至登录页面
点击右上角的 **Login** 按钮。
### 第二步:分析请求(理解 API)
1. 按 `F12` 打开 Dev Tools
2. 点击 **Network** 标签页
3. 清除之前的日志
4. 输入测试凭证:`email=test@test.com`, `password=test`
5. 点击 Login
6. 点击 `/api/login` 请求
7. 检查 **Request** → 查看参数:`email` 和 `password`
**我学到了:** 登录表单向 `/api/login` 发送了一个 POST 请求,其中包含带有邮箱和密码的 JSON 数据。
### 第三步:注入 SQL Payload
**邮箱字段:**
admin' OR '1'='1'--
**密码字段:**
test123
**点击 Login**
### 第四步:成功!
- 在不知道密码的情况下以 **admin** 身份登录!✅
- 检查你的个人资料(右上角)→ 显示 "admin@juice-shop.com"
### 第五步:使用 Dev Tools 验证
1. 再次打开 Network 标签页(`F12`)
2. 使用 payload 点击 Login
3. 点击 `/api/login` 请求
4. 检查 **Response** → 应该显示:
```
{
"email": "admin@juice-shop.com",
"userId": 1,
"token": "eyJhbGciOi..."
}
```
**这是我之前分析过的同一个 API 调用,但现在我明白了当它存在漏洞时会发生什么!**
## 💡 SQL 查询原理解析
### 正常查询(注入前):
```
SELECT * FROM Users WHERE email = 'john@example.com' AND password = 'secret123'
```
**数据库评估:**
- `email = 'john@example.com'` → ❌ FALSE(错误的邮箱)
- `AND password = 'secret123'` → ❌ FALSE(错误的密码)
- **结果:** FALSE → 登录失败 ❌
### SQL 注入后:
```
SELECT * FROM Users WHERE email = 'admin' OR '1'='1'--' AND password = 'test123'
```
**在 `--` 注释之后(其余部分被忽略):**
```
SELECT * FROM Users WHERE email = 'admin' OR '1'='1'
```
**数据库评估:**
- `email = 'admin'` → ❌ FALSE
- `OR 1=1` → ✅ TRUE(1 永远等于 1!)
- **结果:** TRUE → 作为 admin 登录成功!✅
## 🔍 Payload 各部分的作用原理
| 部分 | 作用 |
|------|---------|
| `admin` | 专门针对 admin 用户 |
| `'` | 闭合邮箱字符串(至关重要!) |
| `OR` | 逻辑 OR 运算符 |
| `1=1` | 永远为 TRUE 的条件 |
| `--` | SQL 注释(忽略密码检查) |
## 🆚 SQL 注入 vs 暴力破解
| 方面 | SQL 注入 | Hydra 暴力破解 |
|------------- |----------------------------|------------------------------ |
| **方式** | 篡改 SQL 查询逻辑 | 猜测密码 |
| **尝试次数** | 1 次尝试(瞬间完成)⚡ | 100-1000 次尝试(缓慢)🐢 |
| **绕过机制** | 完全绕过密码检查 | 如果存在弱密码则有效 |
| **检测难度** | 较难(单次请求) | 容易(大量请求) |
## 🛡️ 如何修复
### 1. 使用参数化查询(预编译语句)
```
// ❌ VULNERABLE:
const query = `SELECT * FROM users WHERE email = '${email}'`;
// ✅ SECURE:
const query = 'SELECT * FROM users WHERE email = ?';
db.execute(query, [email]);
```
**原理:** `?` 占位符告诉数据库将输入视为数据,而不是 SQL 代码。
### 2. 输入验证
- 在处理之前验证邮箱格式
- 拒绝包含 SQL 字符(`'`, `"`, `;`, `--`)的输入
### 3. 使用 ORM 框架
- Sequelize、TypeORM、SQLAlchemy 可以安全地处理查询
- 自动使用参数化查询
## 🔍 查找漏洞代码
由于 Juice Shop 是开源的,我克隆了它以查看实际的漏洞代码:
```
git clone https://github.com/juice-shop/juice-shop.git
cd juice-shop
grep -rn "SELECT.*FROM.*email.*password" .
```
**位于:** `src/routes/login.ts` 第 34 行
**存在漏洞的代码:**
```
models.sequelize.query(
`SELECT * FROM Users WHERE email = '${email}' AND password = '${password}' AND deletedAt IS NULL`,
{ type: models.sequelize.QueryTypes.SELECT }
)
```
**问题:** 字符串拼接(`${email}`)导致了 SQL 注入!
## 🚀 下一步计划
这是学习 OWASP Top 10 的第 2 天。我正在逐步建立我的理解:
- **第 1 天:** 了解 Web 应用网络交互(HTTP 请求,API 调用)
- **第 2 天:** 在 API 调用中利用 SQL 注入
- **下一步:** DOM XSS(跨站脚本攻击)- 同样属于 A03:2025 注入
**作者:** Bhadra Menon
**学习之旅:** 记录我的网络安全之路
**GitHub:** https://github.com/bhadramenon
**LinkedIn:** https://www.linkedin.com/in/bhadra-menon/
*如果你也在学习网络安全,欢迎与我联系!我喜欢分享我学到的东西,也很乐意倾听别人的学习历程。*
### 第四步:成功!
- 在不知道密码的情况下以 **admin** 身份登录!✅
- 检查你的个人资料(右上角)→ 显示 "admin@juice-shop.com"
### 第五步:使用 Dev Tools 验证
1. 再次打开 Network 标签页(`F12`)
2. 使用 payload 点击 Login
3. 点击 `/api/login` 请求
4. 检查 **Response** → 应该显示:
```
{
"email": "admin@juice-shop.com",
"userId": 1,
"token": "eyJhbGciOi..."
}
```
**这是我之前分析过的同一个 API 调用,但现在我明白了当它存在漏洞时会发生什么!**
## 💡 SQL 查询原理解析
### 正常查询(注入前):
```
SELECT * FROM Users WHERE email = 'john@example.com' AND password = 'secret123'
```
**数据库评估:**
- `email = 'john@example.com'` → ❌ FALSE(错误的邮箱)
- `AND password = 'secret123'` → ❌ FALSE(错误的密码)
- **结果:** FALSE → 登录失败 ❌
### SQL 注入后:
```
SELECT * FROM Users WHERE email = 'admin' OR '1'='1'--' AND password = 'test123'
```
**在 `--` 注释之后(其余部分被忽略):**
```
SELECT * FROM Users WHERE email = 'admin' OR '1'='1'
```
**数据库评估:**
- `email = 'admin'` → ❌ FALSE
- `OR 1=1` → ✅ TRUE(1 永远等于 1!)
- **结果:** TRUE → 作为 admin 登录成功!✅
## 🔍 Payload 各部分的作用原理
| 部分 | 作用 |
|------|---------|
| `admin` | 专门针对 admin 用户 |
| `'` | 闭合邮箱字符串(至关重要!) |
| `OR` | 逻辑 OR 运算符 |
| `1=1` | 永远为 TRUE 的条件 |
| `--` | SQL 注释(忽略密码检查) |
## 🆚 SQL 注入 vs 暴力破解
| 方面 | SQL 注入 | Hydra 暴力破解 |
|------------- |----------------------------|------------------------------ |
| **方式** | 篡改 SQL 查询逻辑 | 猜测密码 |
| **尝试次数** | 1 次尝试(瞬间完成)⚡ | 100-1000 次尝试(缓慢)🐢 |
| **绕过机制** | 完全绕过密码检查 | 如果存在弱密码则有效 |
| **检测难度** | 较难(单次请求) | 容易(大量请求) |
## 🛡️ 如何修复
### 1. 使用参数化查询(预编译语句)
```
// ❌ VULNERABLE:
const query = `SELECT * FROM users WHERE email = '${email}'`;
// ✅ SECURE:
const query = 'SELECT * FROM users WHERE email = ?';
db.execute(query, [email]);
```
**原理:** `?` 占位符告诉数据库将输入视为数据,而不是 SQL 代码。
### 2. 输入验证
- 在处理之前验证邮箱格式
- 拒绝包含 SQL 字符(`'`, `"`, `;`, `--`)的输入
### 3. 使用 ORM 框架
- Sequelize、TypeORM、SQLAlchemy 可以安全地处理查询
- 自动使用参数化查询
## 🔍 查找漏洞代码
由于 Juice Shop 是开源的,我克隆了它以查看实际的漏洞代码:
```
git clone https://github.com/juice-shop/juice-shop.git
cd juice-shop
grep -rn "SELECT.*FROM.*email.*password" .
```
**位于:** `src/routes/login.ts` 第 34 行
**存在漏洞的代码:**
```
models.sequelize.query(
`SELECT * FROM Users WHERE email = '${email}' AND password = '${password}' AND deletedAt IS NULL`,
{ type: models.sequelize.QueryTypes.SELECT }
)
```
**问题:** 字符串拼接(`${email}`)导致了 SQL 注入!
## 🚀 下一步计划
这是学习 OWASP Top 10 的第 2 天。我正在逐步建立我的理解:
- **第 1 天:** 了解 Web 应用网络交互(HTTP 请求,API 调用)
- **第 2 天:** 在 API 调用中利用 SQL 注入
- **下一步:** DOM XSS(跨站脚本攻击)- 同样属于 A03:2025 注入
**作者:** Bhadra Menon
**学习之旅:** 记录我的网络安全之路
**GitHub:** https://github.com/bhadramenon
**LinkedIn:** https://www.linkedin.com/in/bhadra-menon/
*如果你也在学习网络安全,欢迎与我联系!我喜欢分享我学到的东西,也很乐意倾听别人的学习历程。*标签:CISA项目, MITM代理, OPA, Web安全, 多线程, 网络安全, 蓝队分析, 请求拦截, 隐私保护, 靶场