Closed darkpills closed 6 months ago
Hello,
Thanks! I like the usage of process_serialized()
. Can you tell me how you created your test environment, because although the library is present, Swift
classes don't seem to be included by default. I tried downloading the instance from Symfony's website, and using composer.
Charles
Hello !
Thank you for your tests!
Current version of Symfony 1.5 is partially vulnerable. All depend how you install it:
Here are my notes if it can help about installing 1.5:
Install composer:
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('sha384', 'composer-setup.php') === 'e21205b207c3ff031906575712edab6f13eb0b361f2085f1f1237b7126d785e826a450292b6cfd1d64d92e6563bbde02') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"
And then install Symfony with composer:
php composer.phar require friendsofsymfony1/symfony1 "1.5.*"
php composer.phar install
If you launch install command like in 1.4 you will get a fatal error due to Doctrine components not found. You can either add Doctrine with composer and declare sf_doctrine_path
in your project configuration file, or like me since we don't need an ORM, disable Doctrine during installation. Edit vendor/friendsofsymfony1/symfony1/lib/plugins/sfDoctrinePlugin/config/installer.php
:
$this->installDir(dirname(__FILE__).'/skeleton');
//$this->enablePlugin('sfDoctrinePlugin');
$this->reloadTasks();
And start creating a project, an application and a module:
php ./vendor/symfony/data/bin/symfony generate:project test
php symfony generate:app frontend
php symfony generate:module frontend test
Several files will be created, among them: web/index.php
and web/frontend_dev.php
for respectively production and development configuration of the frontend application.
Then start a webserver with PHP installed and make the root point to web
directory (renamed public
in version 2.x and higher).
Fix the possible permission issues.
Open a web browser to http://localhost/frontend_dev.php
.
Create a git repo:
git init .
git submodule add https://github.com/FriendsOfSymfony1/symfony1.git lib/vendor/symfony
git submodule update --init --recursive
If you try to generate a project, you will get an error due to PHP7.1+ new syntax to declare visibility of constants. However, this syntax is not compatible with PHP5. Here is a snipet to fix it:
find . -name "*.php" -type f -exec grep -l "public const" '{}' \; | noglob xargs -I '{}' sed -i -e s#"public const"#"const"# '{}'
Then, the rest is the same:
php ./vendor/bin/symfony generate:project test
php symfony generate:app frontend
php symfony generate:module frontend test
Hello,
Thanks for the detailled information. I was able to pull it off with the GIT method.
Despite a successful installation, when I unserialized, I get the dreaded __PHP_Incomplete_Class
for every lime_*
object. The lime classes you use in the gadget are NOT in scope when I run the exploit from the symfony website, because lime.php
is never included in the web part of the framework, or present in the autoloader.
For the sake of precision: I installed everything using the official method described here. I then put the unserialize() code in sfContext::getController()
to make sure that everything has been loaded. I get (stripped for brevity):
object(__PHP_Incomplete_Class)#26 (10) {
["__PHP_Incomplete_Class_Name"]=>
string(9) "lime_test"
["output":protected]=>
object(__PHP_Incomplete_Class)#27 (2) {
["__PHP_Incomplete_Class_Name"]=>
string(17) "lime_output_color"
["colorizer"]=>
object(sfOutputEscaperObjectDecorator)#28 (2) {
["value":protected]=>
object(__PHP_Incomplete_Class)#29 (1) {
["__PHP_Incomplete_Class_Name"]=>
string(14) "lime_colorizer"
}
...
}
}
["output"]=>
object(__PHP_Incomplete_Class)#31 (2) {
["__PHP_Incomplete_Class_Name"]=>
string(17) "lime_output_color"
...
...
}
Charles
Thank you a lot for the time you spent on testing :)
Actually, there are a lot of possibilities for the chains, but i tried to provide as less chains as possible (2) to bring all the possible coverage on all versions of symfony 1.
The first chain (Symfony/RCE12) covers versions 1.3.0 < 1.5.13~17 including 1.4.x and with a "maybe" between 1.5.13 and 1.5.17 depending on how you install it.
The second chain (Symfony/RCE13) covers versions 1.0.0 < 1.2.12. For those versions, lime_test is loaded in the autoload of symfony, as seen in this extract of www-1.2.12/cache/frontend/dev/config/config_autoload.yml.php
:
'sfPager' => '/var/www/lib/addon/sfPager.class.php',
'lime_test' => '/var/www/lib/vendor/lime/lime.php',
'lime_output' => '/var/www/lib/vendor/lime/lime.php',
'lime_output_color' => '/var/www/lib/vendor/lime/lime.php',
'lime_colorizer' => '/var/www/lib/vendor/lime/lime.php',
'lime_harness' => '/var/www/lib/vendor/lime/lime.php',
'lime_coverage' => '/var/www/lib/vendor/lime/lime.php',
'lime_registration' => '/var/www/lib/vendor/lime/lime.php',
'sfFunctionCache' => '/var/www/lib/cache/sfFunctionCache.class.php',
However, the installation of version 1.x is a bit tricky. I have a blog post waiting to be published. You can find above an extract of the installation notes if it can help:
Install documentation is still available at https://symfony.com/legacy/doc/getting-started/1_4/en/03-Symfony-Installation and need few changes to get it running:
As the SVN infrastructure has been discontinued, download the version from git and untar the project:
tar -xvzf symfony1-*.tar.gz
mv symfony1-*/* .
And start creating a project, an application and a module:
php ./lib/vendor/symfony/data/bin/symfony generate:project test
php symfony generate:app frontend
php symfony generate:module frontend test
Same as 1.4, except a light change in default symfony bin path:
php ./data/bin/symfony generate:project test
In version 1.2 and lower, full installation path can be found in cache files and project configuration class like config/ProjectConfiguration.class.php
:
require_once '/workspace/www-1.2.12/lib/autoload/sfCoreAutoload.class.php';
sfCoreAutoload::register();
class ProjectConfiguration extends sfProjectConfiguration
{
public function setup()
{
// for compatibility / remove and enable only the plugins you want
$this->enableAllPluginsExcept(array('sfDoctrinePlugin', 'sfCompat10Plugin'));
}
}
So depending on your setup, you might need to play with symlinks on your host/docker.
In lower versions of symfony, deprecated warnings can be seen. Error reporting verbosity can be changed in
apps/frontend/config/settings.yml
.
Same as 1.2
Same as 1.2, except some changes in the initial task names and no default symlink created:
php ./data/bin/symfony init-project test
php ./data/bin/symfony init-app frontend
php ./data/bin/symfony init-module frontend testclone
In 1.0 versions, the actions file name as been renamed:
apps/frontend/modules/test/actions/indexAction.class.php
apps/frontend/modules/test/actions/actions.class.php
Also, the request object is not given as an argument to the controller, and it needs to be fetch manually from sfContext
singleton by the developper:
class testActions extends sfActions
{
public function executeIndex()
{
$request = sfContext::getInstance()->getRequest();
$a = unserialize($request->getParameter('user'));
}
}
We seem to have a different autoload configuration; I don't have lime.php
in cache/frontend/dev/config/config_autoload.yml.php
, and you do.
$ cat cache/frontend/dev/config/config_autoload.yml.php | grep lime -i
$
PS: Also, your folder name is www-1.2.12. Is it vulnerable as well ? You indicate that it is not (using <
instead of <=
).
Could you precise the version of PHP you are using so that i can try to reproduce? I'm on PHP 5.6.40 for testing sf <= 1.4 to match with configuration of most applications which would remain on a 5.x stack.
I will need to update the versions. It's a <=
for all the mentioned versions.
Yes, sorry: PHP 5.6.40-68+ubuntu22.04.1+deb.sury.org+1 (cli)
OK, this is my fault: I uncompressed the symfony archive in the current directory, not in lib/vendor, making all symfony classes being autoloaded, even the one in lib/vendor/symfony/vendor/*
Arf, it breaks my chain for symfony <= 1.2.12 with a __destruct(). I will make a commit to remove this last one and propose other alternative chains, maybe based on Propel.
@darkpills any updates on this?
ps: would you please check the advisory message thread? we made some progress and we're waiting for your advice. thank you
@thePanz the chain for >= 1.3.0 is valid, but the other one is not. I need to put more work into this one to provide complete chains. This can be done within the next days I think.
OK, this is my fault: I uncompressed the symfony archive in the current directory, not in lib/vendor, making all symfony classes being autoloaded, even the one in lib/vendor/symfony/vendor/*
Oh, makes sense.
@cfreal : i provided the following updates and new chains replacing the old one to provide a coverage on all versions. However, most of these depends on enabled plugins ORM.
However^2, I found another nice gadget chain covering almost all versions of 1.x and without any dependencies. I will publish it here later on. I opened another advisory on Symfony1 repository and wait for them to patch it.
Hope this time, there won't be any mistake :)
Another question for you that is not directly linked with the following PR: a class in the framework has this code:
public function __destruct()
{
@mysql_close($this->db);
}
I dig in the php5 mysql extension source code to find any "callback" from C code to PHP code to trigger a gadget chain. However, I could only find zend resource access by with a zval input and resource deletion. Do you have the same analysis? Just if you have time to check, if not don't bother :)
Hello,
Now PEAR is giving me hell. I cannot install the modules:
php5.6 -dinclude_path=/usr/local/lib/php:. ./symfony plugin:install sfPropelPlugin
>> plugin installing plugin "sfPropelPlugin"
>> sfPearFrontendPlugin Attempting to discover channel "pear.symfony-project.com"...
>> sfPearFrontendPlugin Attempting fallback to https instead of http on channel
>> sfPearFrontendPlugin "pear.symfony-project.com"...
Unable to register channel "pear.symfony-project.com" (use --force-license to force installation)
Same as root, same with --force-license
.
Can you walk me through your steps?
Charles
Actually, sfDoctrinePlugin and sfPropelPlugin are already bundled with the tar.gz of Symfony distribution from the legacy website. I did not install any third party component.
Here the is steps for 1.2:
mkdir lib/vendor
cd lib/vendor
tar -xvzf ../../symfony1-*.tar.gz
mv symfony1-* symfony
php ./lib/vendor/symfony/data/bin/symfony generate:project test
php symfony generate:app frontend
php symfony generate:module frontend test
chmod 777 cache/ log/
sed -i -e s#"die("#"//die("#g ./web/frontend_dev.php
sed -i -e s#"\$this->forward('default', 'module');"#"\$a = unserialize(\$request->getParameter('user'));"#g ./apps/frontend/modules/test/actions/actions.class.php
In config/ProjectConfiguration.class.php, enable the needed plugin:
public function setup()
{
$this->enablePlugins('sfDoctrinePlugin');
}
For 1.0, there are some more steps:
Same as 1.2, except some changes in the initial task names:
php ./lib/vendor/symfony/data/bin/symfony new test
php symfony app frontend
php symfony module frontend test
In 1.0 versions, the actions file name as been renamed:
apps/frontend/modules/test/actions/indexAction.class.php
apps/frontend/modules/test/actions/actions.class.php
Also, the request object is not given as an argument to the controller, and it needs to be fetch manually from sfContext
singleton by the developper:
class testActions extends sfActions
{
public function executeIndex()
{
$request = sfContext::getInstance()->getRequest();
$a = unserialize($request->getParameter('user'));
}
}
Finally, you need to remove some deprecated PHP options so that your lib/vendor/symfony/data/config/php.yml
will look like this:
set:
log_errors: on
arg_separator.output: |
&
check:
warn:
session.auto_start: off
Hello darkpills,
Thanks to your detailed infos I was able to make it work! Everything works fine.
Thank you for you contribution! Charles
Hello @cfreal thank you for your time for testing! Another PR coming quickly I hope.
I created 2 gadget chains for all versions of Symfony 1 including the 1.5 fork maintained here https://github.com/FriendsOfSymfony1/symfony1
Symfony1 is not maintained any more. Sensiolabs has been contacted but they won't provide a fix since Symfony1 is end of life.
Symfony1.5.13 and greater are still partially vulnerable depending on how you install it, but no maintainers are responding.