摘要:遷移到安全的構造函數移植到概述本指南介紹了如何遷移到安全的構造函數方法,遷移修復了以下棄用警告由于安全性和可用性問題,不建議使用和構造函數,請改用或構造方法。
遷移到安全的Buffer構造函數
移植到Buffer.from()/Buffer.alloc() API.
概述本指南介紹了如何遷移到安全的Buffer構造函數方法,遷移修復了以下棄用警告:
由于安全性和可用性問題,不建議使用Buffer()和new Buffer()構造函數,請改用new Buffer.alloc()、Buffer.allocUnsafe()或Buffer.from()構造方法。
變式1:放棄對Node.js ≤4.4.x和5.0.0 - 5.9.x的支持(推薦)。
變式2:使用polyfill。
變式3:手動檢測,帶有安全措施。
使用grep查找有問題的代碼位只需運行grep -nrE "[^a-zA-Z](Slow)?Buffers*(" --exclude-dir node_modules。
它會在你自己的代碼中找到所有可能不安全的地方(有一些不太常見的例外)。
使用Node.js 8查找有問題的代碼位如果你使用的是Node.js ≥ 8.0.0(推薦使用),Node.js會公開多個選項,以幫助你找到相關的代碼片段:
--trace-warnings將使Node.js顯示此警告的堆棧跟蹤以及Node.js打印的其他警告。
--trace-deprecation執行相同的操作,但僅適用于棄用警告。
--pending-deprecation將顯示更多類型的棄用警告,特別是,它也會顯示Buffer()棄用警告,即使在Node.js 8上。
你可以使用環境變量設置這些標志:
$ export NODE_OPTIONS="--trace-warnings --pending-deprecation" $ cat example.js "use strict"; const foo = new Buffer("foo"); $ node example.js (node:7147) [DEP0005] DeprecationWarning: The Buffer() and new Buffer() constructors are not recommended for use due to security and usability concerns. Please use the new Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() construction methods instead. at showFlaggedDeprecation (buffer.js:127:13) at new Buffer (buffer.js:148:3) at Object.使用linters查找有問題的代碼位(/path/to/example.js:2:13) [... more stack trace lines ...]
ESLint規則no-buffer-constructor或node/no-deprecated-api也查找對不推薦使用的Buffer() API的調用,這些規則包含在一些預設中。
但是有一個缺點,當Buffer被重寫時,它并不總是正確工作,例如使用polyfill,因此建議將此與上述其他方法結合使用。
變式1:放棄對Node.js ≤4.4.x和5.0.0 - 5.9.x的支持這是目前推薦的解決方案,僅意味著最小的開銷。
自2016年7月以來,Node.js 5.x版本系列一直未得到支持,并且Node.js 4.x版本系列在2018年4月達到其生命周期結束(→計劃)。
這意味著即使出現安全問題,這些版本的Node.js也不會收到任何更新,因此如果可能的話,應該避免使用這些版本線。
在這種情況下,你要做的是將所有new Buffer()或Buffer()調用轉換為使用Buffer.alloc()或Buffer.from(),方法如下:
對于new Buffer(number),將其替換為Buffer.alloc(number)。
對于new Buffer(string)(或new Buffer(string, encoding)),將其替換為Buffer.from(string)(或Buffer.from(string, encoding))。
對于所有其他參數組合(這些更為罕見),還要用Buffer.from(...arguments)替換new Buffer(...arguments)。
請注意,Buffer.alloc()在當前Node.js版本上的速度也比new Buffer(size).fill(0)快,這是你需要確保零??填充的原因。
建議啟用ESLint規則no-buffer-constructor或node/no-deprecated-api以避免意外的不安全Buffer API使用。
還有一個JSCodeshift codemod,用于自動將Buffer構造函數遷移到Buffer.alloc()或Buffer.from(),請注意,它目前僅適用于參數為文字或使用兩個參數調用構造函數的情況。
如果你當前支持那些較舊的Node.js版本并且無法刪除對它們的支持,或者如果你支持包的舊分支,考慮在較舊的分支上使用變式2或變式3,因此使用這些舊分支的人也將收到修復。這樣,你將消除由不謹慎的Buffer API使用引起的潛在問題,并且在Node.js 10上運行代碼時,你的用戶將不會觀察到運行時棄用警告。
變式2:使用polyfill有三種不同的polyfill可用:
safer-buffer是整個Buffer API的替代品,在使用new Buffer()時會拋出。
你將采用與變式1完全相同的步驟,但是在使用新的Buffer API的所有文件中都使用polyfill const Buffer = require("safer-buffer").Buffer。
不要使用舊的new Buffer() API,在添加上面一行的任何文件中,使用舊的new Buffer() API將拋出。
buffer-from和/或buffer-alloc是Buffer API各自部分的ponyfill,你只需添加與你正在使用的API相對應的包。
你可以使用適當的名稱導入所需的模塊,例如const bufferFrom = require("buffer-from")然后使用它而不是調用new Buffer(),例如:new Buffer("test")變為bufferFrom("test")。
使用這種方法的一個缺點是從它們遷移出來的代碼更改略多(因為你將使用不同名稱下的Buffer.from())。
safe-buffer也是整個Buffer API的替代品,但使用new Buffer()仍然可以像以前一樣工作。
這種方法的缺點是它允許你在代碼中使用較舊的new Buffer() API,這是有問題的,因為它可能會導致代碼中出現問題,并將從Node.js 10開始發出運行時棄用警告(在此處閱讀更多內容)。
請注意,在任何一種情況下,你還必須手動刪除對舊Buffer API的所有調用,只是投入safe-buffer本身并不能解決問題,它只是為新API提供了一個polyfill,我看到有人犯了這個錯誤。
建議啟用ESLint規則no-buffer-constructor或node/no-deprecated-api。
放棄對Node.js <4.5.0的支持后,不要忘記刪除polyfill使用。
變式3 - 手動檢測,帶有安全措施如果你只在幾個地方(例如一個)創建Buffer實例,或者你有自己的包裝器,這將非常有用。
Buffer(0)這個用于創建空緩沖區的特殊情況可以安全地替換為Buffer.concat([]),它返回相同的結果一直到Node.js 0.8.x。
Buffer(notNumber)之前:
const buf = new Buffer(notNumber, encoding);
以后:
let buf; if (Buffer.from && Buffer.from !== Uint8Array.from) { buf = Buffer.from(notNumber, encoding); } else { if (typeof notNumber === "number") { throw new Error("The "size" argument must be not of type number."); } buf = new Buffer(notNumber, encoding); }
encoding是可選的。
請注意,typeof notNumber必須在new Buffer()之前,(對于notNumber參數未進行硬編碼的情況)并且不是由Buffer構造函數的棄用引起的 - 這正是不推薦使用Buffer構造函數的原因。缺乏此類型檢查的生態系統包導致了許多安全問題 - 當未經過處理的用戶輸入可能最終出現在Buffer(arg)中時,會出現從DoS到從進程內存向攻擊者泄漏敏感信息等問題。
當notNumber參數被硬編碼時(例如文字"abc"或[0,1,2]),可以省略typeof檢查。
另請注意,使用TypeScript不能解決此問題 - 當從JS中使用用TypeScript編寫的庫時,或者當用戶輸入結束時 - 它的行為與純JS一樣,因為所有類型檢查只是轉換時間,并且不存在于TS編譯的實際JS代碼中。
Buffer(number)對于Node.js 0.10.x(及以下)支持:
var buf; if (Buffer.alloc) { buf = Buffer.alloc(number); } else { buf = new Buffer(number); buf.fill(0); }
否則(Node.js ≥ 0.12.x):
const buf = Buffer.alloc ? Buffer.alloc(number) : new Buffer(number).fill(0);關于Buffer.allocUnsafe()
使用Buffer.allocUnsafe()時要格外小心:
如果你沒有充分的理由,請不要使用它。
例如你可能永遠不會看到小緩沖區的性能差異,事實上,使用Buffer.alloc()可能會更快。
如果你的代碼不在熱代碼路徑中 - 你也可能不會注意到差異。
請記住,零填充可以最大限度地降低潛在風險。
如果使用它,請確保永遠不會以部分填充狀態返回buffer。
如果你按順序寫它 - 總是將它截斷為實際的書寫長度。
處理使用Buffer.allocUnsafe()分配的緩沖區中的錯誤可能會導致各種問題,包括代碼的未定義行為,以及泄露給遠程攻擊者的敏感數據(用戶輸入、密碼、證書)。
請注意,這同樣適用于沒有零填充的new Buffer()用法,具體取決于Node.js版本(缺少類型檢查也會將DoS添加到潛在問題列表中)。
常問問題Buffer構造函數有什么問題?
Buffer構造函數可用于以多種不同方式創建緩沖區:
new Buffer(42)創建一個42字節的Buffer,在Node.js 8之前,由于性能原因,此緩沖區包含任意內存,其中可能包括從程序源代碼到密碼和加密密鑰的任何內容。
new Buffer("abc")創建一個Buffer,其中包含字符串"abc"的UTF-8編碼版本,第二個參數可以指定另一個編碼:例如,可以使用new Buffer(string, "base64")將Base64字符串轉換為它所代表的原始字節序列。
還有其他幾種參數組合。
這意味著在像var buffer = new Buffer(foo);這樣的代碼中,在不知道foo類型的情況下,無法確定生成的緩沖區的確切內容。
有時,foo的值來自外部來源,例如,此函數可以作為Web服務器上的服務公開,將UTF-8字符串轉換為其Base64格式:
function stringToBase64(req, res) { // The request body should have the format of `{ string: "foobar" }`. const rawBytes = new Buffer(req.body.string); const encoded = rawBytes.toString("base64"); res.end({ encoded }); }
請注意,此代碼不驗證req.body.string的類型:
req.body.string應該是一個字符串,如果是這種情況,一切順利。
req.body.string由發送請求的客戶端控制。
如果req.body.string是數字50,則rawBytes將是50個字節:
在Node.js 8之前,內容將是未初始化的。
在Node.js 8之后,內容將是50個字節,值為0。
由于缺少類型檢查,攻擊者可以故意發送一個號碼作為請求的一部分,使用它,他們可以:
讀取未初始化的內存,這將泄露密碼、加密密鑰和其他類型的敏感信息(信息泄露)。
強制程序分配大量內存,例如,當指定500000000作為輸入值時,每個請求將分配500MB的內存,這可以用來完全耗盡程序可用的內存并使其崩潰,或者顯著減慢程序速度(拒絕服務)。
在現實世界的Web服務器環境中,這兩種情況都被認為是嚴重的安全問題。
當使用Buffer.from(req.body.string)時,傳遞一個數字將總是拋出一個異常,提供可由程序始終處理的受控行為。
Buffer()構造函數已被棄用了一段時間,這真的是一個問題嗎?npm生態系統中的代碼調查表明,Buffer()構造函數仍然被廣泛使用,這包括新代碼,并且此類代碼的總體使用實際上已經增加。
上一篇:Docker化Node.js Web應用程序 下一篇:阻塞與非阻塞概述文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/99223.html
Node.js 指南 Node.js?是基于Chrome的V8 JavaScript引擎構建的JavaScript運行時。 常規 關于Node.js 入門指南 輕松分析Node.js應用程序 Docker化Node.js Web應用程序 遷移到安全的Buffer構造函數 Node.js核心概念 阻塞與非阻塞概述 Node.js事件循環、定時器和process.nextTick() 不要阻塞事...
摘要:標準庫中的所有方法都提供非阻塞的異步版本,并接受回調函數,某些方法還具有對應的阻塞方法,其名稱以結尾。比較代碼阻塞方法同步執行,非阻塞方法異步執行。 阻塞與非阻塞概述 此概述介紹了Node.js中阻塞與非阻塞調用之間的區別,此概述將引用事件循環和libuv,但不需要事先了解這些主題,假設讀者對JavaScript語言和Node.js回調模式有基本的了解。 I/O主要指與libuv支持的...
摘要:化應用程序此示例的目的是向你展示如何將應用程序放入容器中,該指南旨在用于開發,而不用于生產部署,本指南還假設你有一個有效的安裝,并且基本了解應用程序的結構。 Docker化Node.js Web應用程序 此示例的目的是向你展示如何將Node.js應用程序放入Docker容器中,該指南旨在用于開發,而不用于生產部署,本指南還假設你有一個有效的Docker安裝,并且基本了解Node.js應...
摘要:在數據緩沖區已超過或寫入隊列當前正忙的任何情況下,將返回。當返回值時,背壓系統啟動,它會暫停傳入的流發送任何數據,并等待消費者再次準備就緒,清空數據緩沖區后,將發出事件并恢復傳入的數據流。 流中的背壓 在數據處理過程中會出現一個叫做背壓的常見問題,它描述了數據傳輸過程中緩沖區后面數據的累積,當傳輸的接收端具有復雜的操作時,或者由于某種原因速度較慢時,來自傳入源的數據就有累積的趨勢,就像...
摘要:參考文檔是基于的引擎構建的運行時。關于文檔用法和示例斷言測試穩定性穩定模塊提供了一組簡單的斷言測試,可用于測試不變量。存在和模式,但建議僅使用模式。類在全局作用域內,因此不太可能需要使用。以下所有示例均可供下載,可用作擴展庫的起點。 Node.js v11.5.0 API參考文檔 Node.js?是基于Chrome的V8 JavaScript引擎構建的JavaScript運行時。 關...
閱讀 2128·2021-09-27 14:04
閱讀 1873·2019-08-30 15:55
閱讀 1698·2019-08-30 13:13
閱讀 1065·2019-08-30 13:07
閱讀 2742·2019-08-29 15:20
閱讀 3240·2019-08-29 12:42
閱讀 3324·2019-08-28 17:58
閱讀 3593·2019-08-28 17:56