挖到项目中的 2 高危和中危漏洞
我正在参加 CodeBuddy「首席试玩官」内容创作大赛,本文所使用的 CodeBuddy 免费下载链接:腾讯云代码助手 CodeBuddy - AI 时代的智能编程伙伴
你好,我是悟空。
一、背景
公司对系统安全非常中试,每个项目上线前都会做渗透测试和众测,如果在众测期间发现一个高危漏洞,就会奖励 5000 块奖金给发现该漏洞的同学。真的非常诱人啊!以至于有很多人晚上熬夜挖洞,有的一次就能挖几万块。
所以在做众测前, 我们都会对代码进行走查,看看有没有安全漏洞。
如果系统中的接口代码写得不严谨,就会造成很多安全漏洞,比如 SQL 注入漏洞、XSS 存储型漏洞。
本篇是工作中遇到的两个真实漏洞案例:
乙方的系统中存在 SQL 注入漏洞,高危漏洞,我提前发现了。如果是我们自己的项目在众测阶段发现 SQL 注入漏洞,那就是 5000 块奖金了。
我们的某个产品在众测阶段被报出 XSS 存储型漏洞,中危漏洞,奖金 2000 块,实打实发放提交人手中。
因为项目中有很多接口需要进行走查,排查起来是非常耗时的,这次我们来通过两个案例来演示如何借助 CodeBuddy 代码助手(一款 AI 工具)快速发现漏洞以及如何解决漏洞的。
二、IDEA 安装 CodeBuddy 插件。
还是熟悉的配方,熟悉的味道,在 IDEA 中搜索 CodeBuddy 插件安装。安装完成后重启 IDEA,然后登录 CodeBuddy 插件就可以开始使用了。

三、真实案例一:SQL 注入漏洞
3.1 全面分析代码中可能存在的漏洞
首先把乙方系统的后端代码文件喂给 CodeBuddy,让它帮我们分析该文件是否有安全漏洞,结果真的有安全漏洞。

CodeBuddy 会从以下几个方面开始分析:
SQL 注入漏洞
权限控制问题
输入验证
敏感数据处理
资源管理
异常处理
经过代码审查,CodeBuddy 发现了几个严重的安全漏洞:
SQL 注入漏洞(严重):
输入验证不足:
异常处理问题:
其他问题:
SQL 语句中的表名"order"是 SQL 关键字,可能导致语法错误
没有进行适当的权限验证
没有使用预编译语句

3.2 分析 SQL 注入漏洞
这次我们重点来分析 SQL 注入漏洞。CodeBuddy 找到这一段代码是有问题的。

CodeBuddy 还给出了 SQL 注入的原因:直接将用户输入拼接到 SQL 语句中,容易受到 SQL 注入攻击。
漏洞详情:代码直接将用户输入的updateTime
参数拼接到 SQL 查询语句中,没有进行任何参数验证或使用预编译语句。
攻击示例:
' OR '1'='1
- 可能返回所有记录
'; DROP TABLE bd_material; --
- 可能删除整个表
'; UPDATE bd_material SET dr=1; --
- 可能篡改数据

最后 CodeBuddy 给出了修复建议:
使用预编译语句(Prepared Statement)防止 SQL 注入。修复后的代码如下:
那为什么这段代码就能解决 SQL 注入的问题呢?
3.3 预编译语句如何防止 SQL 注入
预编译语句(Prepared Statement)如何防止 SQL 注入,以及为什么这种方式与直接字符串拼接有本质的区别?
带着这个问题,我们继续往下看:
预编译语句的工作流程
字符串拼接 vs 预编译语句
预编译实际例子说明
安全性保证
性能优势
3.3.1 预编译语句的工作流程
3.3.1.1 预编译阶段
数据库先收到 SQL 语句模板,其中包含占位符?
;
数据库会预先编译这个 SQL 语句,生成执行计划;
此时 SQL 的结构已经确定,不会再改变;
3.3.1.2 参数绑定阶段
参数值作为数据传递给数据库
数据库将这些值严格作为数据处理,而不是 SQL 语句的一部分
即使参数中包含 SQL 关键字或引号,也只会被当作普通字符串处理
3.3.2 字符串拼接 vs 预编译语句
3.3.2.1 接字符串拼接(不安全)
这种方式中,SQL 语句和参数值在发送到数据库之前就完成了拼接。如果用户输入是:
最终的 SQL 语句会变成:
这样就改变了原始 SQL 的逻辑,造成了注入。
3.3.2.2 预编译语句(安全)
3.3.3 预编译实际例子说明
假设用户输入恶意数据:2023-01-01' OR '1'='1
3.3.3.1 使用预编译语句时
解释如下:
整个输入被当作一个字符串值处理
特殊字符会被自动转义
SQL 注入攻击失败
3.3.4 安全性保证
预编译语句提供三重保护:
语句结构固定:SQL 语句结构在参数绑定前就已确定
参数隔离:参数值与 SQL 语句完全分离处理
自动转义:特殊字符自动进行安全处理
3.3.5 性能优势
除了安全性,预编译语句还有性能优势:
SQL 语句只需编译一次
可重复使用执行计划
减少数据库解析负担
因此,使用预编译语句不仅是安全性的需求,也是性能优化的最佳实践。
四、真实案例二:XSS 存储型漏洞
4.1 一个陌生的名字
XSS 存储型漏洞,估摸着很多同学都没有听过,这里简单给大家解释下。
XSS 攻击:跨站脚本攻击(Cross Site Scripting),为不和前端层叠样式表(Cascading Style Sheets)CSS 混淆,故将跨站脚本攻击缩写为 XSS。
**XSS(跨站脚本攻击)**是指恶意攻击者往 Web 页面里插入恶意 Script 代码,当用户浏览该页时,嵌入其中 Web 里面的 Script 代码会被执行,从而达到恶意攻击用户的目的。类似于 sql 注入。是目前最普遍的 Web 应用安全漏洞,也是 Web 攻击中最常见的攻击方式之一。
4.2 XSS 分类
4.2.1 存储型 XSS
存储型跨站脚本攻击也称为持久型跨站脚本攻击,是一种最具破坏性的跨站脚本攻击。注入的脚本永久存储在 Web 服务器上,如数据库、内存或文件系统中。只要注入脚本代码没有被清理,每次用户访问网页时都将加载恶意脚本。
原理如下图所示:

存储型跨站脚本攻击一般发生在论坛、博客、留言板等允许用户共享内容的网站,如果网站存在漏洞,未严格校验用户输入内容就可能被攻击者利用。攻击者利用发帖、评论、修改个人信息等功能提交恶意脚本代码到 Web 服务器进行保存,那么只要访问对应网页的用户都会在不知情的情况下读取恶意脚本。
相对于反射型跨站脚本攻击,存储型跨站脚本攻击影响范围更大,危及所有访问者。当然这种攻击方式也更难执行,攻击者需要找到可以利用的漏洞。
4.2.2 反射型 XSS
反射型跨站脚本攻击是最常见和最简单的攻击形式。所谓反射,是指此种类型的注入脚本必须被包含在发往 Web 服务器的请求中,然后 Web 服务器以某种方式反射到用户浏览器执行。也就是注入脚本作为客户端的请求提交给 Web 服务器,服务器解析后在响应消息中返回脚本由浏览器执行。因此攻击者需要使用钓鱼邮件、弹窗链接以及其他社会工程学方法引诱用户点击链接向 Web 服务器发出请求。
原理如下图所示:

攻击者往往在合法的 URL 末尾添加恶意代码构造链接,例如:
用户点击此链接后,因为浏览器信任该网站,将执行恶意脚本代码。
从以上介绍可以看出,这种攻击类型 Web 服务器端无需存储注入脚本,直接通过 HTTP GET 或 POST 请求就可以完成攻击,实施比较简单。但是这种攻击方式需要由每个受害者触发才能发生攻击,往往也称为非持久型跨站脚本攻击。
4.2.3 DOM 型 XSS
DOM 型 XSS,是指攻击者在客户端对 DOM 中文档节点的属性、触发事件等进行修改以添加恶意 JavaScript 脚本,并使脚本在本地浏览器中执行。整个过程中没有服务器的参与,因此,DOM 型 XSS 漏洞是一个纯客户端的安全漏洞。
原理如下图所示:

基于 DOM 的跨站脚本攻击与反射型、存储型跨站脚本攻击有很大不同,整个攻击过程均在用户侧浏览器执行,无需 Web 服务器端进行解析和响应访问请求。这种类型的攻击比较难排查,WAF 设备无法获取通信流量,可能难以发现攻击。
4.2.4 总结
反射型 XSS 和 DOM 型 XSS 都属于“非持久型 XSS”,恶意脚本只执行一次;而存储型 XSS 则会将恶意脚本存储到后端服务器的数据库或文件中,每次访问页面时,脚本都会执行一次。
4.3 模拟 XSS 存储型漏洞攻击
正常页面
用户打开系统主页时,会看到如下页面,该页面显示正常。logo 图片的 base64 编码来源与后端返回的数据。

页面的前端代码简化后如下:
前端页面将获取到的 logo base64 编码数据组装成的 HTML 如下图所示:

4.3.2 模拟黑客攻击
在众测阶段,产线会提前分配账号给大家登录测试,有测试同学登录后,用 postman 工具调用了一个保存请求,将 logo 存储为非正常图片的 base64 编码(注入了恶意的代码)。如下图所示:

这段 base64 编码对应的 JavaScript 代码如下:
将这段 JavaScript 代码通过 base64 编码工具转换成 base64 编码,如下图所示:

用户访问主页时,浏览器会从 Web 服务器获取 logo 的图片数据,然后组装到 HTML 中,如下图所示:

最后用户看到的将是这个页面。

鼠标右键点击 test 左侧的图标,选择“在新标签页中打开图片”。

接着就会出现一个弹框,弹出了一个数字 1,表示 XSS 攻击成功了。

4.4 CodeBuddy 协助找安全漏洞
提示语:/Users/wukong/Documents/test.html 可能存在的安全漏洞问题
CodeBuddy 回答如下,第一句就是 XSS 漏洞风险,还是挺智能的。

修复方案如下:

结构改进:
添加了完整的 HTML5 文档结构
规范了页面编码声明
安全增强:
实施了严格的内容安全策略
为图片添加了跨域安全属性
添加了 referrer 控制策略
然后我直接让 CodeBuddy 帮我把文件改好。

这样就把这个 XSS 漏洞修复了,是不是很丝滑!
五、总结
通过第一个真实案例,我们利用 CodeBuddy 分析了代码中存在的 SQL 注入漏洞以及形成原因,然后通过预编译的方式来解决了 SQL 注入问题。
通过第二个真实案例,我们学习了 XSS 漏洞的三种类型,并利用 CodeBuddy 分析了代码中存在的 XSS 漏洞以及解决方案。
版权声明: 本文为 InfoQ 作者【悟空聊架构】的原创文章。
原文链接:【http://xie.infoq.cn/article/737d2ed992710399cc36e9269】。文章转载请联系作者。
评论