From dafb6d927c1c111a773a4a5efcb59a57dce968f2 Mon Sep 17 00:00:00 2001 From: Bogdan Preda Date: Wed, 17 Apr 2024 13:40:31 +0300 Subject: [PATCH 1/7] fix: only allow admin and select References: Codeinwp/visualizer-pro#433 --- .gitignore | 3 ++- classes/Visualizer/Module/Chart.php | 2 +- classes/Visualizer/Source/Query.php | 2 +- tests/test-ajax.php | 16 +++++++++++++++- 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 95d782cfc..5014b47d4 100755 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,5 @@ cypress.env.json .DS_Store /cypress/videos/ /cypress/screenshots/ -artifacts \ No newline at end of file +artifacts +.phpunit.result.cache diff --git a/classes/Visualizer/Module/Chart.php b/classes/Visualizer/Module/Chart.php index 4b536731d..b2fa6312f 100644 --- a/classes/Visualizer/Module/Chart.php +++ b/classes/Visualizer/Module/Chart.php @@ -1421,7 +1421,7 @@ private function _handleDataPage() { public function getQueryData() { check_ajax_referer( Visualizer_Plugin::ACTION_FETCH_DB_DATA . Visualizer_Plugin::VERSION, 'security' ); - if ( ! current_user_can( 'edit_posts' ) ) { + if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( array( 'msg' => __( 'Action not allowed for this user.', 'visualizer' ) ) ); } diff --git a/classes/Visualizer/Source/Query.php b/classes/Visualizer/Source/Query.php index 61a90a6fb..7e4d750ea 100644 --- a/classes/Visualizer/Source/Query.php +++ b/classes/Visualizer/Source/Query.php @@ -80,7 +80,7 @@ public function fetch( $as_html = false, $results_as_numeric_array = false, $raw } // only select queries allowed. - if ( preg_match( '/\s*(\binsert\b|\bdelete\b|\bupdate\b|\breplace\b|\bcreate\b|\balter\b|\bdrop\b|\btruncate\b)\s/i', $this->_query ) ) { + if ( ! preg_match( '/\s*(\bselect\b)\s/i', $this->_query ) ) { $this->_error = __( 'Only SELECT queries are allowed', 'visualizer' ); return false; } diff --git a/tests/test-ajax.php b/tests/test-ajax.php index 85323f3ac..52f423bd1 100644 --- a/tests/test-ajax.php +++ b/tests/test-ajax.php @@ -20,10 +20,17 @@ class Test_Visualizer_Ajax extends WP_Ajax_UnitTestCase { */ private $admin_user_id; + /** + * Subscriber user ID. + * + * @var int + */ + private $subscriber_user_id; + /** * Set up. */ - public function setUp() { + public function setUp(): void { parent::setUp(); $this->admin_user_id = $this->factory->user->create( array( @@ -32,6 +39,12 @@ public function setUp() { ); wp_set_current_user( $this->admin_user_id ); + $this->subscriber_user_id = $this->factory->user->create( + array( + 'role' => 'subscriber', + ) + ); + } /** @@ -117,6 +130,7 @@ public function test_ajax_response_get_query_data_valid_query_with_filtered_colu * Test the AJAX response for fetching the database data with user capability. */ public function test_ajax_response_get_query_data_subcriber_dissallow() { + wp_set_current_user( $this->subscriber_user_id ); $this->_setRole( 'subscriber' ); $_GET['security'] = wp_create_nonce( Visualizer_Plugin::ACTION_FETCH_DB_DATA . Visualizer_Plugin::VERSION ); From 9a2cc2f38a9eaa6c6424e93943a5abe7fc03b342 Mon Sep 17 00:00:00 2001 From: Bogdan Preda Date: Wed, 17 Apr 2024 13:41:25 +0300 Subject: [PATCH 2/7] chore: code style --- tests/test-ajax.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test-ajax.php b/tests/test-ajax.php index 52f423bd1..3d882b685 100644 --- a/tests/test-ajax.php +++ b/tests/test-ajax.php @@ -30,7 +30,7 @@ class Test_Visualizer_Ajax extends WP_Ajax_UnitTestCase { /** * Set up. */ - public function setUp(): void { + public function setUp() { parent::setUp(); $this->admin_user_id = $this->factory->user->create( array( From a2c7e075c794c0c38d1cef5a6197d57084901513 Mon Sep 17 00:00:00 2001 From: Bogdan Preda Date: Wed, 17 Apr 2024 13:46:17 +0300 Subject: [PATCH 3/7] chore: improved test --- tests/test-ajax.php | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/tests/test-ajax.php b/tests/test-ajax.php index 3d882b685..6234ea53d 100644 --- a/tests/test-ajax.php +++ b/tests/test-ajax.php @@ -20,6 +20,13 @@ class Test_Visualizer_Ajax extends WP_Ajax_UnitTestCase { */ private $admin_user_id; + /** + * Contributor user ID. + * + * @var int + */ + private $contibutor_user_id; + /** * Subscriber user ID. * @@ -39,6 +46,12 @@ public function setUp() { ); wp_set_current_user( $this->admin_user_id ); + $this->contibutor_user_id = $this->factory->user->create( + array( + 'role' => 'contributor', + ) + ); + $this->subscriber_user_id = $this->factory->user->create( array( 'role' => 'subscriber', @@ -126,6 +139,34 @@ public function test_ajax_response_get_query_data_valid_query_with_filtered_colu $this->assertTrue( $response->success ); } + /** + * Test the AJAX response for fetching the database data with user capability. + */ + public function test_ajax_response_get_query_data_contributor_dissallow() { + wp_set_current_user( $this->contibutor_user_id ); + $this->_setRole( 'contributor' ); + + $_GET['security'] = wp_create_nonce( Visualizer_Plugin::ACTION_FETCH_DB_DATA . Visualizer_Plugin::VERSION ); + + $_POST['params'] = array( + 'query' => "/**/UPDATE wp_options SET option_value='administrator' WHERE option_name='default_role' --", + 'chart_id' => 1, + ); + try { + // Trigger the AJAX action + $this->_handleAjax( Visualizer_Plugin::ACTION_FETCH_DB_DATA ); + } catch ( WPAjaxDieContinueException $e ) { + // We expected this, do nothing. + } + + $response = json_decode( $this->_last_response ); + $this->assertIsObject( $response ); + $this->assertObjectHasAttribute( 'success', $response ); + $this->assertObjectHasAttribute( 'data', $response ); + $this->assertEquals( 'Action not allowed for this user.', $response->data->msg ); + $this->assertFalse( $response->success ); + } + /** * Test the AJAX response for fetching the database data with user capability. */ From b2a3d8e9811389141b994aac5fa8cb275d8ec78e Mon Sep 17 00:00:00 2001 From: Bogdan Preda Date: Wed, 17 Apr 2024 14:45:36 +0300 Subject: [PATCH 4/7] chore: improved query filtering --- classes/Visualizer/Source/Query.php | 36 +++++++++++++++++++++++++++++ tests/test-ajax.php | 27 ++++++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/classes/Visualizer/Source/Query.php b/classes/Visualizer/Source/Query.php index 7e4d750ea..0d445710b 100644 --- a/classes/Visualizer/Source/Query.php +++ b/classes/Visualizer/Source/Query.php @@ -85,6 +85,42 @@ public function fetch( $as_html = false, $results_as_numeric_array = false, $raw return false; } + // if previous check passed, check for disallowed query parts to prevent subqueries and other harmful queries. + $disallow_query_parts = array( + 'INSERT', + 'UPDATE', + 'DELETE', + 'RENAME', + 'DROP', + 'CREATE', + 'TRUNCATE', + 'ALTER', + 'COMMIT', + 'ROLLBACK', + 'MERGE', + 'CALL', + 'EXPLAIN', + 'LOCK', + 'GRANT', + 'REVOKE', + 'SAVEPOINT', + 'TRANSACTION', + 'SET', + ); + $disallow_regex = implode( + '|', + array_map( + function ( $value ) { + return '\b' . $value . '\b'; + }, $disallow_query_parts + ) + ); + + if ( preg_match( '/(' . $disallow_regex . ')/i', $this->_query) !== 0 ) { + $this->_error = __( 'Only SELECT queries are allowed', 'visualizer' ); + return false; + } + // impose a limit if no limit clause is provided. if ( strpos( strtolower( $this->_query ), ' limit ' ) === false ) { $this->_query .= ' LIMIT ' . apply_filters( 'visualizer_sql_query_limit', 1000, $this->_chart_id ); diff --git a/tests/test-ajax.php b/tests/test-ajax.php index 6234ea53d..8a37705a7 100644 --- a/tests/test-ajax.php +++ b/tests/test-ajax.php @@ -194,4 +194,31 @@ public function test_ajax_response_get_query_data_subcriber_dissallow() { $this->assertEquals( 'Action not allowed for this user.', $response->data->msg ); $this->assertFalse( $response->success ); } + + /** + * Test the AJAX response for fetching the database data with invalid query. + */ + public function test_ajax_response_get_query_data_invalid_query_subquery() { + $this->_setRole( 'administrator' ); + + $_GET['security'] = wp_create_nonce( Visualizer_Plugin::ACTION_FETCH_DB_DATA . Visualizer_Plugin::VERSION ); + + $_POST['params'] = array( + 'query' => "UPDATE wp_options SET option_value = ( SELECT role_name FROM role_configurations WHERE condition = 'specific_condition' LIMIT 1 )WHERE option_name = 'default_role';", + 'chart_id' => 1, + ); + try { + // Trigger the AJAX action + $this->_handleAjax( Visualizer_Plugin::ACTION_FETCH_DB_DATA ); + } catch ( WPAjaxDieContinueException $e ) { + // We expected this, do nothing. + } + + $response = json_decode( $this->_last_response ); + $this->assertIsObject( $response ); + $this->assertObjectHasAttribute( 'success', $response ); + $this->assertObjectHasAttribute( 'data', $response ); + $this->assertEquals( 'Only SELECT queries are allowed', $response->data->msg ); + $this->assertFalse( $response->success ); + } } From 06ebcceea17fe036b950b985882aa9dc4827e405 Mon Sep 17 00:00:00 2001 From: Bogdan Preda Date: Wed, 17 Apr 2024 15:04:53 +0300 Subject: [PATCH 5/7] chore: change user capability check --- classes/Visualizer/Module/Chart.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/classes/Visualizer/Module/Chart.php b/classes/Visualizer/Module/Chart.php index b2fa6312f..6ee20777b 100644 --- a/classes/Visualizer/Module/Chart.php +++ b/classes/Visualizer/Module/Chart.php @@ -1421,7 +1421,7 @@ private function _handleDataPage() { public function getQueryData() { check_ajax_referer( Visualizer_Plugin::ACTION_FETCH_DB_DATA . Visualizer_Plugin::VERSION, 'security' ); - if ( ! current_user_can( 'manage_options' ) ) { + if ( ! current_user_can( 'administrator' ) ) { wp_send_json_error( array( 'msg' => __( 'Action not allowed for this user.', 'visualizer' ) ) ); } From 350385c1630a389c069766691ec65dc5f9571a01 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Apr 2024 23:41:20 +0000 Subject: [PATCH 6/7] chore(deps): bump codeinwp/themeisle-sdk from 3.3.18 to 3.3.20 Bumps [codeinwp/themeisle-sdk](https://github.com/Codeinwp/themeisle-sdk) from 3.3.18 to 3.3.20. - [Release notes](https://github.com/Codeinwp/themeisle-sdk/releases) - [Changelog](https://github.com/Codeinwp/themeisle-sdk/blob/master/CHANGELOG.md) - [Commits](https://github.com/Codeinwp/themeisle-sdk/compare/v3.3.18...v3.3.20) --- updated-dependencies: - dependency-name: codeinwp/themeisle-sdk dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- composer.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/composer.lock b/composer.lock index 1c5b1a902..823c08f4b 100644 --- a/composer.lock +++ b/composer.lock @@ -8,16 +8,16 @@ "packages": [ { "name": "codeinwp/themeisle-sdk", - "version": "3.3.18", + "version": "3.3.20", "source": { "type": "git", "url": "https://github.com/Codeinwp/themeisle-sdk.git", - "reference": "5463d7170ed7b9735223d6715442b8670a477688" + "reference": "d1b92f3ab74f1b3f0afad7e23ddb1c058d66c03c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Codeinwp/themeisle-sdk/zipball/5463d7170ed7b9735223d6715442b8670a477688", - "reference": "5463d7170ed7b9735223d6715442b8670a477688", + "url": "https://api.github.com/repos/Codeinwp/themeisle-sdk/zipball/d1b92f3ab74f1b3f0afad7e23ddb1c058d66c03c", + "reference": "d1b92f3ab74f1b3f0afad7e23ddb1c058d66c03c", "shasum": "" }, "require-dev": { @@ -42,9 +42,9 @@ ], "support": { "issues": "https://github.com/Codeinwp/themeisle-sdk/issues", - "source": "https://github.com/Codeinwp/themeisle-sdk/tree/v3.3.18" + "source": "https://github.com/Codeinwp/themeisle-sdk/tree/v3.3.20" }, - "time": "2024-04-05T09:47:58+00:00" + "time": "2024-04-16T12:27:32+00:00" }, { "name": "markbaker/complex", From be2989d277ffb11239bae8eeb5f5411b55971f01 Mon Sep 17 00:00:00 2001 From: "themeisle[bot]" <> Date: Wed, 17 Apr 2024 23:54:23 +0000 Subject: [PATCH 7/7] chore(release): 3.10.13 ##### [Version 3.10.13](https://github.com/Codeinwp/visualizer/compare/v3.10.12...v3.10.13) (2024-04-17) ### Fixes - **Updated internal dependencies:** Enhanced performance and security. --- CHANGELOG.md | 5 +++++ classes/Visualizer/Plugin.php | 2 +- css/media.css | 2 +- index.php | 2 +- package.json | 2 +- readme.txt | 8 ++++++++ 6 files changed, 17 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b34a6a73..251c20faf 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +##### [Version 3.10.13](https://github.com/Codeinwp/visualizer/compare/v3.10.12...v3.10.13) (2024-04-17) + +### Fixes +- **Updated internal dependencies:** Enhanced performance and security. + ##### [Version 3.10.12](https://github.com/Codeinwp/visualizer/compare/v3.10.11...v3.10.12) (2024-04-15) ### Fixes diff --git a/classes/Visualizer/Plugin.php b/classes/Visualizer/Plugin.php index a1e5c673f..4c5810071 100644 --- a/classes/Visualizer/Plugin.php +++ b/classes/Visualizer/Plugin.php @@ -28,7 +28,7 @@ class Visualizer_Plugin { const NAME = 'visualizer'; - const VERSION = '3.10.12'; + const VERSION = '3.10.13'; // custom post types const CPT_VISUALIZER = 'visualizer'; diff --git a/css/media.css b/css/media.css index 20da6613a..9c5e5dbe3 100644 --- a/css/media.css +++ b/css/media.css @@ -1,5 +1,5 @@ /* - Version: 3.10.12 + Version: 3.10.13 */ #visualizer-library-view { padding: 30px 10px 10px 30px; diff --git a/index.php b/index.php index 363f23b45..55a0b20d4 100644 --- a/index.php +++ b/index.php @@ -3,7 +3,7 @@ Plugin Name: Visualizer: Tables and Charts for WordPress Plugin URI: https://themeisle.com/plugins/visualizer-charts-and-graphs/ Description: A simple, easy to use and quite powerful tool to create, manage and embed interactive charts into your WordPress posts and pages. The plugin uses Google Visualization API to render charts, which supports cross-browser compatibility (adopting VML for older IE versions) and cross-platform portability to iOS and new Android releases. - Version: 3.10.12 + Version: 3.10.13 Author: Themeisle Author URI: http://themeisle.com Requires at least: 5.2 diff --git a/package.json b/package.json index 848b89386..ea99369bd 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "visualizer", - "version": "3.10.12", + "version": "3.10.13", "description": "Visualizer Lite", "repository": { "type": "git", diff --git a/readme.txt b/readme.txt index 804bf92b8..7eb8643e3 100755 --- a/readme.txt +++ b/readme.txt @@ -157,6 +157,14 @@ Pay attention that to turn your shortcodes into graphs, your theme has to have ` == Changelog == +##### [Version 3.10.13](https://github.com/Codeinwp/visualizer/compare/v3.10.12...v3.10.13) (2024-04-17) + +### Fixes +- **Updated internal dependencies:** Enhanced performance and security. + + + + ##### [Version 3.10.12](https://github.com/Codeinwp/visualizer/compare/v3.10.11...v3.10.12) (2024-04-15) ### Fixes