背景
公司信安部門對項目進行安全掃描,查出一些漏洞,其中有一項要求升級 javascript 框架庫(如圖):
嚇得我以爲讓我把 Vue2 升級成 Vue3。
經過一些調試之後才知道,是webpack打包之後的工具包中依賴的 YUI 是存 在安全漏洞的版本。
漏洞定位
信安同事一開始只給我上面的圖,我根本不知道是哪個包的版本需要升級。
我只能用漏洞標題去百度,搜到了一些同樣掃出漏洞的情況,多是在說下面幾個工具:
- jquery 我用了已經升級到最新的了
- js-cookie 文章說改存 localStorage(我改了但是還是存在漏洞)
- jsencrypt 事實證明確實是這個,但沒有具體說明原因
查到這裏,同事也發來更詳細的說明:
YUI:2.9.0 (Link) https://www.cvedetails.com/cve/CVE-2012-5883/
於是我就在打包後的代碼中搜索 YUI(不區分大小寫,不進行全字匹配),果然搜到了一段註釋:
確認了這個事情,接下來就容易多了。這明顯不是我的代碼,那就在 node_modules 中繼續搜索,最終在 jsencrypt 下查到了這段註釋:
YUI2 的版本漏洞
在網上搜索關於 YUI 2.9.0 漏洞的信息:搜索結果
結果中也包含掃描工具提供的漏洞地址,該漏洞指出:
在 YUI 2.8.0 - 2.9.0 中的 Flash 組件基礎機構中存在 XSS 漏洞,遠程攻擊者可以通過 SWF 程序(YUI SWF 提供了一種在網頁中嵌入 Adobe Flash Player 的標準方法)注入任意 Web 腳本或 HTML。
現在我們知道 YUI 2.9.0 這個版本確實有安全隱患,BUG 我們真的有這個漏洞麼 ?
YUI 在代碼中的實際應用
官方介紹:YUI 是一個免費的、開源的 JavaScript 和 CSS 庫,用於構建豐富的交互式 web 應用程序。
不太嚴謹的說,YUI 就是類似 jquery 的一個工具庫。
然後看看 jsencrypt 爲啥要使用它呢?
從 node_modules\jsencrypt\lib\lib\jsrsasign\yahoo.js 的代碼看,整個文件到處的只是一個包含 lang.extend 方法的對象。
lang.extend 方法模擬類的繼承方式,從一個對象上擴展出領域給對象。
也就是說 jsencrypt 僅僅使用了 YUI 的 lang.extend 方法,碰都沒碰 YUI SWF。
這麼看盡管代碼用的是 2.9.0 版本的一部分,但是這個版本的安全漏洞根本影響不到項目。
解決辦法
現在可以總結出:
- 漏洞的原因是 YUI 2.9.0 版本存在安全漏洞
- 安全軟件掃描的依據是註釋中包含 yui 的版本號
那其實只要解決掉 YUI 版本號的這塊註釋即可。
方法一:使用壓縮後的文件
網上搜的辦法大部分是使用壓縮後(不含註釋)的文件:node_modules\jsencrypt\bin\jsencrypt.min.js
// 舊的引入方式 import JSEncrypt from 'jsencrypt' // 新的引入方式 import JSEncrypt from 'jsencrypt/bin/jsencrypt.min'
方法二:優化打包配置,刪除註釋
我的辦法是,在打包環節刪除註釋,全局 AOE 幹掉所有註釋,解決註釋引發的所有問題。那麼如何清除掉這些註釋呢?參考官方文檔配置如下
TerserWebpackPlugin | webpack 中文文檔
看了下源碼是這麼寫的
optimization: { ... minimizer: [ { options: { test: /\.m?js(\?.*)?$/i, chunkFilter: () => true, warningsFilter: () => true, extractComments: false, sourceMap: false, cache: true, cacheKeys: defaultCacheKeys => defaultCacheKeys, parallel: true, include: undefined, exclude: undefined, minify: undefined, terserOptions: { output: { // 默認保留了 @license 註釋 comments: /^\**!|@preserve|@license|@cc_on/i }, compress: { ...}, mangle: { ...} } } } ]); }
似乎直接改output就行了於是試了一下
vue.config.js增加配置
chainWebpack(config) { // 刪除註釋 config.optimization.minimizer('terser').tap(args => { // 直接修改 terserOptions 下的屬性值,保留原有配置 // 這裏訪問 terserOptions 的時候並沒有 output,訪問不到 output.comments 需要直接賦值 args[0].terserOptions.output = { comments: false, } return args }) }
但是這種方式我試了不行而且拋出了異常
config.optimization.minimizer(...).tap is not a function
於是又看到有一個這種插件 terser-webpack-plugin、uglifyjs-webpack-plugin
1、安裝 terser-webpack-plugin
yarn add terser-webpack-plugin -D
2、修改 vue.config.js 文件
const TerserPlugin = require("terser-webpack-plugin"); module.exports = { ... configureWebpack: { optimization: { minimizer: [ new TerserPlugin({ terserOptions: { output: { comments: false } }, extractComments: false }) ] } }, ... }
1. 安裝uglifyjs-webpack-plugin
npm install uglifyjs-webpack-plugin -D
2. vue.config.js裏添加配置
const UglifyJsPlugin = require('uglifyjs-webpack-plugin') //引入插件 module.exports = { configureWebpack: { optimization: { minimizer: [ new UglifyJsPlugin({ uglifyOptions: { // 刪除註釋 output: { comments: false }, // 刪除console debugger 刪除警告 compress: { drop_console: true, //console drop_debugger: false, pure_funcs: ['console.log'] //移除console } } }) ] } } }
用插件的兩種方式我都試了可以解決問題、成功去掉了註釋
參考文檔:
https://blog.csdn.net/qq_45585640/article/details/126402126
https://blog.csdn.net/u012961419/article/details/130016341