?
avatar PhilETaylor
PhilETaylor
3 Apr 2021

Steps to reproduce the issue

Possibly another release blocker.

On 7th October 2020 I reported four security issues with the com_csp to @joomla/security the JSST. Im pleased to say that most were addressed back then including invalid data storage, persistent XSS and the ability to post reports for storage when the feature was disabled.

However one still remains unresolved and as the JSST have stated they are no longer interested in private reporting of security issues for Joomla 4, and that they should be posted here, and with the recent increase in com_csp fixes, I'm posting here now.

The problem is, the new com_csp, in detect mode, allows you to post UNLIMITED times to the report endpoint

This can allow an attacker to make your database huge, and ultimately your server will run out of disk space.

There is no rate limiting on the number of rows a single IP address can create.

To replicate this:

Assumption: mySite.com is your own site. example.com is a made up domain name that can change each request.

Set up: Enable CSP with client = both or site, and Mode = detect.

Make a command line curl post:

curl --location --request POST 'http://mySite.com/index.php?option=com_csp&task=report.log&client=site' \
--data-raw '{ "csp-report": {
    "document-uri": "http://example1.com/css/style.css",
    "referrer": "",
    "blocked-uri": "http://example1.com/css/style.css.css",
    "violated-directive": "style-src cdn.mystyles.com",
    "original-policy": "default-src '\''none'\''; style-src cdn.mystyles.com; report-uri /_/csp-reports"
  }
}'

then change example1.com to example2.com and run the post again. Do this until you get to example100.com and then visit the Content Security Policy report log in Joomla admin and see all 100 reports.

Multiply this by X times... = a database that is huge, keep going, and you will eventually run out of disk space on the server.

No other place in Joomla allows the public to create unlimited rows in their database without authentication.

Possible solutions.

  1. Implement rate limiting - possibly investigate the Symfony Rate Limiter Component

  2. Implement arbitrary limits - make them up but make them sensible

  3. implement some kind of time limited checksum in the report URL advertised with each request

  4. Limit the number of reports that can ever be stored at one time. No one is ever going to need 1million reports in their database, they might never need 100... again an arbitrary limit could be guessed at

  5. read and digest https://csper.io/blog/csp-report-filtering and take any things we can learn from people that have been here before us. Eg. Blacklists "his technique alone cuts out ~50% of the weird reports."

// Tagging @brianteeman @Fedik

avatar PhilETaylor PhilETaylor - open - 3 Apr 2021
avatar joomla-cms-bot joomla-cms-bot - change - 3 Apr 2021
Labels Added: ?
avatar joomla-cms-bot joomla-cms-bot - labeled - 3 Apr 2021
avatar PhilETaylor PhilETaylor - change - 3 Apr 2021
The description was changed
avatar PhilETaylor PhilETaylor - edited - 3 Apr 2021
avatar PhilETaylor PhilETaylor - change - 3 Apr 2021
The description was changed
avatar PhilETaylor PhilETaylor - edited - 3 Apr 2021
avatar PhilETaylor PhilETaylor - change - 3 Apr 2021
The description was changed
avatar PhilETaylor PhilETaylor - edited - 3 Apr 2021
avatar PhilETaylor PhilETaylor - change - 3 Apr 2021
The description was changed
avatar PhilETaylor PhilETaylor - edited - 3 Apr 2021
avatar PhilETaylor PhilETaylor - change - 3 Apr 2021
The description was changed
avatar PhilETaylor PhilETaylor - edited - 3 Apr 2021
avatar PhilETaylor PhilETaylor - change - 3 Apr 2021
The description was changed
avatar PhilETaylor PhilETaylor - edited - 3 Apr 2021
avatar PhilETaylor PhilETaylor - change - 3 Apr 2021
The description was changed
avatar PhilETaylor PhilETaylor - edited - 3 Apr 2021
avatar brianteeman
brianteeman - comment - 3 Apr 2021

its all a waste of effort. This component is clearly not suitable for core. The fact that no one else is even testing it shows that none of the testers think its something they would use and therefore will spend time testing.

avatar PhilETaylor
PhilETaylor - comment - 3 Apr 2021

The fact that no one else is even testing it

I tested extensively in October 2020, and it was found lacking back then, as per my initial comments about the security issues I reported :-(

avatar brianteeman
brianteeman - comment - 3 Apr 2021

you were included in the people who tested and not the else ;)

For what its worth I do remember attending a presentation by scott helme at BSides a few years ago about only recording a fraction of the reports to prevent exactly what you are describing but I can't find it now.

avatar PhilETaylor
PhilETaylor - comment - 3 Apr 2021

Considering you can script this to flood the db table within seconds, only storing a fraction of those, will just delay the inevitable and not fix the issue :)

avatar brianteeman
brianteeman - comment - 3 Apr 2021

Still not found the info from the presentation but did find the solution to your reported issue by only reporting the issue for the specified host. See the description/explanation https://scotthelme.co.uk/fixing-mixed-content-with-csp/

avatar Fedik
Fedik - comment - 3 Apr 2021

I had this issue in my head also,
tbh I have no idea,

Limit the number of reports that can ever be stored at one time. No one is ever going to need 1million reports in their database, they might never need 100... again an arbitrary limit could be guessed at

yea, maybe some limitation would make sense

avatar brianteeman
brianteeman - comment - 3 Apr 2021
avatar brianteeman
brianteeman - comment - 3 Apr 2021

Interesting stat from report-uri.com

21k sites generated 517 billion reports

avatar Fedik
Fedik - comment - 3 Apr 2021

btw, if your site have enabled Redirect component and "collect 404 url", you can do very similar,
just do request with random URL every time:

http://mySite.com/blabla/nonexistingpage1
http://mySite.com/blabla/nonexistingpage2
http://mySite.com/blabla/nonexistingpage3
...
...
...
http://mySite.com/blabla/nonexistingpage1000000

No other place in Joomla allows the public to create unlimited rows in their database without authentication.

so we already have that place ?

avatar Fedik
Fedik - comment - 3 Apr 2021

Seems we need the same fix for both com_csp, and system/redirect plugin

avatar PhilETaylor
PhilETaylor - comment - 3 Apr 2021

/faceplam

avatar PhilETaylor
PhilETaylor - comment - 3 Apr 2021

The saving grace here is that both issues are disabled by default on sites and are opt-in.

avatar sandewt
sandewt - comment - 11 Apr 2021

yea, maybe some limitation would make sense

$log_file_size_limit = 1000000; // bytes - once exceeded no further entries are added

See:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/report-uri#examples

avatar PhilETaylor
PhilETaylor - comment - 11 Apr 2021

well considering we are not logging to a file, but to a database, setting a log file size makes no sense :)

avatar sandewt
sandewt - comment - 11 Apr 2021

well considering we are not logging to a file, but to a database, setting a log file size makes no sense :)

I know, but one idea often leads to another.

avatar zero-24 zero-24 - close - 4 May 2021
avatar zero-24
zero-24 - comment - 4 May 2021

CSP will be gone soon that is going to solve this issue by removing this feature all together: #33550

avatar zero-24 zero-24 - change - 4 May 2021
Status New Closed
Closed_Date 0000-00-00 00:00:00 2021-05-04 19:38:42
Closed_By zero-24

Add a Comment

Login with GitHub to post a comment