Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Data leak using orphaned share-over-link #15097

Closed
schwerpunkt opened this issue Mar 22, 2015 · 12 comments · Fixed by #15145
Closed

Data leak using orphaned share-over-link #15097

schwerpunkt opened this issue Mar 22, 2015 · 12 comments · Fixed by #15145

Comments

@schwerpunkt
Copy link

Steps to reproduce

I was not able to reproduce it so far.
It might have been a relict of the OC7 => OC8 upgrade.

Still there is a deep security/data leak issue:

I had shared a file with the share over link function in OC (I think it was the latest version of OC7) on my website a few weeks ago.
Later I unshared the file (I can't recall doing it through the webinterface or a mobile app or whether I just deleted the file).

Today I clicked the link that I still had on my website and unexpectedly an endless stream of data was downloaded from my OC (a download.zip accessed by a link that earlier had pointed to a shared picture).

I downloaded up to 3GB of that stream before I killed my apache out of fear.
The download.zip in the HEX editor showed terrifyingly my folder structure as well as all the files' contents.

The orphaned token of the shared link was still in the oc_share table of my database.

Expected behaviour

Invalid share-link should display a missing file / error message.

Orphaned shared links should not exist.

Actual behaviour

A whole stream of all my OC-users data was downloaded in a download.zip-file.

Server configuration

Operating system:

Ubuntu 12.04

Web server:

Apache/2.4.12 (Ubuntu)

Database:

mysql Ver 14.14

PHP version:

PHP 5.5.22-1+deb.sury.org~precise+1

ownCloud version: (see ownCloud admin page)

8.0.2.0

Updated from an older ownCloud or fresh install:

updated from latest OC7

List of activated apps:

Activity, Calendar, Contacts, Deleted Files, External storage support, First Run Wizard, Mozilla Sync, PDF Viewer, Pictures, Share Files, Text Editor, Updater, Versions, Video Viewer

The content of config/config.php:

<?php
$CONFIG = array (
  'instanceid' => '---',
  'passwordsalt' => '---',
  'datadirectory' => '---',
  'dbtype' => 'mysql',
  'version' => '8.0.2.0',
  'dbname' => 'owncloud',
  'dbhost' => 'localhost',
  'dbtableprefix' => 'oc_',
  'dbuser' => '---',
  'dbpassword' => '---',
  'installed' => true,
  'theme' => '',
  'maintenance' => false,
  'overwritewebroot' => '/owncloud',
  'overwrite.cli.url' => '/owncloud',
  'trusted_domains' => 
  array (
    0 => '---',
    1 => '---',
  ),
  'secret' => '---',
  'loglevel' => 1,
);

Are you using external storage, if yes which one: local/smb/sftp/...

smb

Are you using encryption: yes/no

no

Are you using an external user-backend, if yes which one:

none

@karlitschek
Copy link
Contributor

@LukasReschke @schiesbn This is interesting. What do you think?

@8h2a
Copy link

8h2a commented Mar 22, 2015

I have exactly the same issue. I looked up an orphaned share in the database and tried to download it. The token was probably created with owncloud 7 because it was the old format.
When i clicked on download, it downloaded EVERYTHING that was in my owncloud.

This is a severe security issue which has to be dealt with immediately.

@DeepDiver1975
Copy link
Member

I fail to reproduce this.

@schwerpunkt
Copy link
Author

I still could not reproduce the setup that led to having an orphaned entry in the oc_share table, but a single record in the table that does not point to a valid share (so it seems) offers all data to be downloaded.

In the oc_share table for:

(`id`,`share_type`,`share_with`,`uid_owner`,`parent`,`item_type`,`item_source`,`item_target`,`file_source`,`file_target`,`permissions`,`stime`,`accepted`,`expiration`,`token`,`mail_send`)

E.g. the following entry:

(2715,0,NULL,'valid_user_name',NULL,'file','','','','',1,1423251407,0,NULL,'public_token',0)

This of course is tampered data directly in the SQL, but my productive OC instance which had the issue was not tampered with. The link there pointed to a file, which was once shared using the token of the DB entry.

Does in the case of the example calling https://link.to/owncloud/index.php/s/public_token download all your data?

The oc_share entry of the incident, where the file was not on the server anymore, was:

(2715,3,NULL,'my_user_name',NULL,'file','899424','/899424',899424,'/Photo-2015-01-28-00-03-10_0230.JPG',1,1423251407,0,NULL,'1afc221d4b539929a88ef5d6e3560564',0)

I am using almost every official OC software there is in my productive setup (Android, iOS, Mac/Linux/Win client, web interface), that's why it's unfortunately hard for me to reproduce if any of those are responsible for the orphaned link.
Again, the share was created using OC7 and has been unshared on OC8, which doesn't make reproduction easier.

@schwerpunkt
Copy link
Author

I also noticed: when I have sharing enabled and I am logged in, I can download this download.zip containing all my data when accessing https://link.to/owncloud/index.php/s/anytokenpossible/download.

I realize that this is rather useless for an attacker since he would need credentials, but probably it is still unwanted behavior related to the issue.

Having a valid token though, not pointing to a file, provides access to the data without credentials.

@LukasReschke LukasReschke self-assigned this Mar 23, 2015
@LukasReschke
Copy link
Member

I will take this one.

@schwerpunkt Please contact us always using security@owncloud.com in case you found a potential security relevant issues. For more information on reporting security issues see https://owncloud.org/security/ – we will keep this open for now.

@8h2a
Copy link

8h2a commented Mar 23, 2015

I can reproduce this:

I also noticed: when I have sharing enabled and I am logged in, I can download this download.zip containing all my data when accessing https://link.to/owncloud/index.php/s/anytokenpossible/download.

It's another issue that's not as critical, but should probably still get fixed.

About the original issue:
I tried it on another system with an older PHP version (5.4.38-1) and i get the following error when i try to access www.link.to/owncloud/index.php/s/ORPHANED_TOKEN/download

Fatal error: Call to a member function is_dir() on a non-object in ...../owncloud/lib/private/files/filesystem.php on line 586

The PHP version on my main system is 5.4.39-0+deb7u1. That was the system where i sucessfully reproduced the bug.

@PVince81
Copy link
Contributor

Here are steps to generate orphaned shares, not sure if the result would be the same: #14664

@LukasReschke
Copy link
Member

I did some digging in the sharing code (including when things like xsendfile are used) and from my point-of-view we have the following different issues in place. However, I was not able to reproduce this issue but stumbled upon other (non security relevant) bugs.

@schwerpunkt Can you double-check if accessing said sharing token with a not logged-in user (i.e. cookies and session cleaned) is still possible? If so would it be possible to provide me some kind of access to your machine?

Accessing an invalid shared token's download page as guest

Steps to reproduce

  1. Login as valid user
  2. Access a dummy download page such as /index.php/s/dummy/download
  3. All files of the logged-in user are downloaded as a ZIP file

Cause

This problem is caused by the fact that the sharing controller is returning an empty string as current file file and folder path instead of throwing an exception. The function generating the downloaded ZIP then, \OC_Files::get will deliver all files of the current users' root directory. Since the user is not logged-in this results in an uncatched fatal PHP exception.

Risk assessment

Not a security issue but anyways a low category bug.

Action to take

  • Verify the validity in the sharing controller

Accessing an invalid shared token's download page as logged-in user

Steps to reproduce

  1. Logout
  2. Access a dummy download page such as /index.php/s/dummy/download
  3. A white page is shown to the user and a PHP exception is thrown
( ! ) Fatal error: Call to a member function is_dir() on null in /Users/lukasreschke/Documents/Programming/master/lib/private/files/filesystem.php on line 579
Call Stack
#   Time    Memory  Function    Location
1   0.0000  230264  {main}( )   .../index.php:0
2   0.0144  1517456 OC::handleRequest( )    .../index.php:36
3   0.0478  3154632 OC\Route\Router->match( )   .../base.php:799
4   0.0527  3504592 call_user_func:{/Users/lukasreschke/Documents/Programming/master/lib/private/route/router.php:251} ( )  .../router.php:251
5   0.0527  3504664 OC\Route\Router->{closure:/Users/lukasreschke/Documents/Programming/master/core/routes.php:100-103}( )  .../router.php:251
6   0.0530  3541816 OCP\AppFramework\App->dispatch( )   .../routes.php:102
7   0.0530  3542176 OC\AppFramework\App::main( )    .../app.php:125
8   0.0547  3630240 OC\AppFramework\Http\Dispatcher->dispatch( )    .../app.php:103
9   0.0549  3633856 OC\AppFramework\Http\Dispatcher->executeController( )   .../dispatcher.php:86
10  0.0550  3635832 call_user_func_array:{/Users/lukasreschke/Documents/Programming/master/lib/private/appframework/http/dispatcher.php:156} ( )    .../dispatcher.php:156
11  0.0550  3636648 OCA\Files_Sharing\Controllers\ShareController->downloadShare( ) .../dispatcher.php:156
12  0.0554  3671928 OC_Files::get( )    .../sharecontroller.php:286
13  0.0554  3672184 OC\Files\Filesystem::is_dir( )  .../files.php:87

Cause

This problem is caused by the fact that the sharing controller is returning an empty string as current file file and folder path instead of throwing an exception. The function generating the downloaded ZIP then, \OC_Files::get will deliver all files of the current users' root directory.

Risk assessment

Not a security issue but anyways a low category bug.

Action to take

  • Verify the validity in the sharing controller

Accessing valid shares where the file got deleted from the filecache

Steps to reproduce

  1. Login as user "admin"
  2. Create a file "test.txt" and the directory "foo"
  3. Share the file "test.txt" and the directory "foo"
  4. Delete "test.txt" and the directory "foo" from the filesystem and the fielcache
  5. Access the download page for test.txt and the directory "foo"
  6. A white page is shown to the user and a PHP exception is thrown
( ! ) Fatal error: Call to a member function is_dir() on null in /Users/lukasreschke/Documents/Programming/master/lib/private/files/filesystem.php on line 579
Call Stack
#   Time    Memory  Function    Location
1   0.0000  230264  {main}( )   .../index.php:0
2   0.0144  1517456 OC::handleRequest( )    .../index.php:36
3   0.0478  3154632 OC\Route\Router->match( )   .../base.php:799
4   0.0527  3504592 call_user_func:{/Users/lukasreschke/Documents/Programming/master/lib/private/route/router.php:251} ( )  .../router.php:251
5   0.0527  3504664 OC\Route\Router->{closure:/Users/lukasreschke/Documents/Programming/master/core/routes.php:100-103}( )  .../router.php:251
6   0.0530  3541816 OCP\AppFramework\App->dispatch( )   .../routes.php:102
7   0.0530  3542176 OC\AppFramework\App::main( )    .../app.php:125
8   0.0547  3630240 OC\AppFramework\Http\Dispatcher->dispatch( )    .../app.php:103
9   0.0549  3633856 OC\AppFramework\Http\Dispatcher->executeController( )   .../dispatcher.php:86
10  0.0550  3635832 call_user_func_array:{/Users/lukasreschke/Documents/Programming/master/lib/private/appframework/http/dispatcher.php:156} ( )    .../dispatcher.php:156
11  0.0550  3636648 OCA\Files_Sharing\Controllers\ShareController->downloadShare( ) .../dispatcher.php:156
12  0.0554  3671928 OC_Files::get( )    .../sharecontroller.php:286
13  0.0554  3672184 OC\Files\Filesystem::is_dir( )  .../files.php:87

Cause

This problem is caused by the fact that the sharing controller is returning an empty string as current file file and folder path instead of throwing an exception. The function generating the downloaded ZIP then, \OC_Files::get will deliver all files of the current users' root directory. Since the user is not logged-in this results in an uncatched fatal PHP exception.

Risk assessment

Not a security issue but anyways a low category bug.

Action to take

  • Verify the validity in the sharing controller

@8h2a
Copy link

8h2a commented Mar 23, 2015

I was able to reproduce the bug.
Steps to reproduce:

  • Share file in owncloud 7 (7.0.4.2)
  • Delete the parent folder of the shared file
  • The share stays is in the DB and the share via the sharelink is inaccessible. (which is good)
  • Upgrade to owncloud 8 (8.0.2) (This step is crucial. The bug is not reproduceable without upgrading from 7 to 8. It seems like the old tokens are handled different than the newer ones)
  • Optional Step: Logout, Reset Browser Session, etc.
  • Access the share via the old share url: almost empty page, but there is a dowload button which adds a "/download" to the URL.
  • Upon clicking, a download.zip is downloaded which contains EVERYTHING from the owncloud directory (of the user who shared the file)
  • No exception is thrown and no error is logged.

Software versions:
Apache 2.2.22-13+deb7u3
PHP 5.4.36-0+deb7u1
SQLite 3
Debian 7

I hope these instructions were clear enough. If you're having trouble reproducing this, just ask me.

@LukasReschke
Copy link
Member

Thanks. That helped a lot. – For the record.

Database entry before update:

sqlite> select * from oc_share;
id|share_type|share_with|uid_owner|parent|item_type|item_source|item_target|file_source|file_target|permissions|stime|accepted|expiration|token|mail_send
1|3||admin||file|4|/4|4|/welcome.txt|1|1427187732|0||856af45b13da83a126732be14501e6a4|0

Database entry after update:

sqlite> select * from oc_share;
id|share_with|uid_owner|parent|item_type|item_source|item_target|file_source|file_target|expiration|token|share_type|permissions|stime|accepted|mail_send
1||admin||file|4|/4|4|/welcome.txt||856af45b13da83a126732be14501e6a4|3|1|1427187732|0|0

Regular sharing entry with ownCloud 8:

sqlite> select * from oc_share;
id|share_with|uid_owner|parent|item_type|item_source|item_target|file_source|file_target|expiration|token|share_type|permissions|stime|accepted|mail_send
2||admin||file|17|/17|17|/welcome.txt||ptVErSZoweo1xw1|3|1|1427188050|0|0

@LukasReschke
Copy link
Member

\OC\Files\Filesystem::getPath returns null instead of a string despite it's PHPDoc and the checks in master/stable8 are not expecting this.

Preparing Pull Requests and hopefully some unit tests.

LukasReschke added a commit that referenced this issue Mar 24, 2015
Despite it's PHPDoc the function might return `null` which was not properly catched and thus in some situations the share was resolved to the sharing users root directory.

To test this perform the following steps:

* Share file in owncloud 7 (7.0.4.2)
* Delete the parent folder of the shared file
* The share stays is in the DB and the share via the sharelink is inaccessible. (which is good)
* Upgrade to owncloud 8 (8.0.2) (This step is crucial. The bug is not reproduceable without upgrading from 7 to 8. It seems like the old tokens are handled different than the newer ones)
* Optional Step: Logout, Reset Browser Session, etc.
* Access the share via the old share url: almost empty page, but there is a dowload button which adds a "/download" to the URL.
* Upon clicking, a download.zip is downloaded which contains EVERYTHING from the owncloud directory (of the user who shared the file)
* No exception is thrown and no error is logged.

This will add a check whether the share is a valid one and also adds unit tests to prevent further regressions in the future. Needs to be backported to ownCloud 8.

Adding a proper clean-up of the orphaned shares is out-of-scope and would probably require some kind of FK or so.

Fixes #15097
LukasReschke added a commit that referenced this issue Mar 25, 2015
Despite it's PHPDoc the function might return `null` which was not properly catched and thus in some situations the share was resolved to the sharing users root directory.

To test this perform the following steps:

* Share file in owncloud 7 (7.0.4.2)
* Delete the parent folder of the shared file
* The share stays is in the DB and the share via the sharelink is inaccessible. (which is good)
* Upgrade to owncloud 8 (8.0.2) (This step is crucial. The bug is not reproduceable without upgrading from 7 to 8. It seems like the old tokens are handled different than the newer ones)
* Optional Step: Logout, Reset Browser Session, etc.
* Access the share via the old share url: almost empty page, but there is a dowload button which adds a "/download" to the URL.
* Upon clicking, a download.zip is downloaded which contains EVERYTHING from the owncloud directory (of the user who shared the file)
* No exception is thrown and no error is logged.

This will add a check whether the share is a valid one and also adds unit tests to prevent further regressions in the future. Needs to be backported to ownCloud 8.

Adding a proper clean-up of the orphaned shares is out-of-scope and would probably require some kind of FK or so.

Fixes #15097
@MorrisJobke MorrisJobke added this to the 8.1-current milestone Mar 26, 2015
labkode pushed a commit to cernbox/core that referenced this issue Aug 14, 2015
…github.com/owncloud/core/commits/v8.1.1/apps/files_sharing/lib/controllers/sharecontroller.php

Despite it's PHPDoc the function might return `null` which was not properly catched and thus in some situations the share was resolved to the sharing users root directory.

To test this perform the following steps:

* Share file in owncloud 7 (7.0.4.2)
* Delete the parent folder of the shared file
* The share stays is in the DB and the share via the sharelink is inaccessible. (which is good)
* Upgrade to owncloud 8 (8.0.2) (This step is crucial. The bug is not reproduceable without upgrading from 7 to 8. It seems like the old tokens are handled different than the newer ones)
* Optional Step: Logout, Reset Browser Session, etc.
* Access the share via the old share url: almost empty page, but there is a dowload button which adds a "/download" to the URL.
* Upon clicking, a download.zip is downloaded which contains EVERYTHING from the owncloud directory (of the user who shared the file)
* No exception is thrown and no error is logged.

This will add a check whether the share is a valid one and also adds unit tests to prevent further regressions in the future. Needs to be backported to ownCloud 8.

Adding a proper clean-up of the orphaned shares is out-of-scope and would probably require some kind of FK or so.

Fixes owncloud#15097
@lock lock bot locked as resolved and limited conversation to collaborators Aug 12, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants