Skip to content

Commit 50c7b27

Browse files
release: fixes
### Fixes - **Updated internal dependencies:** Enhanced performance and security.
2 parents 17b5b8f + 7e3642d commit 50c7b27

File tree

4 files changed

+153
-7
lines changed

4 files changed

+153
-7
lines changed

classes/Visualizer/Module/Chart.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1421,6 +1421,10 @@ private function _handleDataPage() {
14211421
public function getQueryData() {
14221422
check_ajax_referer( Visualizer_Plugin::ACTION_FETCH_DB_DATA . Visualizer_Plugin::VERSION, 'security' );
14231423

1424+
if ( ! current_user_can( 'edit_posts' ) ) {
1425+
wp_send_json_error( array( 'msg' => __( 'Action not allowed for this user.', 'visualizer' ) ) );
1426+
}
1427+
14241428
$params = wp_parse_args( $_POST['params'] );
14251429
$chart_id = filter_var( $params['chart_id'], FILTER_VALIDATE_INT );
14261430

classes/Visualizer/Source/Query.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ public function fetch( $as_html = false, $results_as_numeric_array = false, $raw
8080
}
8181

8282
// only select queries allowed.
83-
if ( preg_match( '/^\s*(insert|delete|update|replace|create|alter|drop|truncate)\s/i', $this->_query ) ) {
83+
if ( preg_match( '/\s*(\binsert\b|\bdelete\b|\bupdate\b|\breplace\b|\bcreate\b|\balter\b|\bdrop\b|\btruncate\b)\s/i', $this->_query ) ) {
8484
$this->_error = __( 'Only SELECT queries are allowed', 'visualizer' );
8585
return false;
8686
}

composer.lock

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/test-ajax.php

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
<?php
2+
/**
3+
* WordPress unit test plugin.
4+
*
5+
* @package visualizer
6+
* @subpackage Tests
7+
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
8+
* @since 3.10.12
9+
*/
10+
11+
/**
12+
* Test the AJAX functionality.
13+
*/
14+
class Test_Visualizer_Ajax extends WP_Ajax_UnitTestCase {
15+
16+
/**
17+
* Admin user ID.
18+
*
19+
* @var int
20+
*/
21+
private $admin_user_id;
22+
23+
/**
24+
* Set up.
25+
*/
26+
public function setUp() {
27+
parent::setUp();
28+
$this->admin_user_id = $this->factory->user->create(
29+
array(
30+
'role' => 'administrator',
31+
)
32+
);
33+
wp_set_current_user( $this->admin_user_id );
34+
35+
}
36+
37+
/**
38+
* Test the AJAX response for fetching the database data.
39+
*/
40+
public function test_ajax_response_get_query_data_valid_query() {
41+
$this->_setRole( 'administrator' );
42+
43+
$_GET['security'] = wp_create_nonce( Visualizer_Plugin::ACTION_FETCH_DB_DATA . Visualizer_Plugin::VERSION );
44+
45+
$_POST['params'] = array(
46+
'query' => 'SELECT * FROM wp_posts',
47+
'chart_id' => 1,
48+
);
49+
try {
50+
// Trigger the AJAX action
51+
$this->_handleAjax( Visualizer_Plugin::ACTION_FETCH_DB_DATA );
52+
} catch ( WPAjaxDieContinueException $e ) {
53+
// We expected this, do nothing.
54+
}
55+
56+
$response = json_decode( $this->_last_response );
57+
$this->assertIsObject( $response );
58+
$this->assertObjectHasAttribute( 'success', $response );
59+
$this->assertObjectHasAttribute( 'data', $response );
60+
$this->assertTrue( $response->success );
61+
}
62+
63+
/**
64+
* Test the AJAX response for fetching the database data with invalid query.
65+
*/
66+
public function test_ajax_response_get_query_data_invalid_query() {
67+
$this->_setRole( 'administrator' );
68+
69+
$_GET['security'] = wp_create_nonce( Visualizer_Plugin::ACTION_FETCH_DB_DATA . Visualizer_Plugin::VERSION );
70+
71+
$_POST['params'] = array(
72+
'query' => "/**/UPDATE wp_options SET option_value='administrator' WHERE option_name='default_role' --",
73+
'chart_id' => 1,
74+
);
75+
try {
76+
// Trigger the AJAX action
77+
$this->_handleAjax( Visualizer_Plugin::ACTION_FETCH_DB_DATA );
78+
} catch ( WPAjaxDieContinueException $e ) {
79+
// We expected this, do nothing.
80+
}
81+
82+
$response = json_decode( $this->_last_response );
83+
$this->assertIsObject( $response );
84+
$this->assertObjectHasAttribute( 'success', $response );
85+
$this->assertObjectHasAttribute( 'data', $response );
86+
$this->assertEquals( 'Only SELECT queries are allowed', $response->data->msg );
87+
$this->assertFalse( $response->success );
88+
}
89+
90+
/**
91+
* Test the AJAX response for fetching the database data with a valid query that uses columns that might get filtered.
92+
*/
93+
public function test_ajax_response_get_query_data_valid_query_with_filtered_columns() {
94+
$this->_setRole( 'administrator' );
95+
96+
$_GET['security'] = wp_create_nonce( Visualizer_Plugin::ACTION_FETCH_DB_DATA . Visualizer_Plugin::VERSION );
97+
98+
$_POST['params'] = array(
99+
'query' => 'select date_create from wp_insert;',
100+
'chart_id' => 1,
101+
);
102+
try {
103+
// Trigger the AJAX action
104+
$this->_handleAjax( Visualizer_Plugin::ACTION_FETCH_DB_DATA );
105+
} catch ( WPAjaxDieContinueException $e ) {
106+
// We expected this, do nothing.
107+
}
108+
109+
$response = json_decode( $this->_last_response );
110+
$this->assertIsObject( $response );
111+
$this->assertObjectHasAttribute( 'success', $response );
112+
$this->assertObjectHasAttribute( 'data', $response );
113+
$this->assertTrue( $response->success );
114+
}
115+
116+
/**
117+
* Test the AJAX response for fetching the database data with user capability.
118+
*/
119+
public function test_ajax_response_get_query_data_subcriber_dissallow() {
120+
$this->_setRole( 'subscriber' );
121+
122+
$_GET['security'] = wp_create_nonce( Visualizer_Plugin::ACTION_FETCH_DB_DATA . Visualizer_Plugin::VERSION );
123+
124+
$_POST['params'] = array(
125+
'query' => "/**/UPDATE wp_options SET option_value='administrator' WHERE option_name='default_role' --",
126+
'chart_id' => 1,
127+
);
128+
try {
129+
// Trigger the AJAX action
130+
$this->_handleAjax( Visualizer_Plugin::ACTION_FETCH_DB_DATA );
131+
} catch ( WPAjaxDieContinueException $e ) {
132+
// We expected this, do nothing.
133+
}
134+
135+
$response = json_decode( $this->_last_response );
136+
$this->assertIsObject( $response );
137+
$this->assertObjectHasAttribute( 'success', $response );
138+
$this->assertObjectHasAttribute( 'data', $response );
139+
$this->assertEquals( 'Action not allowed for this user.', $response->data->msg );
140+
$this->assertFalse( $response->success );
141+
}
142+
}

0 commit comments

Comments
 (0)