Lucene search

K
wallarmlabWlrmblogWALLARMLAB:FDC5DBAD6464940DF2F74AAB95289D21
HistoryMar 03, 2021 - 7:54 p.m.

Grammarly fixed XSS vulnerability that bypasses AWS WAF

2021-03-0319:54:16
wlrmblog
lab.wallarm.com
43

9.8 High

CVSS3

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

7.5 High

CVSS2

Access Vector

NETWORK

Access Complexity

LOW

Authentication

NONE

Confidentiality Impact

PARTIAL

Integrity Impact

PARTIAL

Availability Impact

PARTIAL

AV:N/AC:L/Au:N/C:P/I:P/A:P

Grammarly is the unicorn company that announced its open bug bounty program last September. Since that time, many security researchers posted their submissions and got paid well. Some of Grammarly's issues are also useful for others. Like the recent XSS, that also bypasses an AWS WAF.

The recent XSS report is a bit different among others. First of all, it was submitted by Frans Rosen, one of the top HackerOne hackers. He is the 6th for the all-time rank.

Secondly, the report was paid for $3000 unlike tons of $50-100 XSSes on a platform.

The report title is: "Config override using non-validated query parameter allows at least reflected XSS by injecting configuration into state" <https://hackerone.com/reports/1082847&gt;

screenshot Frans report

This security issue is an excellent example of in-depth JavaScript research that Frans did.

Moreover, for some reason, an XSS payload that Frans used to validate this Grammarly vulnerability bypasses AWS WAF.

Let's understand why.

The payload look like a very usual XSS for the first glance:

https://app.grammarly.com/docs/new?config={%22account%22:{%22subscription%22:%22javascript:alert(document.domain)//%22},%22api%22:{%22redirect%22:%22javascript:alert(document.domain)//%22}}

It consists of a JSON-encoded config parameter that vulnerable application parse. JSON attributes subscription and redirect contains an ordinary XSS sample of alert() function call. And if we will send this request to check how does the mod_security WAF detects it, we will get the following:

2021/03/03 01:10:44 [error] 41#41: *1 [client 172.17.0.1] ModSecurity: Access denied with code 403 (phase 2). Matched "Operator `Ge' with parameter `5' against variable `TX:ANOMALY_SCORE' (Value: `28' ) [file "/etc/modsecurity.d/owasp-crs/rules/REQUEST-949-BLOCKING-EVALUATION.conf"] [line "80"] [id "949110"] [rev ""] [msg "Inbound Anomaly Score Exceeded (Total Score: 28)"] [data ""] [severity "2"] [ver "OWASP_CRS/3.2.0"] [maturity "0"] [accuracy "0"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-generic"] [hostname "172.17.0.1"] [uri "/docs/new"] [unique_id "161473384455.381362"] [ref ""], client: 172.17.0.1, server: localhost, request: "GET /docs/new?config={%22account%22:{%22subscription%22:%22javascript:alert(document.domain)//%22},%22api%22:{%22redirect%22:%22javascript:alert(document.domain)//%22}} HTTP/1.1", host: "localhost:8080"

At the same time, AWS WAF will pass this payload with no blocking:

payload with JSON

But, if we will remove the JSON object and use the same payload in a plain text way, AWS WAF will block it:

payload without JSON

An attentive reader may notice that we modified the payload by adding onerror attribute to make this payload work in HTML attribute injection way. That's true, but now we can add the JSON prefix back and see what happens:

 payload with JSON prefix

It passed! We basically found that adding JSON prefixes before payloads makes them invisible for AWS WAF. Let's understand what happened and why.

We initially decided that the reason for this bypass is behind the JSON parser. As we already discussed recently in a post WAF JSON decoding capability required to protect against API threats like CVE-2020-13942 Apache Unomi RCE

But it was not even close since AWS WAF has no JSON parsing capabilities at all.

After minifying Grammarly payload, we will get that the following request will be blocked by AWS WAF:

After minifying Grammarly payload

But adding just one additional double quote into there bypass the WAF:

payload adding one additional double quote

The reason is not in JSON-like prefix, but the double-quote itself. We can easily remove the bracer charter and get the same bypass result with the payload ""onerror=javascript:alert('I-LOVE-AWS-WAF!').

It seems irrational but adding any numbers of double quotes before an XSS payloads bypass AWS WAF. We tested on 1500 rules enabled

tested on 1500 rules enabled

Please leave a comment if you have an idea why. Thanks for reading!

The post Grammarly fixed XSS vulnerability that bypasses AWS WAF appeared first on Wallarm.

9.8 High

CVSS3

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

7.5 High

CVSS2

Access Vector

NETWORK

Access Complexity

LOW

Authentication

NONE

Confidentiality Impact

PARTIAL

Integrity Impact

PARTIAL

Availability Impact

PARTIAL

AV:N/AC:L/Au:N/C:P/I:P/A:P