前端安全—你必須要注意的依賴安全漏洞

NO IMAGE

從一個安全漏洞說起

前端安全—你必須要注意的依賴安全漏洞

Lodash 是一款非常流行的 npm 庫,每月的下載量超過 8000 萬次,GitHub 上使用它的項目有超過 400 萬。前段時間 Lodash 的一個安全漏洞刷爆了朋友圈,我們先來回憶下這個安全漏洞:

攻擊者可以通過 Lodash 的一些函數覆蓋或汙染應用程序。例如:通過 Lodash 庫中的函數 defaultsDeep 可以修改 Object.prototype 的屬性。

前端安全—你必須要注意的依賴安全漏洞

我們都知道,JavaScript 在讀取對象中的某個屬性時,如果查找不到就會去其原型鏈上查找。試想一下,如果被修改的屬性是 toString 方法:

const payload = '{"constructor": {"prototype": {"toString": true}}}'
_.defaultsDeep({}, JSON.parse(payload))

每個對象都有一個 toString() 方法,當該對象被表示為一個文本值時,或者一個對象以預期的字符串方式引用時自動調用。默認情況下,toString() 方法被每個 Object 對象繼承。如果此方法在自定義對象中未被覆蓋,toString() 返回 [object type],其中 type 是對象的類型。如果覆蓋了 toString() 方法,那麼給應用帶來的影響就是非常大的。

其實上述的問題就屬於一個很常見的安全漏洞 —— 原型汙染

原型汙染:攻擊者通過某種手段修改 JavaScript 對象的原型(prototype)

然而這並不是 Lodash 第一次爆出安全漏洞了。事實上,像這樣的安全漏洞還可能存在於我們使用的千千萬萬個不同的開源依賴中,如果我們平時不重視他們,一旦出現問題對我們的項目造成的損失是不可估計的。這相當於你的項目中埋著很多不知道什麼時候就會爆炸的炸彈。

安全調查

其實開發人員對開源代碼的安全性的信任程度要大於對自己編寫的代碼的安全性的信任程度,但是在確保代碼安全性和質量的工具還有很多不足之處。在 npm 還沒有一個完善的安全檢測機制之前,npmNodeJs 團隊曾經對數萬名 JavaScript 開發者發起過一個調查,第一個問題就是安全問題,具體就是開發人員如何看待他們編寫的代碼和所使用的開源項目的安全性。

調查結果顯示:全球 97%JavaScript 開發人員在自己開發的項目中都依賴開源代碼,77% 的開發人員對他們使用的開源代碼是否安全表示擔憂。更有趣的是,有 87% 的人表示擔心自己的代碼的安全性。

前端安全—你必須要注意的依賴安全漏洞

另外,超過一半的 JavaScript 開發人員認為,他們用來評估開源代碼的安全性和質量的工具還不夠好。

前端安全—你必須要注意的依賴安全漏洞

npm audit

前端安全—你必須要注意的依賴安全漏洞

基於上面的不太樂觀的調查結果,[email protected] 增加了一項重大更新:npm audit 命令。從上面的 logo 就可以看出,這個版本是主打安全性。 npm audit 命令會遞歸地分析依賴關係樹以識別不安全的依賴,如果你在項目中使用了具有已知安全問題的依賴,就收到警告通知。該命令會在你更新或者安裝了新的依賴包後自動運行。

npm 官方專門維護了一個漏洞列表,當開發者或者專業的安全團隊發現某個依賴包存在安全問題後就會上報給 npm 官方,然後官方會通知該項目開發者進行修復,修復完成後 npm 會把漏洞詳細的描述信息、解決方案發布出來:

前端安全—你必須要注意的依賴安全漏洞

npm aduit 主要做的就是把需要檢查的依賴信息發送給一個官方檢查接口, 該結構會在歷史上報的漏洞數據庫中判斷當前依賴信息是否含有漏洞,然後生成一個包含包名稱、漏洞嚴重性、簡介、路徑等的漏洞報告反饋給開發者。

我們現在直接安裝一個具有安全漏洞的 [email protected] 版本,可見安裝完成後會提醒你你剛剛增加的依賴中含有3個漏洞。

前端安全—你必須要注意的依賴安全漏洞

執行 npm audit 我們可以看到漏洞詳情,這個版本的 lodash 存在3個安全漏洞,我們來具體看一個:

前端安全—你必須要注意的依賴安全漏洞

  • High: 表安全漏洞等級
  • Package: 存在漏洞的包名稱
  • Dependency of: 當前工程直接依賴的包名稱
  • Path: 漏洞完整依賴路徑
  • More info: 漏洞詳情

這裡注意,並不只是直接依賴的包具有漏洞才會收到提醒,而是隻要是你的依賴樹中某一個節點依賴依賴了具有漏洞的包你就會收到提醒,來看看下面的例子:

項目中並非直接依賴了 lodash ,而是 @commitlint/cli 依賴的 @commitlint/load 中依賴了 lodash 就會算作一個漏洞,所以一些龐大的迭代週期很長的項目含有幾萬個安全漏洞也是很正常的。

前端安全—你必須要注意的依賴安全漏洞

點開漏洞詳情的鏈接:https://www.npmjs.com/advisories/1065

前端安全—你必須要注意的依賴安全漏洞

我們可以看到漏洞具體說明,以及解決方法,右側是該漏洞的具體上報時間,漏洞公開時間。

GitHub 安全板塊

平時我們可能經常會收到類似如下的 GitHub 安全漏洞提醒的郵件。

前端安全—你必須要注意的依賴安全漏洞

打開鏈接,我們可以看到漏洞具體的詳情頁面:

前端安全—你必須要注意的依賴安全漏洞

GitHub 單獨為它開闢了一個,Security 板塊來展示 GitHub 檢測到的依賴安全漏洞,可見這些漏洞是足夠引起大家重視並且需要快速修復的:

前端安全—你必須要注意的依賴安全漏洞

另外,GitHub 還為每個可修復的漏洞提供了一鍵修復的功能,點擊 Automated security updates 按鈕,GitHub 會自動將這些依賴漏洞修復,並提交一個 Pull Request 給你的倉庫:

前端安全—你必須要注意的依賴安全漏洞

安全漏洞修復策略

npm 也提供了 npm audit fix 命令來幫助我們自動修復漏洞,還繼續使用上面的例子, Lodash4.17.12 版本之前都具有原型汙染漏洞,下面我們來看看具體的修復策略:

直接依賴漏洞

當前我們直接依賴了一個具有安全漏洞的 [email protected] 版本:

  "dependencies": {
"lodash": "^4.17.4"
}

由於 ^4.17.4 的依賴範圍是 >=3.0.3 < 4.0.0,已修復的版本 4.17.12 在這個範圍內,那麼實際上 npm audit fix 執行的邏輯就是 npm update [email protected]

[email protected]^4.17.4 -> [email protected]^4.17.12

間接依賴漏洞

假設我們現在的依賴路徑非常深: @commitlint/cli^7.1.2>@commitlint/load^1.0.1>lodash^3.0.0

前端安全—你必須要注意的依賴安全漏洞

因為 @commitlint/loadlodash 的依賴是^3.0.0(>=3.0.0 <4.0.0)4.17.12 不在這個範圍,所以我們不能直接通過升級 Lodash 來修復漏洞,這時我們就要向上層依賴進行分析。

假設此時 @commitlint/load 有一個更新版本 @commitlint/load^1.0.2lodash 的依賴是^4.0.0(>=4.0.0 <5.0.0)[email protected] 在這個依賴範圍內,那麼修復策略為 npm update @commitlint/[email protected] --depth=2

npm update 只會檢查更新頂層的依賴,更新更深層次的依賴版本需要使用 –depth 指定更新的深度。

按照這個邏輯,如果 @commitlint/load 也沒有找到可以升級的包,那麼再到上層依賴查找,直到找到可以修復漏洞的那個層級的依賴。

強制修復漏洞

按照上面的策略,從底層依賴一直向上層查找,如果一直到最上層依賴才有符合要求的修復版本,那麼就直接 npm update 更新最頂層依賴。

繼續使用上面的例子,如果 @commitlint/cli^7.1.2( >=7.1.2 <8.0.0 ) 還不能找到一個可修復的版本,那麼 npm audit fix 這個命令就無能為力了。

這時我們可以嘗試 npm audit fix --force(強制執行 audit fix 安裝最新的依賴項(toplevel))來進行修復,這個邏輯就是:npm install @commitlint/[email protected] --save

這個命令會直接跨越當前指定的 semver 版本範圍,強制將依賴更新到最新版本,一定要謹慎使用。

npm 還提供了一些其他的修復命令命令

  • npm audit fix --package-lock-only:在不修改 node_modules 的情況下執行 audit fix,仍然會更改 pkglock
  • npm audit fix --only=prod:跳過更新 devDependencies

不可修復漏洞

當然,以上的修復策略都不能解決這個安全漏洞,那說明此漏洞是無法自動修復的,需要人工判定處理。

關閉安全檢查

如果你對這些安全漏洞不 care,你也可以手動指定一些配置來關閉這些安全檢查:

  • 安裝單個包關閉安全審查: npm install example-package-name --no-audit
  • 安裝所有包關閉安全審查 – 運行 npm set audit false
  • 手動將 ~/.npmrc 配置文件中的 audit 修改為 false

當然,強烈不推薦這麼做,一定要對自己開發的項目負責到底~

解讀依賴漏洞報告

執行 npm audit --json 將會打印出一個詳細的 json 格式的安全報告,在這個報告裡可以看到這些漏洞的詳情,以及具體的漏洞修復策略。

由於這個 JSON 比較大,我就不直接貼在這裡了,大家可以選擇一個項目到本地執行 npm audit --json 查看。

漏洞數據總覽

metadata 屬性中:我們可以看到漏洞檢查的數據總覽:

  {
"vulnerabilities": {
"info": 0,
"low": 0,
"moderate": 4,
"high": 29,
"critical": 0
},
"dependencies": 18594,
"devDependencies": 891090,
"optionalDependencies": 9514,
"peerDependencies": 0,
"totalDependencies": 909785
}

vulnerabilities 中展示了每種等級漏洞的數量,infolowmoderatehighcritical 從左到右對應的安全漏洞等級從低到高。

下面是每種依賴的檢測數量,就是我們熟悉的 dependenciesdevDependencies 等等。

修復策略

actions 屬性中,會列出所有可漏洞的修復策略,例如下面的,對 @commitlint/load 執行更新,深度為 2 ,以修復 @commitlint/cli>@commitlint/load>lodash 這條路徑上的漏洞:

{
"action": "update",
"module": "@commitlint/load",
"target": "1.0.2",
"resolves": [
{
"id": 1184,
"path": "@commitlint/cli>@commitlint/load>lodash",
"dev": false,
"optional": false,
"bundled": false
}
],
"depth": 2
}

另外,action 還有我們上面提到的其他幾種操作:

  • install(修復直接依賴)
  • install major(強制升級依賴,跨越主版本)
  • review(不可自動修復,需要人工review)

漏洞詳情

advisories 屬性存放了每個漏洞的詳情:

"1065": {
"cves": [
"CVE-2019-10744"
],
"access": "public",
"severity": "high",
"metadata": "",
"reviewers": "",
"confirmors": "",
"id": 1065,
"repo_from": "npm",
"title": "Prototype Pollution",
"module_name": "lodash",
"found_by_link": "",
"found_by_user_name": "Snyk Security Team",
"reported_by_link": "",
"reported_by_user_name": "Snyk Security Team",
"vulnerable_versions": "<4.17.12",
"patched_versions": ">=4.17.12",
"overview": "Versions of `lodash` before 4.17.12 are vulnerable to Prototype Pollution.  The function `defaultsDeep` allows a malicious user to modify the prototype of `Object` via `{constructor: {prototype: {...}}}` causing the addition or modification of an existing property that will exist on all objects.\n\n",
"recommendation": "Update to version 4.17.12 or later.",
"references": "- [Snyk Advisory](https://snyk.io/vuln/SNYK-JS-LODASH-450202)",
"cwe": "CWE-471",
"url": "https://npmjs.com/advisories/1065",
"gmt_create": "2019-07-16T02:28:32.000Z",
"gmt_modified": "2019-09-11T04:49:11.000Z",
"deleted_at": null,
"findings": [
{
"version": "4.17.11",
"paths": [
"@commitlint/cli>@commitlint/load>@commitlint/rules>@commitlint/ensure>lodash",
"@commitlint/cli>@commitlint/load>lodash",
"@commitlint/cli>@commitlint/load>@commitlint/resolve-extends>lodash",
"@commitlint/cli>@commitlint/load>lodash",
"@commitlint/cli>lodash"
],
"dev": true,
"optional": false,
"bundled": false
}
]
}

由於屬性比較多,我們挑幾個重點的來看看:

  • cves:CVE漏洞編號
  • severity:漏洞等級
  • found_by_user_name:發現該漏洞的用戶(這裡 Snyk Security Team 是一個知名的安全團隊)
  • vulnerable_versions:受影響的版本
  • patched_versions:已修復的版本
  • findings:所有依賴此路徑的漏洞
  • overview:漏洞的簡要說明,這裡就提到了 LodashdefaultsDeep 容易收到原型汙染
  • references:漏洞參考,一般是由某些專業安全平臺發佈的報告

安全平臺

上面的報告中提到了幾個專業的安全平臺,容易讓人產生迷惑,我們下面來具體看一下:

HackerOne

前端安全—你必須要注意的依賴安全漏洞

HackerOne(http://hackerone.com)成立於 2012 年,是一個安全漏洞聚合和披露平臺,黑客可以在網站上披露自己發現的安全漏洞、並報告給相關的網站或公司,這些網站或公司在確認後可以給黑客提供獎金等各類感謝。HackerOne 平臺的註冊黑客人數已突破 30 萬人,提交的有效漏洞總計超過 10 萬個,支付的漏洞獎勵金超過 4200 萬美元。

前端安全—你必須要注意的依賴安全漏洞

"references": "- [HackerOne Report](https://hackerone.com/reports/541502)"

我們可以在安全報告中看到,某些漏洞還會有一份 HackerOne 的漏洞報告做為參考。

Snyk

前端安全—你必須要注意的依賴安全漏洞

Snyk 是用於多個開發堆棧的依賴關係分析平臺,涵蓋 JavaScript,Java,.Net,Ruby,Python,PHP,GolangScalaSnyk 維護著一個全面的,開放源代碼漏洞數據庫,其中包括 Snyk 自己的專門研究團隊發現的漏洞,以及從公共數據源跟蹤的漏洞。

Snyk 的漏洞數據庫通過其威脅情報系統提供有關漏洞的全面數據,提供更好的覆蓋範圍,並能夠顯示和報告尚未收到 CVE 的漏洞。例如,npm 提示的漏洞中有 72% 是先被添加到 Snyk 數據庫裡的。

Snyk 同樣也提供了掃描安全漏洞的機制,相比 npm audit,它的優勢是可以很容易和 GitHubGitLabCI 流程集成在一起,更多掃描機制上的對比,可以看看這篇文章:https://www.nearform.com/blog/comparing-npm-audit-with-snyk/

前端安全—你必須要注意的依賴安全漏洞

"references": "- [Snyk Advisory](https://snyk.io/vuln/SNYK-JS-LODASH-450202)"

我們可以在上面的安全報告中看到,某些漏洞還會有一份 Snyk 的漏洞報告做為參考,並且 Lodash 這個安全漏洞也是由 Snyk 安全團隊發現並上報的。

CVE

前端安全—你必須要注意的依賴安全漏洞

CVE 代表著通用漏洞和披露的標準, 這是一個由聯邦政府贊助的研究和開發中心的非營利組織。它的目的是識別軟件或固件中的漏洞並將其編目到一個免費的數據庫中, 以提高組織的安全性。

CVE ID 標識特定漏洞或暴露, 組織可以快速準確地從各種 CVE 兼容的信息源中獲取信息。通過在不同安全工具和服務之間的進行比對, CVE 可以幫助組織選擇最適合其需要的內容。

"cves": [
"CVE-2019-10744"
]

前端安全—你必須要注意的依賴安全漏洞

前端安全—你必須要注意的依賴安全漏洞

我們可以看到,不論是上面的 npm audit 報告還是 SnykHackerOne 等其他的安全平臺的報告都會附上一個漏洞的 CVE 編號。

參考

小結

希望看完本篇文章能對你有如下幫助:

  • 瞭解依賴安全漏洞的背景
  • 瞭解 npm 自動修復安全漏洞的機制
  • 瞭解一些常規的安全知識,提高對前端安全問題的關注度

文中如有錯誤,歡迎在評論區指正,如果這篇文章幫助到了你,歡迎點贊和關注。

想閱讀更多優質文章、可關注我的github博客,你的star✨、點贊和關注是我持續創作的動力!

推薦關注我的微信公眾號【code祕密花園】,每天推送高質量文章,我們一起交流成長。

前端安全—你必須要注意的依賴安全漏洞

相關文章

可能是最全面最易懂的解析前端浮動的文章

飛一般的WebGL之唱起3D編程前的戰歌

解讀新一代Web性能體驗和質量指標

當瀏覽器全面禁用三方Cookie