reddit hackernews mail facebook facebook linkedin

CVE-2016-11018

An issue was discovered in the Huge-IT gallery-images plugin before 1.9.0 for WordPress. The headers Client-Ip and X-Forwarded-For are prone to unauthenticated SQL injection. The affected file is gallery-images.php. The affected function is huge_it_image_gallery_ajax_callback().


While I was working on a famous bug bounty program, WPScan returns me the list of the plugins configured on the Wordpress install. Here is what I found in one of them: Image Gallery by Huge-IT.

WPScan output, no issues known:

[+] Name: gallery-images - v1.8.6  
 |  Location: https://[REDACTED]/wp-content/plugins/gallery-images/  
 |  Readme: https://[REDACTED]/wp-content/plugins/gallery-images/readme.txt  

After a fast search on exploit-db.com with no success, I finally decided to download it and read the code to find vulnerabilites by myself. Since the readme was available, I was able to confirm the version of the plugin.

I was looking for two kind of vulnerabilities: file upload and sql injection. First thing I did was to locate PHP files, and grepping the result to find Content-Disposition header:

$ find . -name "*.php*" | xargs grep -i header
./Front_end/gallery_front_end_view.php:							header("Location:".$actual_link."");
./Front_end/gallery_front_end_view.php:							header("Location:".$actual_link."");
./Front_end/gallery_front_end_view.php:							header("Location:".$actual_link."");
./Front_end/gallery_front_end_view.php:							header("Location:".$actual_link."");
./Front_end/gallery_front_end_view.php:		/*HEIGHT FROM HEADER.PHP*/
./Front_end/gallery_front_end_view.php:							header("Location:".$actual_link."");
./Front_end/gallery_front_end_view.php:							header("Location:".$actual_link."");
./Front_end/gallery_front_end_view.php:							header("Location:".$actual_link."");
./Front_end/gallery_front_end_view.php:							header("Location:".$actual_link."");
./Front_end/gallery_front_end_view.php:							header("Location:".$actual_link."");
./Front_end/gallery_front_end_view.php:							header("Location:".$actual_link."");
./admin/gallery_func.php:			header('Location: admin.php?page=gallerys_huge_it_gallery&id='.$rowsldccs->id.'&task=apply');
./admin/gallery_view.php:	header('Location: admin.php?page=gallerys_huge_it_gallery&id='.$row->id.'&task=apply');
./admin/gallery_view.php:	<div id="gallery-header">

Nothing interesting here…

Then, I noticed that the “non admin” requests where mainly coded in two files: gallery-images.php and Front_end/gallery_front_end_view.php. Luckily I started to read the first one which contains the hole.

In the function huge_it_image_gallery_ajax_callback, the variable $huge_it_ip is used multiple times in the following form:

$wpdb->prepare("SELECT `image_status`,`ip` FROM ".$wpdb->prefix."huge_itgallery_like_dislike WHERE image_id = %d AND `ip` = '".$huge_it_ip."'",(int)$row->id);

This variable is defined at the top of the file:

if(!empty($_SERVER['HTTP_CLIENT_IP'])){
	$huge_it_ip=$_SERVER['HTTP_CLIENT_IP'];
}
elseif(!empty($_SERVER['HTTP_X_FORWARDED_FOR'])){
	$huge_it_ip=$_SERVER['HTTP_X_FORWARDED_FOR'];
}
else{
	$huge_it_ip=$_SERVER['REMOTE_ADDR'];
}

Unfortunately HTTP headers cannot be trusted, even ip address. So I started to test the injection in X-Forwarded-For header and it worked perfectly on my local install. However the site I was testing seems to had a firewall who drop this header. I then tested the injection in Client-Ip header and it passed !

Note that the plugin must be enabled to be able to exploit the injection. Finally here is the full request in Burp Suite:

POST /wp-admin/admin-ajax.php HTTP/1.1
Host: local.wordpress.com
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0 Iceweasel/38.8.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Referer: http://local.wordpress.com/wp-admin/admin.php?page=gallerys_huge_it_gallery&task=edit_cat&id=1
Content-Length: 89
Client-Ip: 123.123.123.123
Cookie: wordpress_3e0ed6e299d95d3a38b8516e25f1b1e2=admin%7C1463913228%7CYRWrxl5s69SoSkkXyMBFnXzSt2dSINk63ojC6F0mcWJ%7Cb28be90ae8a75452f047cb21fcc84f42a9a801123af24c1f77bb3f19c880147b; wordpress_test_cookie=WP+Cookie+check; wordpress_logged_in_3e0ed6e299d95d3a38b8516e25f1b1e2=admin%7C1463913228%7CYRWrxl5s69SoSkkXyMBFnXzSt2dSINk63ojC6F0mcWJ%7C243730f21ebdc724e25dd292d6c8d1773510dd572a0a39abc88b379852181f1f; wp-settings-1=libraryContent%3Dbrowse%26editor%3Dtinymce; wp-settings-time-1=1463740430; PHPSESSID=e5a63r274m6mvcfbmblgacrvq0
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache

action=huge_it_video_gallery_ajax&task=load_images_content&galleryid=1&page=1&perpage=100

The parameter task can be one of the following:
load_images_content
load_images_lightbox
load_image_justified
load_image_thumbnail
load_blog_view

And the result: cve-2016-11018

A Full Path Disclosure is also available if you call http://www.example.com/wp-content/plugins/gallery-images/gallery-images.php

I sent an email to Huge-IT who released a fix the same day. Fast enough :)

External resources