Closed Bug 1698503 (CVE-2021-29946) Opened 4 years ago Closed 4 years ago

Stop Alt-Svc connections to go to blocked ports, when they are written and parsed as exceeding 16 bit

Categories

(Core :: Networking, defect)

defect

Tracking

()

RESOLVED FIXED
88 Branch
Tracking Status
firefox-esr78 88+ fixed
firefox86 --- wontfix
firefox87 --- wontfix
firefox88 + fixed

People

(Reporter: freddy, Assigned: freddy)

References

(Regression)

Details

(Keywords: csectype-sop, regression, sec-low, Whiteboard: [post-critsmash-triage][adv-main88+][adv-esr78.10+])

Attachments

(2 files)

When seeing an Alt-Svc header in nsHttpChannel::ProcessAltService(), we first copy it into a string and pass it into AltSvcMapping::ProcessHeader, which then parses the a substring after the colon character as a port into an int32_t.

Unfortunately and unlike other parts of our code (I haven't checked other uses of NS_CheckPortSafety exhaustively), this is never being range-checked to be within the valid port ranges of int16_t.

So, despite adding a test for the AltSvc case, I have taken the liberty to modify the AllowPort function. But there are multiple ways in which we could do that..

Alternatives:

  • disallow values with bits beyond the typical size right in the utility function and return false (e.g., disallowed)
  • unset the high bits (logical-and with 0xFFFF) and let it through according to the block list
  • change the function signature to expect a uint16_t

@dragana: Which of you would you prefer here? I'll attach a patch that goes with option 1, but happy to adjust.

Anecdotally, we used to have a 16-bit type with bug 95488, but a global rewrite from NSPR numeric types to stdint in bug 579517 incorrectly removed that. lolsob

I'll rate it as sec-low, might be sec-moderate under certain circumstances.

Flags: needinfo?(dd.mozilla)

Anecdotally, we used to have a 16-bit type with bug 95488, but a global rewrite from NSPR numeric types to stdint in bug 579517 incorrectly removed that. lolsob

I was reading that incorrectly. We regressed with bug 1556019.

Regressed by: 1556019
Has Regression Range: --- → yes
Keywords: regression

That bug only changes a single variable, the signature above already has uint32...

@annevk: Always had.

But we only started calling the NS_CheckPortSafety function after bug 1552993, but that parsed it as 32-bit int, so that always allowed the (badPort+0xFFFF) loophole..

(In reply to Frederik Braun [:freddy] from comment #0)

When seeing an Alt-Svc header in nsHttpChannel::ProcessAltService(), we first copy it into a string and pass it into AltSvcMapping::ProcessHeader, which then parses the a substring after the colon character as a port into an int32_t.

Unfortunately and unlike other parts of our code (I haven't checked other uses of NS_CheckPortSafety exhaustively), this is never being range-checked to be within the valid port ranges of int16_t.

So, despite adding a test for the AltSvc case, I have taken the liberty to modify the AllowPort function. But there are multiple ways in which we could do that..

Alternatives:

  • disallow values with bits beyond the typical size right in the utility function and return false (e.g., disallowed)
  • unset the high bits (logical-and with 0xFFFF) and let it through according to the block list
  • change the function signature to expect a uint16_t

@dragana: Which of you would you prefer here? I'll attach a patch that goes with option 1, but happy to adjust.

Anecdotally, we used to have a 16-bit type with bug 95488, but a global rewrite from NSPR numeric types to stdint in bug 579517 incorrectly removed that. lolsob

int32_t is use on purpose. Value -1 means "default port for a scheme" (80/443).
unsetting the higher bits will only lead to confusion.
The approach you are taking is the only option.

Flags: needinfo?(dd.mozilla)
Group: network-core-security → core-security-release
Status: ASSIGNED → RESOLVED
Closed: 4 years ago
Resolution: --- → FIXED
Target Milestone: --- → 88 Branch
Flags: qe-verify-
Whiteboard: [post-critsmash-triage]

Probably not terribly important to backport since it's only sec-low, but it does graft cleanly to ESR78. Do we want to consider backporting there?

Flags: needinfo?(fbraun)
Flags: in-testsuite+

Yeah, let's backport if it applies cleanly. The secondary effects of exploiting this bug can be worse in a busier network than in a typical end user scenario.

Flags: needinfo?(fbraun)

Please nominate this for ESR78 approval in that case :)

Flags: needinfo?(fbraun)

Comment on attachment 9209142 [details]
Bug 1698503 - robuster port blocking r=dragana

ESR Uplift Approval Request

  • If this is not a sec:{high,crit} bug, please state case for ESR consideration: The impact of exploiting this is likely higher for busier networks (e.g., enterprise secenarios)
  • User impact if declined: Missing security fix
  • Fix Landed on Version:
  • Risk to taking this patch: Medium
  • Why is the change risky/not risky? (and alternatives if risky): The fix does not break existing workflows. Ports shouldn't exceed 16 bits.
  • String or UUID changes made by this patch: None
Flags: needinfo?(fbraun)
Attachment #9209142 - Flags: approval-mozilla-esr78?

Comment on attachment 9209142 [details]
Bug 1698503 - robuster port blocking r=dragana

Approved for 78.10esr.

Attachment #9209142 - Flags: approval-mozilla-esr78? → approval-mozilla-esr78+
Whiteboard: [post-critsmash-triage] → [post-critsmash-triage][adv-main88+]
Attached file advisory.txt
Whiteboard: [post-critsmash-triage][adv-main88+] → [post-critsmash-triage][adv-main88+][adv-esr78.10+]
Alias: CVE-2021-29946
Regressions: 1708729
Group: core-security-release
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: