From 91e0ac8627999e1cce7108d412421f17a7c80d87 Mon Sep 17 00:00:00 2001 From: EarthlingDavey <15802017+EarthlingDavey@users.noreply.github.com> Date: Tue, 5 Nov 2024 17:24:12 +0000 Subject: [PATCH 1/6] Update Dockerfile --- Dockerfile | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Dockerfile b/Dockerfile index 1caa351c6..17a37d172 100644 --- a/Dockerfile +++ b/Dockerfile @@ -52,6 +52,12 @@ RUN rm zz-docker.conf && \ ## Set our pool configuration COPY deploy/config/php-pool.conf pool.conf +# Apend our relay config to the existing config file. +RUN { \ + echo 'relay.loglevel = error'; \ + echo 'relay.logfile = /dev/stderr'; \ + } >> /usr/local/etc/php/conf.d/docker-php-ext-relay.ini + WORKDIR /var/www/html From 0a1c17f76e5b7c292c59405c3946013ba80d5bcf Mon Sep 17 00:00:00 2001 From: EarthlingDavey <15802017+EarthlingDavey@users.noreply.github.com> Date: Tue, 5 Nov 2024 17:28:20 +0000 Subject: [PATCH 2/6] Update Dockerfile --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index 17a37d172..30b60a19e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -54,6 +54,7 @@ COPY deploy/config/php-pool.conf pool.conf # Apend our relay config to the existing config file. RUN { \ + echo 'relay.maxmemory = 16M'; \ echo 'relay.loglevel = error'; \ echo 'relay.logfile = /dev/stderr'; \ } >> /usr/local/etc/php/conf.d/docker-php-ext-relay.ini From 094296afe707c0581fbe642024a57243a4363e05 Mon Sep 17 00:00:00 2001 From: EarthlingDavey <15802017+EarthlingDavey@users.noreply.github.com> Date: Wed, 6 Nov 2024 12:26:42 +0000 Subject: [PATCH 3/6] Various logging improvements. --- Dockerfile | 6 +- deploy/config/php-pool.conf | 1 + public/app/themes/clarity/functions.php | 1 + public/app/themes/clarity/inc/security.php | 60 +++++++++++++++++-- public/app/themes/clarity/inc/updates.php | 67 ++++++++++++++++++++++ 5 files changed, 128 insertions(+), 7 deletions(-) create mode 100644 public/app/themes/clarity/inc/updates.php diff --git a/Dockerfile b/Dockerfile index 30b60a19e..25a391c00 100644 --- a/Dockerfile +++ b/Dockerfile @@ -59,6 +59,9 @@ RUN { \ echo 'relay.logfile = /dev/stderr'; \ } >> /usr/local/etc/php/conf.d/docker-php-ext-relay.ini +# Don't log every request. +RUN perl -pi -e 's#^(?=access\.log\b)#;#' /usr/local/etc/php-fpm.d/docker.conf + WORKDIR /var/www/html @@ -127,9 +130,6 @@ WORKDIR /var/www/html COPY --from=composer:2 /usr/bin/composer /usr/bin/composer -# Don't leg every request. -RUN perl -pi -e 's#^(?=access\.log\b)#;#' /usr/local/etc/php-fpm.d/docker.conf - VOLUME ["/sock"] # nginx USER 101 diff --git a/deploy/config/php-pool.conf b/deploy/config/php-pool.conf index 47e3cc3fd..06605bbb6 100644 --- a/deploy/config/php-pool.conf +++ b/deploy/config/php-pool.conf @@ -23,6 +23,7 @@ request_slowlog_timeout = 10s; slowlog = /proc/self/fd/2; [global] +log_buffering = false; daemonize = no emergency_restart_threshold = 10; emergency_restart_interval = 1m; diff --git a/public/app/themes/clarity/functions.php b/public/app/themes/clarity/functions.php index 09d607081..580965ef3 100644 --- a/public/app/themes/clarity/functions.php +++ b/public/app/themes/clarity/functions.php @@ -113,6 +113,7 @@ require_once 'inc/shortcodes.php'; require_once 'inc/security.php'; require_once 'inc/table-modification.php'; +require_once 'inc/updates.php'; require_once 'inc/uploads.php'; require_once 'inc/whitelisted-emails.php'; diff --git a/public/app/themes/clarity/inc/security.php b/public/app/themes/clarity/inc/security.php index 065b2db2a..95a0b21dd 100644 --- a/public/app/themes/clarity/inc/security.php +++ b/public/app/themes/clarity/inc/security.php @@ -2,6 +2,7 @@ namespace MOJ\Justice; +use function Env\env; use Roots\WPConfig\Config; // --------------------------------------------- @@ -13,12 +14,45 @@ */ class Security { + + /** + * A list of known hosts. + */ + private array $known_hosts = [ + 'api.deliciousbrains.com', + 'connect.advancedcustomfields.com' + ]; + + /** + * The application host e.g. intranet.docker or intranet.justice.gov.uk + */ + private string $home_host; + /** * Loads up actions that are called when WordPress initialises */ public function __construct() { + $this->home_host = parse_url(get_home_url(), PHP_URL_HOST); + $this->actions(); + + // Push the application host to known_hosts. + array_push($this->known_hosts, $this->home_host); + + // Push the OpenSearch host to known_hosts. + if ($ep_url = Config::get('EP_HOST')) { + array_push($this->known_hosts, parse_url($ep_url, PHP_URL_HOST)); + } + + // Push the S3 bucket host to known_hosts. + if ($s3_bucket = env('AWS_S3_BUCKET')) { + array_push($this->known_hosts, $s3_bucket . ".s3.eu-west-2.amazonaws.com"); + } + + if ($custom_s3_host = env('AWS_S3_CUSTOM_HOST')) { + array_push($this->known_hosts, $custom_s3_host); + } } /** @@ -34,6 +68,7 @@ public function actions(): void add_filter('wp_headers', [$this, 'headerMods']); add_filter('auth_cookie_expiration', [$this, 'setLoginPeriod'], 10, 0); add_filter('pre_http_request', [$this, 'handleLoopbackRequests'], 10, 3); + add_filter('pre_http_request', [$this, 'logUnknownHostRequests'], 10, 3); } /** @@ -90,13 +125,10 @@ public function setLoginPeriod(): float|int * @param string $url * @return false|array|\WP_Error */ - public function handleLoopbackRequests(false|array|\WP_Error $response, array $parsed_args, string $url): false|array|\WP_Error { // Is the request url to the application host? - if (parse_url($url, PHP_URL_HOST) !== parse_url(get_home_url(), PHP_URL_HOST)) { - // Request is not to the application host - log the url. - error_log('pre_http_request url: ' . $url); + if (parse_url($url, PHP_URL_HOST) !== $this->home_host) { return $response; } @@ -116,6 +148,26 @@ public function handleLoopbackRequests(false|array|\WP_Error $response, array $p // Return the result. return $http->request($new_url, $parsed_args); } + + /** + * Log the urls of requests to unknown hosts. + * + * This could be useful in identifying requests to malicious URLs. + * + * @param false|array|\WP_Error $response + * @param array $parsed_args + * @param string $url + * @return false|array|\WP_Error + */ + public function logUnknownHostRequests(false|array|\WP_Error $response, array $parsed_args, string $url): false|array|\WP_Error + { + if (!in_array(parse_url($url, PHP_URL_HOST), $this->known_hosts)) { + // Log the request url. + error_log('pre_http_request url: ' . $url); + } + + return $response; + } } new Security(); diff --git a/public/app/themes/clarity/inc/updates.php b/public/app/themes/clarity/inc/updates.php new file mode 100644 index 000000000..9d1cf2ff4 --- /dev/null +++ b/public/app/themes/clarity/inc/updates.php @@ -0,0 +1,67 @@ +hooks(); + } + + /** + * @return void + */ + public function hooks(): void + { + /** + * Prevent http requests to api.wordpress.org to check for WP core versions. + * + * Even though `AUTOMATIC_UPDATER_DISABLED` is set to true, we need to block + * requests api.wordpress.org to where WP checks for available versions. + * + * This filter's function returns a dummy payload that will prevent an api request, + * and not cause an error. + * + * @see https://wp-kama.com/2020/disable-wp-updates-check + * @see https://developer.wordpress.org/reference/functions/wp_version_check/ + */ + + add_filter( + 'pre_site_transient_update_core', + fn() => (object) [ + 'updates' => [], + 'version_checked' => $GLOBALS['wp_version'], + 'last_checked' => time() + ] + ); + + /** + * Prevent http requests to api.wordpress.org to check for theme updates. + * + * This filter's function returns a dummy payload that will prevent an api request, + * and not cause an error. + * + * @see https://wp-kama.com/2020/disable-wp-updates-check + * @see https://developer.wordpress.org/reference/functions/wp_update_themes/ + */ + + add_filter('pre_site_transient_update_themes', static function ($value) { + static $theme; + + $theme || $theme = wp_get_theme('clarity'); + + return (object) [ + 'last_checked' => time(), + 'checked' => [ + 'clarity' => $theme->get('Version') + ] + ]; + }); + } +} + +new Updates(); From 064798068ada24614f5971c0ea13077ca956163e Mon Sep 17 00:00:00 2001 From: EarthlingDavey <15802017+EarthlingDavey@users.noreply.github.com> Date: Wed, 6 Nov 2024 12:32:37 +0000 Subject: [PATCH 4/6] Update updates.php --- public/app/themes/clarity/inc/updates.php | 28 ++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/public/app/themes/clarity/inc/updates.php b/public/app/themes/clarity/inc/updates.php index 9d1cf2ff4..4c07fd512 100644 --- a/public/app/themes/clarity/inc/updates.php +++ b/public/app/themes/clarity/inc/updates.php @@ -40,7 +40,7 @@ public function hooks(): void ); /** - * Prevent http requests to api.wordpress.org to check for theme updates. + * Prevent http requests to api.wordpress.org to check for theme version. * * This filter's function returns a dummy payload that will prevent an api request, * and not cause an error. @@ -61,6 +61,32 @@ public function hooks(): void ] ]; }); + + /** + * Prevent http requests to api.wordpress.org to check for plugin versions. + * + * This filter's function returns a dummy payload that will prevent an api request, + * and not cause an error. + * + * @see https://wp-kama.com/2020/disable-wp-updates-check + * @see https://developer.wordpress.org/reference/functions/wp_update_plugins/ + */ + + add_filter('pre_site_transient_update_plugins', static function ($value) { + static $plugins; + $plugins || $plugins = get_plugins(); + + $return_value = (object) [ + 'last_checked' => time(), + 'checked' => [] + ]; + + foreach ($plugins as $file => $p) { + $return_value->checked[$file] = $p['Version']; + } + + return $return_value; + }); } } From 5e1e87639ce5cc7531eacd2f24ffec5da42e7651 Mon Sep 17 00:00:00 2001 From: EarthlingDavey <15802017+EarthlingDavey@users.noreply.github.com> Date: Wed, 6 Nov 2024 12:37:42 +0000 Subject: [PATCH 5/6] Update docker-compose.yml --- docker-compose.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docker-compose.yml b/docker-compose.yml index b0a5bd37a..e705db3de 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -17,6 +17,8 @@ services: volumes: - .:/var/www/html - php-socket:/sock + ### Deploy scripts + - ./deploy/config/php-pool.conf:/usr/local/etc/php-fpm.d/pool.conf env_file: - .env depends_on: From e814e5d7a7ad67f0d44137ba78b1ffe69161b8ce Mon Sep 17 00:00:00 2001 From: EarthlingDavey <15802017+EarthlingDavey@users.noreply.github.com> Date: Wed, 6 Nov 2024 12:55:28 +0000 Subject: [PATCH 6/6] Update updates.php --- public/app/themes/clarity/inc/updates.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/public/app/themes/clarity/inc/updates.php b/public/app/themes/clarity/inc/updates.php index 4c07fd512..4f5970b12 100644 --- a/public/app/themes/clarity/inc/updates.php +++ b/public/app/themes/clarity/inc/updates.php @@ -29,7 +29,6 @@ public function hooks(): void * @see https://wp-kama.com/2020/disable-wp-updates-check * @see https://developer.wordpress.org/reference/functions/wp_version_check/ */ - add_filter( 'pre_site_transient_update_core', fn() => (object) [ @@ -48,7 +47,6 @@ public function hooks(): void * @see https://wp-kama.com/2020/disable-wp-updates-check * @see https://developer.wordpress.org/reference/functions/wp_update_themes/ */ - add_filter('pre_site_transient_update_themes', static function ($value) { static $theme; @@ -71,7 +69,6 @@ public function hooks(): void * @see https://wp-kama.com/2020/disable-wp-updates-check * @see https://developer.wordpress.org/reference/functions/wp_update_plugins/ */ - add_filter('pre_site_transient_update_plugins', static function ($value) { static $plugins; $plugins || $plugins = get_plugins();