When deserializing a DecryptingInputStream, we call NSSCipherStrategy::DeserializeKey on an untrusted input: ``` template <typename CipherStrategy> bool DecryptingInputStream<CipherStrategy>::Deserialize( const mozilla::ipc::InputStreamParams& aParams) { MOZ_ASSERT(aParams.type() == mozilla::ipc::InputStreamParams::TEncryptedFileInputStreamParams); const auto& params = aParams.get_EncryptedFileInputStreamParams(); nsCOMPtr<nsIFileInputStream> stream; nsFileInputStream::Create(NS_GET_IID(nsIFileInputStream), getter_AddRefs(stream)); nsCOMPtr<nsIIPCSerializableInputStream> baseSerializable = do_QueryInterface(stream); if (NS_WARN_IF( !baseSerializable->Deserialize(params.fileInputStreamParams()))) { return false; } Init(WrapNotNull<nsCOMPtr<nsIInputStream>>(std::move(stream)), params.blockSize()); mKey.init(mCipherStrategy.DeserializeKey(params.key())); // <-- here if (NS_WARN_IF( NS_FAILED(mCipherStrategy.Init(CipherMode::Decrypt, params.key())))) { return false; } return true; } ``` This asserts that the size is correct, but does not check it at runtime in a release build: ``` NSSCipherStrategy::KeyType NSSCipherStrategy::DeserializeKey( const Span<const uint8_t>& aSerializedKey) { KeyType res; MOZ_ASSERT(res.size() == aSerializedKey.size()); std::copy(aSerializedKey.cbegin(), aSerializedKey.cend(), res.begin()); return res; } ``` This means that the `std::copy` call can overflow the allocated stack buffer. I've provided a patch which will convert an outgoing request body of size 0x1234 to an EncryptedInputStream and trigger this issue. I don't seem to be able to attach multiple files to the report, so I'll add my server script as a comment. I've only tested this on linux, where the incoming IPC message is processed on the main thread. In my build this means that this appears not to be exploitable (there is nothing on the stack which can be corrupted that is used prior to the stack-cookie check), so I'm reporting this without applying a deadline. I've still marked this as a security bug, as it may still be exploitable on other platforms/compilers or if there are situations in which other threads handle incoming IPC messages; I'm not sufficiently familiar with Firefox' threading model.
Bug 1843038 Comment 0 Edit History
Note: The actual edited comment in the bug view page will always show the original commenter’s name and original timestamp.
When deserializing a DecryptingInputStream, we call NSSCipherStrategy::DeserializeKey on an untrusted input: ```C++ template <typename CipherStrategy> bool DecryptingInputStream<CipherStrategy>::Deserialize( const mozilla::ipc::InputStreamParams& aParams) { MOZ_ASSERT(aParams.type() == mozilla::ipc::InputStreamParams::TEncryptedFileInputStreamParams); const auto& params = aParams.get_EncryptedFileInputStreamParams(); nsCOMPtr<nsIFileInputStream> stream; nsFileInputStream::Create(NS_GET_IID(nsIFileInputStream), getter_AddRefs(stream)); nsCOMPtr<nsIIPCSerializableInputStream> baseSerializable = do_QueryInterface(stream); if (NS_WARN_IF( !baseSerializable->Deserialize(params.fileInputStreamParams()))) { return false; } Init(WrapNotNull<nsCOMPtr<nsIInputStream>>(std::move(stream)), params.blockSize()); mKey.init(mCipherStrategy.DeserializeKey(params.key())); // <-- here if (NS_WARN_IF( NS_FAILED(mCipherStrategy.Init(CipherMode::Decrypt, params.key())))) { return false; } return true; } ``` This asserts that the size is correct, but does not check it at runtime in a release build: ```C++ NSSCipherStrategy::KeyType NSSCipherStrategy::DeserializeKey( const Span<const uint8_t>& aSerializedKey) { KeyType res; MOZ_ASSERT(res.size() == aSerializedKey.size()); std::copy(aSerializedKey.cbegin(), aSerializedKey.cend(), res.begin()); return res; } ``` This means that the `std::copy` call can overflow the allocated stack buffer. I've provided a patch which will convert an outgoing request body of size 0x1234 to an EncryptedInputStream and trigger this issue. I don't seem to be able to attach multiple files to the report, so I'll add my server script as a comment. I've only tested this on linux, where the incoming IPC message is processed on the main thread. In my build this means that this appears not to be exploitable (there is nothing on the stack which can be corrupted that is used prior to the stack-cookie check), so I'm reporting this without applying a deadline. I've still marked this as a security bug, as it may still be exploitable on other platforms/compilers or if there are situations in which other threads handle incoming IPC messages; I'm not sufficiently familiar with Firefox' threading model.