Fix unauth-SSRC memory grow#372
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #372 +/- ##
==========================================
+ Coverage 82.42% 82.54% +0.11%
==========================================
Files 19 19
Lines 1462 1472 +10
==========================================
+ Hits 1205 1215 +10
Misses 142 142
Partials 115 115
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
02b62e5 to
feffa0b
Compare
|
Nice find! @sirzooro would you mind adding a test to assert no allocations on auth failure. IMO the warning on NULL crypto isn’t needed. If we add to much noise then maybe something real would get ignored. |
|
Does doing replay detection without authentication allow a DoS? I can spam RTP packets and break sessions now without keying materials |
Added new tests. Is there some valid production use of NULL cipher beside debugging? If yes, I would add another option to silence these warnings. I would like to have at least warning if someone would accidentally use insecure configuration in production environment.
I do not see anything obvious in the code, AI scan also did not reveal anything related to this. Maybe this is caused by increased CPU usage (higher jitter) or receive UDP buffer was overflown and some frames were dropped? |
|
i looked yesterday and it looks good to me, but i didn't really review it, I can review it tonight, @Sean-Der what do you think? |
|
@sirzooro Can we reduce it down to just fix I would like to still keep single purpose commits (even if AI can do big changes easily) especially in these security changes. Sorry for the push back :/ I think we should merge/tag that right away! |
|
@Sean-Der I have removed logging changes. PR contains main fix for unauth-SSRC memory grow, and two other small ones in context.go (first two points in description above). I also updated PR's description to match actual changes. |
|
@Sean-Der small reminder :) |
|
@sirzooro I think we can just break the changes into separate commits in this PR, the idea is that if someone is looking at blame or reviewing the changes that happens to a repo it's a lot easier if commit = single change, also if we want to revert stuff for whatever reason. |
|
I already removed logging changes from this PR, what is left is fix for issue in the title plus two minor fixes in |
|
@sirzooro I'm sorry can we rebase these minor fixes to a separate commit, it also makes more sense for security fixes in case we want to release a CVE or just link the patch / commit. |
Prevent memory growth from processing of unauthenticated SSRCs. Added explicit warnings when insecure configuration options are active.
|
@JoTurk done, removed it from this PR. |
Fix unauthenticated-SSRC memory exhaustion and add security-warning logging
Summary
This change addresses two classes of vulnerability where unauthenticated data in RTP/RTCP headers could be used to allocate unbounded per-SSRC state before the auth tag is verified.
Security Fixes
Unauthenticated SSRC state allocation (memory exhaustion)
srtp.go / srtcp.go —
getSRTPSSRCStateandgetSRTCPSSRCStatenow accept akeepNew boolparameter. During decryption the SSRC is read from the unauthenticated RTP/RTCP header, so these functions are called in read-only mode (keepNew = false): a temporary state object is created but not inserted into the map. The state is committed to the map by the newsetSRTPSSRCState/setSRTCPSSRCStatehelpers only aftermarkAsValid()succeeds (i.e. authentication is confirmed).session_srtp.go —
decryptRTPis now called beforegetOrCreateReadStream. Previously an unauthenticated peer could causegetOrCreateReadStreamto allocate a per-SSRC stream for an arbitrary spoofed SSRC, exhausting memory without ever providing a valid packet.Both fixes include inline comments explaining the security rationale and the intentional ordering of the replay check relative to authentication.
What Changed
context.go
setSRTPSSRCStateandsetSRTCPSSRCStatehelpers for explicit post-auth state commitment.getSRTPSSRCStateandgetSRTCPSSRCStatereturn a secondboolindicating whether the state was pre-existing.SetROCandSetIndexupdated to passkeepNew = true(they always want to create state).session_srtp.go
decryptRTPcall abovegetOrCreateReadStreamto prevent unauthenticated stream allocation (see Security Fixes above).srtcp.go / srtp.go
getSRTCPSSRCState(ssrc, false)/getSRTPSSRCState(ssrc, false)with deferredsetSRTCPSSRCState/setSRTPSSRCStateafter authentication.getSRTCPSSRCState(ssrc, true)/getSRTPSSRCState(ssrc, true)(no behaviour change for encrypt).API Notes
getSRTPSSRCState/getSRTCPSSRCStatesignatures changed (internal); callers outside the package are unaffected.Tests
go test ..Reviewer Notes
markAsValid()is explicitly called.