Piwigo Multiple Vulnerabilities
Vendor: Piwigo
Product: Piwigo
Version: <= 2.9.5
Website: http://www.piwigo.org/
###########################################################################
                     ______      ____________          __  
                    / ____/_  __/ / __/_  __/__  _____/ /_ 
                   / / __/ / / / / /_  / / / _ \/ ___/ __ \
                  / /_/ / /_/ / / __/ / / /  __/ /__/ / / /         
                  \____/\__,_/_/_/   /_/  \___/\___/_/ /_/ 
                      GulfTech Research and Development                                                                 
###########################################################################
#                 Piwigo <= 2.9.5 Multiple Vulnerabilities                #            
###########################################################################
Released Date: 2021-09-22
Last Modified: 2021-09-22
 Company Info: Piwigo.org
 Version Info: 
              Vulnerable
               Piwigo <= 2.9.5
--[ Table of contents
00 - Introduction
    00.1 Background
01 - Cross Site Scripting
    01.1 - Vulnerable code analysis
    01.2 - Remote exploitation
02 - SQL Injection
    02.1 - Vulnerable code analysis
    02.2 - Remote exploitation
03 - Credit
04 - Solution
05 - Contact information
--[ 00 - Introduction
The purpose of this article is to detail the vulnerabilities that I found 
in the Piwigo software. 
--[ 00.1 - Background
Piwigo is a popular open source photo gallery application written in PHP.
--[ 01 - Cross Site Scripting
Piwigo is vulnerable to a XSS issue within the "permalinks" functionality. 
This vulnerability can be exploited by an attacker to execute arbitrary 
client side code within the context of the victim client.
--[ 01.1 - Vulnerable code analysis
The vulnerable code can be found within the "parse_sort_variables" function
which is located in admin/permalinks.php and is as follows:
$url_components = parse_url( $_SERVER['REQUEST_URI'] );
$base_url = $url_components['path'];
parse_str($url_components['query'], $vars);
$is_first = true;
foreach ($vars as $key => $value)
{
	if (!in_array($key, $get_rejects) and $key!=$get_param)
	{
		$base_url .= $is_first ? '?' : '&';
		$is_first = false;
		$base_url .= $key.'='.urlencode($value);
	}
}
As we can see from the above code, the user supplied "REQUEST_URI" server
variable is used to build the $base_url variable which is later displayed
as a link to the end user. The problem with this code is that value data is
urlencoded, but key data is unasanitized. This leads to a reflected XSS
condition which could allow an attacker to force an authenticated admin
user to perform malicious actions silently on the attackers behalf.
--[ 01.2 - Remote exploitation
The Javascript payload that I created was able to create a web shell on the 
remote host by taking the following steps once executed by an authenticated 
administrator.
1] Gather "pwg_token" CSRF token
2] Install LocalFilesEditor plugin
3] Activate plugin
4] Write shell to /local/config/config.inc.php
5] De activate plugin
6] Uninstall plugin
7] Redirect user to the index page
Exploitation of this issue is rather straight forward, but because 
variables in PHP can't have dots and spaces in their names so those are 
converted to underscores by the call to "parse_str" in the vulnerable code
shown earlier. An attacker must adhere to these limitations whenever
constructing XSS payloads. 
--[ 02 - SQL Injection
Piwigo is vulnerable to an SQL Injection issue within the "permalinks" 
functionality. This vulnerability can be exploited by an attacker to execute 
arbitrary SQL statements.
--[ 02.1 - Vulnerable code analysis
The vulnerable code can be found located in the admin/permalinks.php file and is 
as follows:
if ( isset($_POST['set_permalink']) and $_POST['cat_id']>0 )
{
  check_pwg_token();
  $permalink = $_POST['permalink'];
  if ( empty($permalink) )
    delete_cat_permalink($_POST['cat_id'], isset($_POST['save']) );
  else
    set_cat_permalink($_POST['cat_id'], $permalink, isset($_POST['save']) );
  $selected_cat = array( $_POST['cat_id'] );
}
Both the "set_cat_permalink" and "delete_cat_permalink" functions rely on the 
"cat_id" variable already being sanitized. However, the only sanity checks that
take place with "cat_id" are to make sure it is greater than zero. This is not
sufficient as PHP type juggling will cast a string that starts with a number to 
a valid integer for the comparison, yet the original tainted value will remain.
This allows an attacker to pass a string that starts with an integer in order to
achieve SQL Injection.
--[ 02.2 - Remote exploitation
It seems an admin account is required to exploit this issue, so I did not bother
with trying to write an exploit for this issue.
--[ 03 - Credit
James Bercegay
GulfTech Research and Development
--[ 04 - Solution
The issue is addressed with the following commit.
https://github.com/Piwigo/Piwigo/commit/7e154ab093546e5288221685c1f8bfec2382d09a
This is scheduled for release 2.10.0.RC2
--[ 05 - Contact information
Web
https://gulftech.org/
Mail
security@gulftech.org
Copyright 2019 GulfTech Research and Development. All rights reserved.