llaville / php-compatinfo

Library that find out the minimum version and the extensions required for a piece of code to run
https://llaville.github.io/php-compatinfo/7.1/
Other
371 stars 21 forks source link

security: uses db from known path #225

Closed glensc closed 7 years ago

glensc commented 7 years ago

the tool uses sqlite database from known path /tmp/bartlett/compatinfo.sqlite.

this has several issues:

  1. malicious user could replace the file filling it with bogus data causing damage elsewhere because the data was modified in the db
  2. malicious user could replace file with corrupted version exploiting security holes in sqlite driver itself
  3. other user in system could unknowingly prevent other users to use the same tool because he/she created the file first so that other users can not access or update it.
[~] ➔ strace -efile ~/scm/eventum/eventum/phpcompatinfo.phar  2>&1 | grep /tmp
lstat("/tmp", {st_mode=S_IFDIR|S_ISVTX|0777, st_size=560, ...}) = 0
open("/tmp/phpqDXAj2", O_RDWR|O_CREAT|O_EXCL, 0600) = 3
access("/tmp/bartlett", F_OK)           = 0
access("/tmp/bartlett/compatinfo.sqlite", F_OK) = 0
lstat("/tmp/bartlett/compatinfo.sqlite", {st_mode=S_IFREG|0664, st_size=1034240, ...}) = 0
lstat("/tmp/bartlett", {st_mode=S_IFDIR|0775, st_size=60, ...}) = 0
open("/tmp/bartlett/compatinfo.sqlite", O_RDONLY) = 6
lstat("/tmp/bartlett/compatinfo.sqlite", {st_mode=S_IFREG|0664, st_size=1034240, ...}) = 0
stat("/tmp/bartlett/compatinfo.sqlite", {st_mode=S_IFREG|0664, st_size=1034240, ...}) = 0
open("/tmp/bartlett/compatinfo.sqlite", O_RDWR|O_CREAT|O_CLOEXEC, 0644) = 6
stat("/tmp/bartlett/compatinfo.sqlite", {st_mode=S_IFREG|0664, st_size=1034240, ...}) = 0
stat("/tmp/bartlett/compatinfo.sqlite-journal", 0x7ffcb4332b70) = -1 ENOENT (No such file or directory)
stat("/tmp/bartlett/compatinfo.sqlite-wal", 0x7ffcb4332b70) = -1 ENOENT (No such file or directory)
stat("/tmp/bartlett/compatinfo.sqlite-journal", 0x7ffcb4332fe0) = -1 ENOENT (No such file or directory)
stat("/tmp/bartlett/compatinfo.sqlite-wal", 0x7ffcb4332fe0) = -1 ENOENT (No such file or directory)
stat("/tmp/bartlett/compatinfo.sqlite", {st_mode=S_IFREG|0664, st_size=1034240, ...}) = 0
unlink("/tmp/phpqDXAj2")                = 0
[~] ➔ 

as for the third point, it's rather easily achieved:

[~] ➔ rm -rf  /tmp/bartlett
[~] ➔ (umask 7; ~/scm/eventum/eventum/phpcompatinfo.phar  ) >/dev/null
[~] ➔ ls -dl /tmp/bartlett/
drwxrwx--- 2 glen glen 60 sept  22 20:35 /tmp/bartlett//
[~] ➔ ls -dl /tmp/bartlett/compatinfo.sqlite 
-rw-rw---- 1 glen glen 1034240 sept  22 20:35 /tmp/bartlett/compatinfo.sqlite
[~] ➔ 
glensc commented 7 years ago

error when /tmp/bartlett/compatinfo.sqlite is not accessible:

[~] ➔ phpcompatinfo.phar
PHP Warning:  copy(/tmp/bartlett/compatinfo.sqlite): failed to open stream: Permission denied in phar:///home/glen/.local/bin/phpcompatinfo.phar/vendor/bartlett/php-compatinfo-db/src/Bartlett/CompatInfoDb/Environment.php on line 53
PHP Stack trace:
PHP   1. {main}() /home/glen/.local/bin/phpcompatinfo.phar:0
PHP   2. require() /home/glen/.local/bin/phpcompatinfo.phar:45
PHP   3. Bartlett\Reflect\Console\Application->run() phar:///home/glen/.local/bin/phpcompatinfo.phar/bin/phpcompatinfo:51
PHP   4. Symfony\Component\Console\Application->run() phar:///home/glen/.local/bin/phpcompatinfo.phar/vendor/bartlett/php-reflect/src/Bartlett/Reflect/Console/Application.php:242
PHP   5. Bartlett\Reflect\Console\Application->doRun() phar:///home/glen/.local/bin/phpcompatinfo.phar/vendor/symfony/console/Application.php:123
PHP   6. Symfony\Component\Console\Application->doRun() phar:///home/glen/.local/bin/phpcompatinfo.phar/vendor/bartlett/php-reflect/src/Bartlett/Reflect/Console/Application.php:267
PHP   7. Symfony\Component\Console\Application->doRunCommand() phar:///home/glen/.local/bin/phpcompatinfo.phar/vendor/symfony/console/Application.php:192
PHP   8. Symfony\Component\Console\Command\Command->run() phar:///home/glen/.local/bin/phpcompatinfo.phar/vendor/symfony/console/Application.php:860
PHP   9. Symfony\Component\Console\Command\ListCommand->execute() phar:///home/glen/.local/bin/phpcompatinfo.phar/vendor/symfony/console/Command/Command.php:259
PHP  10. Symfony\Component\Console\Helper\DescriptorHelper->describe() phar:///home/glen/.local/bin/phpcompatinfo.phar/vendor/symfony/console/Command/ListCommand.php:81
PHP  11. Symfony\Component\Console\Descriptor\Descriptor->describe() phar:///home/glen/.local/bin/phpcompatinfo.phar/vendor/symfony/console/Helper/DescriptorHelper.php:72
PHP  12. Symfony\Component\Console\Descriptor\TextDescriptor->describeApplication() phar:///home/glen/.local/bin/phpcompatinfo.phar/vendor/symfony/console/Descriptor/Descriptor.php:55
PHP  13. Bartlett\Reflect\Console\Application->getHelp() phar:///home/glen/.local/bin/phpcompatinfo.phar/vendor/symfony/console/Descriptor/TextDescriptor.php:180
PHP  14. Symfony\Component\Console\Application->getHelp() phar:///home/glen/.local/bin/phpcompatinfo.phar/vendor/bartlett/php-reflect/src/Bartlett/Reflect/Console/Application.php:175
PHP  15. Bartlett\CompatInfo\Console\Application->getLongVersion() phar:///home/glen/.local/bin/phpcompatinfo.phar/vendor/symfony/console/Application.php:245
PHP  16. Bartlett\CompatInfoDb\Environment::versionRefDb() phar:///home/glen/.local/bin/phpcompatinfo.phar/src/Bartlett/CompatInfo/Console/Application.php:52
PHP  17. Bartlett\CompatInfoDb\Environment::initRefDb() phar:///home/glen/.local/bin/phpcompatinfo.phar/vendor/bartlett/php-compatinfo-db/src/Bartlett/CompatInfoDb/Environment.php:67
PHP  18. copy() phar:///home/glen/.local/bin/phpcompatinfo.phar/vendor/bartlett/php-compatinfo-db/src/Bartlett/CompatInfoDb/Environment.php:53

  [PDOException]                                     
  SQLSTATE[HY000] [14] unable to open database file  

list [--xml] [--raw] [--format FORMAT] [-h|--help] [-q|--quiet] [-v|vv|vvv|--verbose] [-V|--version] [--ansi] [--no-ansi] [-n|--no-interaction] [--no-plugins] [--profile] [--progress] [--output OUTPUT] [--manifest] [--] <command> [<namespace>]

[~] ➔ 
glensc commented 7 years ago

suggestion:

do not use world writable dirs with fixed names for storing state data (temporary files created with tempnam are ok), use user's $HOME for such data, perhaps some packagist library implementing xdg spec: https://packagist.org/search/?q=xdg

llaville commented 7 years ago

Hello @glensc

I've not forgotten your report; thanks ! I've finally have time to have a look on it and implement a solution yesterday.

I should be able to publish it this week. As this issue is related to another package that handle the database, I'll close this one, and link them

llaville commented 7 years ago

To follow on package php-compatinfo-db issue