File Inclusion with Possible RCE #532

Closed
opened 2026-10-05 00:02:28 +02:00 by adam · 5 comments
Owner

In Piwigo/admin/plugin.php

32: $sections = explode('/', $_GET['section']); 
59: $filename = PHPWG_PLUGINS_PATH . implode('/', $sections); 
60: if(is_file($filename))
62: include_once ($filename); 

As you can see, a user-controlled variable is being sent stright to include_once(). a person who managed to upload a .jpg file or any other content with PHP paylaod will just need to refer to that location and include_once() will execute it, making a code execution possible.

In Piwigo/admin/plugin.php ``` 32: $sections = explode('/', $_GET['section']); 59: $filename = PHPWG_PLUGINS_PATH . implode('/', $sections); 60: if(is_file($filename)) 62: include_once ($filename); ``` As you can see, a user-controlled variable is being sent stright to include_once(). a person who managed to upload a .jpg file or any other content with PHP paylaod will just need to refer to that location and include_once() will execute it, making a code execution possible. <!-- github-sync-id:196307361 -->
adam closed this issue 2026-10-05 00:02:28 +02:00
Author
Owner

There are quite some security checks before including anything. Uploading a JPEG in the "upload" directory won't be able to get his file included. You can't have ".." as part of the $sections, for example.

There are quite some security checks before including anything. Uploading a JPEG in the "upload" directory won't be able to get his file included. You can't have ".." as part of the $sections, for example. <!-- github-comment-id:267938358 -->
Author
Owner

Hey @plegall,

If you are implying:

if (!preg_match('/^[\w-]+$/', $plugin_id))
{
  die('Invalid plugin identifier');
}

As a security fix, it isn't sufficent because it only sanitizes $plugin_id = $sections[0];

How about other $secution[i] other than [0]? they aren't sanitized, we just have to send in another array. all the security checks apply to the $plugin_id which is just the first occurance of $sections.

Thanks,

Hey @plegall, If you are implying: ``` if (!preg_match('/^[\w-]+$/', $plugin_id)) { die('Invalid plugin identifier'); } ``` As a security fix, it isn't sufficent because it only sanitizes $plugin_id = $sections[0]; How about other $secution[i] other than [0]? they aren't sanitized, we just have to send in another array. all the security checks apply to the $plugin_id which is just the first occurance of $sections. Thanks, <!-- github-comment-id:267975534 -->
Author
Owner
$sections = explode('/', $_GET['section'] );
for ($i=0; $i<count($sections); $i++)
{
  if (empty($sections[$i]) or $sections[$i]=='..')
  {
    unset($sections[$i]);
    $i--;
  }
}

No part of the $sections can be ".."

``` $sections = explode('/', $_GET['section'] ); for ($i=0; $i<count($sections); $i++) { if (empty($sections[$i]) or $sections[$i]=='..') { unset($sections[$i]); $i--; } } ``` No part of the $sections can be ".." <!-- github-comment-id:268241924 -->
Author
Owner

@plegall not good enough. because that checks if $sections[i] is exactly "..", which is sad cause attackers can send in /..// or /..%2F and the $sections[$i]=='..' will return false. I suggest you doing a preg_replace() on it rather that one. tis easy to jump.

@plegall not good enough. because that checks if $sections[i] is exactly "..", which is sad cause attackers can send in /..// or /..%2F and the $sections[$i]=='..' will return false. I suggest you doing a preg_replace() on it rather that one. tis easy to jump. <!-- github-comment-id:268259053 -->
Author
Owner

Use CVE-2016-10105 for this.

Use CVE-2016-10105 for this. <!-- github-comment-id:270076108 -->
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: adam/Piwigo#532