Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

web: base64 encode user controlled strings (#1525) #1663

Merged
merged 2 commits into from Aug 24, 2021

Conversation

ArsenArsen
Copy link
Contributor

@ArsenArsen ArsenArsen commented Aug 22, 2021

This fixes a reported Stored XSS vulnerability in toBloodhoundJson by
encoding the user-controlled values in this payload into base64 and
parsing them with atob.

In my exploration of the vulnerability with various payloads I and
others crafted, it would appear that this is the only available XSS in
hledger-web in relation to stored accounts and transaction details. If
there is other parts of the UI which may contain user-controlled data,
they should be examined for similar things. In this instance,
protections provided by yesod and other libraries worked fine, but in a
bit of code that hledger-web was generating, the user could insert a
</Script> tag (which is valid HTML and equivalent to </script> but not
caught by the T.Replace that existed in toBloodhoundJson) in order to
switch out of a script context, allowing the parser to be reset, and for
arbitrary JavaScript to run.

The real fix is a bit more involved, but produces much better results:
Content-Security-Policy headers should be introduced, and using
sha256- or a different algorithm, they should be marked
as trusted in the header. This way, if the (in-browser) parser and
hledger-web generator disagree on the source code of the script, the
script won't run. Note that this would still be susceptible to attacks
that involve changing the script by escaping from the string inside it
or something similar to that, which can be avoided additionally by using
either the method used in this commit, or a proper JSON encoder.

Test payload: </Script><svg onload=alert(1)//>

Closes #1525

@simonmichael simonmichael added the web The hledger-web tool. label Aug 22, 2021
@simonmichael
Copy link
Owner

simonmichael commented Aug 22, 2021

Thanks @ArsenArsen .

The CI failure can be fixed by adding - base64-0.4.2.3 to extra-deps: in stack8.6.yaml.

Also that package seems to have quite a few deps, including ghc-byteorder which requires cabal-version (cabal file format) 2.2, which I believe means hledger would be no longer buildable with cabal-install <2.2 (adding a new potential roadblock for installers). Debian oldstable has cabal 2.2 though, so I guess that would be ok.

There's also the base64-string package. Although older and probably unmaintained, it has no dependencies.

@simonmichael
Copy link
Owner

simonmichael commented Aug 22, 2021

Could you briefly summarise the limitations of this fix versus the "real fix" you mention ?

Your commit message passed bin/commitlint, but not quite all of our guidelines - would you mind making it fix: web: ... to help me at changelog time.

Also for the changelog, could you remind me briefly of how the vulnerability looked to users ? Eg, here's a draft:

  • An XSS (cross-site scripting) vulnerability has been fixed in hledger-web's add form.
    Previously, obfuscated javascript could be added via (the account name field ?),
    and could be executed automatically by subsequent visitors viewing (hledger-web ?)

@simonmichael
Copy link
Owner

PS if you can say without too much work which hledger version introduced the vulnerability, I'll mention that too.

@ArsenArsen
Copy link
Contributor Author

Would other GHC versions not also require the extra dep specified?

To quote the base64 readme: "There are no dependencies aside from those bundled with GHC, text-short, and the ghc-byteorder re-export".
I thought these would be rather minor. If you want, I can refactor the patch to use base64-strings, but I intended to refactor the rest of this function and its callers to use Text instead.

The second approach has the advantage of preventing further XSS, to the
extent specified above, in practice, a combination of both should be
used, b64 for embedded data and the CSP sha256-hash script-src over
everything else, which will eliminate all injected or malformed script
blocks (via CSP), in combination with eliminating any HTML closing tags
which might occur in stored data (via b64).

This vulnerability appears to have been first introduced when
autocompletion was added in hledger-web, git tag hledger-0.24, commit
hash: ec51d28

An appropriate changelog entry for this vulnerability would be:

  • An XSS vulnerability has been fixed in hledger-web. Previously, JavaScript could be added to any autocomplete-able field and could be executed automatically by subsequent visitors viewing the journal.

It's not fair to call this obfuscated JavaScript, it just uses some HTML laxness to go around an insufficient prevention previously added to the add form. And this works in any field that can be autocompleted via Bloodhound.

@ArsenArsen ArsenArsen force-pushed the master branch 2 times, most recently from 3f94269 to 00c3ef4 Compare August 24, 2021 14:42
This fixes a reported Stored XSS vulnerability in toBloodhoundJson by
encoding the user-controlled values in this payload into base64 and
parsing them with atob.

In my exploration of the vulnerability with various payloads I and
others crafted, it would appear that this is the only available XSS in
hledger-web in relation to stored accounts and transaction details. If
there is other parts of the UI which may contain user-controlled data,
they should be examined for similar things. In this instance,
protections provided by yesod and other libraries worked fine, but in a
bit of code that hledger-web was generating, the user could insert a
</Script> tag (which is valid HTML and equivalent to </script> but not
caught by the T.Replace that existed in toBloodhoundJson) in order to
switch out of a script context, allowing the parser to be reset, and for
arbitrary JavaScript to run.

The real fix is a bit more involved, but produces much better results:
Content-Security-Policy headers should be introduced, and using
sha256-<hash of script> or a different algorithm, they should be marked
as trusted in the header. This way, if the (in-browser) parser and
hledger-web generator disagree on the source code of the script, the
script won't run. Note that this would still be susceptible to attacks
that involve changing the script by escaping from the string inside it
or something similar to that, which can be avoided additionally by using
either the method used in this commit, or a proper JSON encoder.

The second approach has the advantage of preventing further XSS, to the
extent specified above, in practice, a combination of both should be
used, b64 for embedded data and the CSP sha256-hash script-src over
everything else, which will eliminate all injected or malformed script
blocks (via CSP), in combination with eliminating any HTML closing tags
which might occur in stored data (via b64).

This vulnerability appears to have been first introduced when
autocompletion was added in hledger-web, git tag hledger-0.24, commit
hash: ec51d28

Test payload: </Script><svg onload=alert(1)//>

Closes simonmichael#1525
This has the advantage of there being no extra unpacking/packing of
Data.Text to/from strings where it isn't necessary.
@simonmichael
Copy link
Owner

Great work, thanks for the vulnerability fix!

@bayegaspard
Copy link

Thank you @ArsenArsen and @simonmichael for the acknowledgement. I am wondering just for the record, can we file a CVE for the reported bug?

@simonmichael
Copy link
Owner

simonmichael commented May 5, 2023 via email

@bayegaspard
Copy link

Yes, just to record version <1.23 was vulnerable to stored XSS. I will test the recent versions soon, when I get some free time.

@bayegaspard
Copy link

bayegaspard commented May 5, 2023

We disclose vulnerabilities only when it is fixed. So now that it is fixed, we can file for CVE.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
web The hledger-web tool.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

XSS vulnerability: malicious javascript can be stored via hledger-web add/edit
3 participants