Go to main content

Textpattern CMS support forum

You are not logged in. Register | Login | Help

#1 2022-10-26 13:23:17

jakob
Admin
From: Germany
Registered: 2005-01-20
Posts: 4,412
Website

CSP and nonces?

Yiannis has been educating me in the adoption of CSP rules which I have (probably woefully) neglected in the past. I find getting a working configuration a bit hit and miss and what we’ve got working in the end (with some help from report-uri.com/home/generate), while accepted by the W3C validator, is still marked as containing unsafe directives by csp-evaluator.withgoogle.com.

It seems we need to specify permitted nonces in the header and corresponding matching nonces in the css link and js script tags so that we may retire 'inline_unsafe' etc.

They’ve been a few threads on the forum and on GitHub (in which Stef says it’s quite straightforward) and I can see that the Textpattern 4.9 comes with that functionality built in here and here. I also see it mentioned in detail in config.dist here in the dev branch.

Is there something we can already use with txp 4.8.8 and can anyone suggest the best way to go about it? At present our CSP headers are set in htaccess but the config.dist sample seems to suggest there’s another way. If it’s any help, the css and js files that are loaded change from the time to time, but the few instances of inline js/css rarely.


TXP Builders – finely-crafted code, design and txp

Offline

#2 2022-10-27 08:47:14

phiw13
Plugin Author
From: Japan
Registered: 2004-02-27
Posts: 2,759
Website

Re: CSP and nonces?

Yeah, securing the /textpattern is currently (TXP 4.8.8) really hard. The inline style part, esp attributes, is probably possible, it is mostly style="display:none" and style="display:none; (yay, both…!) for which generating a hash is easy and possible to include in a style-src-attr attribute. For the style-src-elem you need to add the unsafe-inline – so many <style /> blocks.

Most plugins I use don’t use other style attribute, I think – or I may have patched them.
You still need to include unsafe-inline in the style-src directive for Firefox.

For scripts either esp attributes it is a mess… for example, onclick="return verify('Are you sure?')"
Sure you can (currently) generate a hash for this, but then you realise, the string is localised and one of the authors speaks and uses e.g. French. etc etc etc.

So what I do is a separate CSP set for /textpattern, and safer/stricter CSP rules for the public site.

As you note, current TXP 4.9(dev) offer some serious options for the back-end especially.

–^–

Thought: would it be an idea to have sooner rather that later a TXP 4.9 release with what is currently in dev + some eventual patches for PHP 8.2 ? There is some interesting stuff already. Feasible ?

(and postpone the custom-field work for a later, 5.0 release ?)

There are probably/certainly bugs to be fixed and some polish work as well.


Where is that emoji for a solar powered submarine when you need it ?

Offline

#3 2022-10-27 09:34:28

colak
Admin
From: Cyprus
Registered: 2004-11-20
Posts: 8,905
Website GitHub Twitter

Re: CSP and nonces?

I think that we should go the htaccess way!

I already did some basic additions in the /textpattern/.htaccess to deal with 2 issues.

  1. A persistent cache issue, which loads previous states of the loaded pages
  2. An issue which I mentioned some time ago with the article preview that loads external content such as iframes.

The added code:

Header always set Referrer-Policy "no-referrer"

<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType text/html "access plus 1 minute"
ExpiresDefault "access plus 1 month"
</IfModule>

The above are not thoroughly tested yet and have no idea if they will break anything!!!


Yiannis
——————————
neme.org | hblack.net | EMAP | A Sea change | NeMe @ github
I do my best editing after I click on the submit button.

Online

#4 2022-10-27 10:41:03

jakob
Admin
From: Germany
Registered: 2005-01-20
Posts: 4,412
Website

Re: CSP and nonces?

Thank you, both of you. My question was more about how to generate matching nonces (or possibly a hash) for the front end so that unsafe_inline can be dropped from the CSP directives.

You made me realize, though, that I probably haven’t thought about the implications that might have for the admin-side. Presumably if one adds stricter CSP directives to the htaccess in the web root, one (currently) needs to add a separate htaccess in the /textpattern directory that relaxes them again, at least for txp 4.8.8.

I think that we should go the htaccess way!

If I’ve understood the principle of nonces correctly, the nonce must be generated anew for each page request and sent as a CSP header and inserted into the respective link and script tag as a nonce="…" attribute so that they match. That wouldn’t work with a fixed value set in .htaccess.

From a bit of cursory research, it seems there would be two approaches (maybe more?):

  1. Have Apache dynamically generate a unique id for the nonce with each page request and pass that via the global $_SERVER variable so that can be referenced in .htaccess and in one’s HTML code. See this stackoverflow thread. For that the server needs to include a module as part of the apache setup. That thread mentions mod_unique_id and mod_cspnonce as two possible options. If our server can be made to include these, this option looks “relatively straightforward” (famous last words) to implement. I guess that is host-dependent.
     
  2. Have Textpattern generate a unique id with each page request and send that as a content header via PHP and include that in one’s HTML code. I presume that is the string that is mentioned in config-dist here which is then replaced by the actual key stored in the global variable $csp_nonce (generated here in txp 4.9) and sent as a header via PHP here (admin-side in this case). One would then reference and insert $csp_nonce into one’s html as needed, e.g. as <txp:php>global $csp_nonce; echo " nonce="' . $csp_nonce . '"';</txp:php>. That’s as far as I got with my sleuthing.

It looks like “/Textpattern/Password/Random” does already exist in 4.8.8. so maybe once can emulate this second approach for the public-facing site already on 4.8.8? Are the settings mentioned in config-dist also picked up on in 4.8.8?

I don’t know which variant is “better” but the second is, I guess, more portable as it doesn’t depend on the server settings.


TXP Builders – finely-crafted code, design and txp

Offline

#5 2022-10-27 10:49:30

Bloke
Developer
From: Leeds, UK
Registered: 2006-01-29
Posts: 10,790
Website GitHub

Re: CSP and nonces?

jakob wrote #334034:

It looks like “/Textpattern/Password/Random” does already exist in 4.8.8.

Yes.

so maybe once can emulate this second approach for the public-facing site already on 4.8.8?

Yes. All you really need is a line to generate the nonce and then maybe use <txp:header> to send it? Not tried it, but can’t see a reason it wouldn’t work as implied with the mentioned plugin and its detail. Stick a token into a Txp variable as part of your template in the first line, before anything is sent to the browser, and it might work. You could write the token generation as a shortcode instead of a plugin if you wished. Compartmentalise it that way (even though it requires a single line of PHP).

Maybe even create a shortcode add_script which takes the name of the script you want, generates a token and sets everything up ready for you to output the script tag via another shortcode later or something?

Are the settings mentioned in config-dist also picked up on in 4.8.8?

I doubt it. They were specifically added to 4.9, iirc.

Last edited by Bloke (2022-10-27 10:53:24)


The smd plugin menagerie — for when you need one more gribble of power from Textpattern. Bleeding-edge code available on GitHub.

Txp Builders – finely-crafted code, design and Txp

Offline

#6 2022-10-27 11:13:33

phiw13
Plugin Author
From: Japan
Registered: 2004-02-27
Posts: 2,759
Website

Re: CSP and nonces?

jakob wrote #334034:

Thank you, both of you. My question was more about how to generate matching nonces (or possibly a hash) for the front end so that unsafe_inline can be dropped from the CSP directives.

A hash is rather easy to generate at the command line; it has the disadvantage of being a little static. Assuming you want to generate a hash for a style attribute (style="display:none;") – (one doc ):

echo -n 'display:none;' | openssl sha256 -binary | openssl base64

You made me realize, though, that I probably haven’t thought about the implications that might have for the admin-side. Presumably if one adds stricter CSP directives to the htaccess in the web root, one (currently) needs to add a separate htaccess in the /textpattern directory that relaxes them again, at least for txp 4.8.8.

Yes. What you put in an htaccess at the root level will affect everywhere on your site. That why I mentioned I use a looser CSP policy for /textpattern, in a separate htaccess inside /textpattern.


Where is that emoji for a solar powered submarine when you need it ?

Offline

#7 2022-11-01 09:28:59

philwareham
Core designer
From: Haslemere, Surrey, UK
Registered: 2009-06-11
Posts: 3,555
Website GitHub Mastodon

Re: CSP and nonces?

There is a lengthy discussion here about CSP and hashes/nonces which might help.

Offline

#8 2022-11-15 17:44:58

jakob
Admin
From: Germany
Registered: 2005-01-20
Posts: 4,412
Website

Re: CSP and nonces?

Just closing the loop here … at least partially.

colak wrote #334032:

I think that we should go the htaccess way!

OK: The htaccess way

If an Apache server includes mod_unique_id, it will generate a unique identifier with each page request which can be used for a nonce.* How do you find out if your server supports this?

  • Under Admin › Diagnostics click on PHP Configuration to open the PHPINFO page of the server.
  • Search for “Unique” and if your server generates a unique id, you should find the entry $_SERVER['UNIQUE_ID'] along with a corresponding value. Reload the page and that value updates.
    I was pleasantly surprised to see this was already the case on my cheap local shared host and on the server where the website is.

There are two parts to implementing CSP nonces as described on MDN and here: Background information on using a nonce with CSP.

Setting the CSP nonce value in your .htaccess file

As part of your Content-Security-Policy directives, include the following line:

<IfModule mod_headers.c>
         ... your other Header settings ...
         Header set Content-Security-Policy: "\
         ... your other CSP directives ... \
         script-src 'strict-dynamic' 'nonce-%{UNIQUE_ID}e' 'unsafe-inline' https:;"
</IfModule>

This will include the nonce in the CSP directives. Retaining 'unsafe-inline' and https: ensures compatibility with older browsers but newer browsers will override those with the stricter rule (in some browsers you see a corresponding message in the browser inspector dev console).

IMPORTANT NOTE: For versions of Textpattern less than 4.9, nonces are not yet supported for the admin side. To ensure you don’t block javascript on the admin-side, you must add corresponding more relaxed CSP directives to the /textpattern/.htaccess file. As far as I am aware, you must repeat all the CSP directives you need for the admin-area, you can’t just relax individual lines. From version 4.9 onwards this may not be necessary.

Inserting the corresponding nonce in your code

Somewhere at the top of your page, save the unique id produced by the server as a Textpattern variable, e.g.

<txp:variable name="server_unique_id"><txp:php>echo $_SERVER['UNIQUE_ID'];</txp:php></txp:variable>

You can now use this variable in your code wherever you have a script tag to add a nonce, for example:

<script nonce="<txp:variable name="server_unique_id" />">
        document.documentElement.className = document.documentElement.className.replace('no-js', 'js');
</script>

The nonce changes with each page request and you can verify that in your HTML page source. <script>…</script> tags without a nonce will be blocked by the browser.

Overall, this is quite straightforward to implement. However, it’s worth bearing in mind that you are setting up a dependency between your code and the server providing the corresponding unique_id. If an update to the server stops producing that, or you relocate your code to a server that doesn’t generate a unique_id, your scripts will stop loading.

If you want to be independent of such dependencies, you can generate the nonce and the corresponding headers within Textpattern. But that’s a tutorial for another day -> see the GitHub thread linked in the post above.

*From reading around, it seems that a unique_id is not as good as a truly random nonce, but that it is better than leaving the gate open with ‘unsafe-inline’.


TXP Builders – finely-crafted code, design and txp

Offline

#9 2022-11-15 18:02:30

jakob
Admin
From: Germany
Registered: 2005-01-20
Posts: 4,412
Website

Re: CSP and nonces?

Some more notes:

And, as posted at the beginning of the thread, you can get useful feedback on your CSP directives at csp-evaluator.withgoogle.com

Improvements to the above mini-tutorial and information on other webservers welcome!


TXP Builders – finely-crafted code, design and txp

Offline

#10 2022-11-16 00:05:53

phiw13
Plugin Author
From: Japan
Registered: 2004-02-27
Posts: 2,759
Website

Re: CSP and nonces?

Thanks for that info! I see that my own host and the host for one client both have that Apache module enabled. I’ll have to experiment now… (for my personal site(s) ist does not matter much as I organise things to have all JS in external files. For the client it might be helpful to close the unsafe-inline hole.

Hmm the mod_unique_id module is not enabled on my localhost server. need to dive in httpd.conf I think.

As for the /textpattern folder, you’ll need indeed an .htaccess file with all settings needed. For Textpattern.next you won’t need it if you use the build-in mechanism, that would overwrite the htaccess based setting. If you use the same mechanism for both public and admin side then you have no need for the .htaccess anymore.


Where is that emoji for a solar powered submarine when you need it ?

Offline

#11 2022-11-16 17:16:27

colak
Admin
From: Cyprus
Registered: 2004-11-20
Posts: 8,905
Website GitHub Twitter

Re: CSP and nonces?

I know I’m guilty of opening a can of worms, but I wish Safari and ff were supporting more of the CSP directives. At the moment, whatever we do is mostly for Chrome and Opera.


Yiannis
——————————
neme.org | hblack.net | EMAP | A Sea change | NeMe @ github
I do my best editing after I click on the submit button.

Online

#12 2022-11-16 23:22:21

phiw13
Plugin Author
From: Japan
Registered: 2004-02-27
Posts: 2,759
Website

Re: CSP and nonces?

colak wrote #334139:

I know I’m guilty of opening a can of worms, but I wish Safari and ff were supporting more of the CSP directives. At the moment, whatever we do is mostly for Chrome and Opera.

I am not sure what your complain about Safari is, as it supports most of what Chromium supports – certainly since Safari 15. Firefox still lags behind, though, and I have the impression that the security & network people at Mozilla are not convinced at all about the utility of some of the directives.

Edit

I should add: Safari’s support for some directive is not always complete. For example, Safari 15+ supports the style-src-elem directive. If used, it will block a <style /> block but will not block the use of an external stylesheet (see for example, here for docs.textpattern.com). But supports for the latter in Chromium is very recent.

Note also that the specification is constantly evolving, with Chromium sometimes implementing things without really waiting for consensus (ahem… understatement….).

End Edit.

–^–

After enabling mod_unique_id in httpd.conf, my local server now hums along well to experiment with setting nonces.

–^–

While searching around how people implement the use of unique_id for this, I came across one comment (sorry, lost the URL, one of the numerous StackOverflow posts) that mentioned that the server generated string sometimes contains the @ character, and browsers reject that string as invalid nonces. That post was not recent-recent and did not contain any reference, as far as I can remember. Perhaps the Apache folks have updated their string generation since then. But the possibility exists that the nonces fail and the script(s) are blocked – very sometimes though.

Last edited by phiw13 (2022-11-17 00:26:08)


Where is that emoji for a solar powered submarine when you need it ?

Offline

Board footer

Powered by FluxBB