Files in nextcloud data directory can be downloaded via wget

Hello, when using the wget command and puting the direct address to a file on nextcloud it can download a file directly which is a security issue.
Example- wget https://cloud.example.com/data/user/files/test.txt
I’m guessing there is something I have to add to .htaccess but i’m not sure what. Sorry if I’m bad at explaining.
Thanks

I am getting an internal server error with it.

Which versions are you running?

thats just an example domain for security, im on nextcloud 18.0.4

I was testing the link on my own server of course which is also 18.0.4. But i am getting a server error with that link.

Try putting your username and a file owned by that user instead

Please post an example (command and output). You can change the domain to xxxxx .

Did already of course, got server error

root@xxxxx:~# wget https://cloud.xxxxx.com/data/xxxxx/files/video/test.mov
–2020-06-02 18:40:59-- https://cloud.xxxxx.com/data/xxxxx/files/video/test.mov
Resolving cloud.xxxxx.com (cloud.xxxxxx.com)… 2606:4700:3033::ac43:8d5e, 2606:4700:3032::6818:613f, 2606:4700:3035::6818:603f, …
Connecting to cloud.xxxxxx.com (cloud.xxxxx.com)|2606:4700:3033::ac43:8d5e|:443… connected.
HTTP request sent, awaiting response… 302 Found
Location: https://cloud.xxxxx.com/index.php/login [following]
–2020-06-02 18:40:59-- https://cloud.xxxxx.com/index.php/login
Reusing existing connection to [cloud.xxxxx.com]:443.
HTTP request sent, awaiting response… 200 OK
Length: unspecified [text/html]
Saving to: ‘test.mov.1’

test.mov.1 [ <=> ] 5.79K --.-KB/s in 0s

2020-06-02 18:40:59 (92.8 MB/s) - ‘test.mov.1’ saved [5924]

I get in “data” HTTP 403 forbidden. Check .htaccess in / and /data of nextcloud installation.

I have the same problem as @Danny_Poche on my external storage.

Is it practical to provide an example of what such a .htaccess should look like?

/var/www/html/nextcloud/.htaccess:

https://github.com/nextcloud/server/blob/master/.htaccess

/var/www/html/nextcloud/data/.htaccess:
(from my self installed nextcloud, Debian Buster, Nextcloud 18.0.4)

# Generated by Nextcloud on 2020-04-23 12:52:47
# Section for Apache 2.4 to 2.6
<IfModule mod_authz_core.c>
  Require all denied
</IfModule>
<IfModule mod_access_compat.c>
  Order Allow,Deny
  Deny from all
  Satisfy All
</IfModule>

# Section for Apache 2.2
<IfModule !mod_authz_core.c>
  <IfModule !mod_access_compat.c>
    <IfModule mod_authz_host.c>
      Order Allow,Deny
      Deny from all
    </IfModule>
    Satisfy All
  </IfModule>
</IfModule>

# Section for Apache 2.2 to 2.6
<IfModule mod_autoindex.c>
  IndexIgnore *
</IfModule>

Thank you very much for sharing!

I just realized I have the same file in the root of my data folder - I got confused because I don’t really use the data folder, only the folders in external storage, and they have no .htaccess files. My bad :stuck_out_tongue:

However - having that .htaccess file in the root of the Nextcloud data directory doesn’t prevent me fetching files from my users data directory with wget, so there must be something other amiss.

I’ll look into this a bit more thoroughly, and report back if I find out what’s going on.

Hm… it seems I’m stumped.

Here’s my most relevant configuration files, both in case anybody has the time to check for boogeymen :slight_smile: and also as a reference for others that may struggle with Apache and Nextcloud configuration.

My install works seemingly good, except for that unnerving ability to read files using wget without authentication.

Please just tell if you want to see any other configuration files.

I’m on Nextcloud 18.0.5, Apache 2.4.38 and Postgres 11.7 on Debian 10 with 64-bit kernel version 4.19.

cat /etc/apache2/apache2.conf | grep -v '#'
DefaultRuntimeDir ${APACHE_RUN_DIR}
PidFile ${APACHE_PID_FILE}
Timeout 300
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 5
User ${APACHE_RUN_USER}
Group ${APACHE_RUN_GROUP}
HostnameLookups Off
ErrorLog ${APACHE_LOG_DIR}/error.log
LogLevel warn
IncludeOptional mods-enabled/*.load
IncludeOptional mods-enabled/*.conf
Include ports.conf
Protocols h2 h2c http/1.1

<Directory />
	Options FollowSymLinks
	AllowOverride None
	Require all denied
</Directory>

<Directory /usr/share>
	AllowOverride None
	Require all granted
</Directory>

<Directory /var/www/>
	Options Indexes FollowSymLinks
	AllowOverride All
	Require all granted
</Directory>

AccessFileName .htaccess

<FilesMatch "^\.ht">
	Require all denied
</FilesMatch>

LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined
LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %O" common
LogFormat "%{Referer}i -> %U" referer
LogFormat "%{User-agent}i" agent

IncludeOptional conf-enabled/*.conf
IncludeOptional sites-enabled/*.conf
ls -1 /etc/apache2/mods-enabled
access_compat.load
alias.conf
alias.load
auth_basic.load
authn_core.load
authn_file.load
authz_core.load
authz_host.load
authz_user.load
autoindex.conf
autoindex.load
deflate.conf
deflate.load
dir.conf
dir.load
env.load
filter.load
headers.load
http2.conf
http2.load
mime.conf
mime.load
mpm_prefork.conf
mpm_prefork.load
negotiation.conf
negotiation.load
php7.3.conf
php7.3.load
proxy.conf
proxy_fcgi.load
proxy.load
reqtimeout.conf
reqtimeout.load
rewrite.load
setenvif.conf
setenvif.load
socache_shmcb.load
ssl.conf
ssl.load
status.conf
status.load
cat /etc/apache2/sites-enabled/000-default.conf | grep -v '#'
<VirtualHost *:80>
	DocumentRoot /var/www/html
	ErrorLog ${APACHE_LOG_DIR}/error.log
	CustomLog ${APACHE_LOG_DIR}/access.log combined
	Redirect permanent "/" "https://www.mydomain.tld/"
</VirtualHost>
cat /etc/apache2/sites-enabled/default-ssl.conf | grep -v '#'
<IfModule mod_ssl.c>
	<VirtualHost _default_:443>
		DocumentRoot /var/www/html
		ErrorLog ${APACHE_LOG_DIR}/error.log
		CustomLog ${APACHE_LOG_DIR}/access.log combined
		SSLEngine on
		SSLCertificateFile    /etc/letsencrypt/live/mydomain.tld/fullchain.pem
		SSLCertificateKeyFile /etc/letsencrypt/live/mydomain.tld/privkey.pem

		<FilesMatch "\.(cgi|shtml|phtml|php)$">
				SSLOptions +StdEnvVars
		</FilesMatch>

		<Directory /usr/lib/cgi-bin>
				SSLOptions +StdEnvVars
		</Directory>

		Redirect permanent "/" "https://www.mydomain.tld/"
	</VirtualHost>
</IfModule>
cat /etc/apache2/sites-enabled/www.mydomain.tld_ssl.conf | grep -v '#'
<IfModule mod_ssl.c>
	<VirtualHost _default_:443>

		DocumentRoot /var/www/html
		ServerName mydomain.tld
		ServerAlias www.mydomain.tld

		SSLEngine on
		SSLCertificateFile    /etc/letsencrypt/live/mydomain.tld/fullchain.pem
		SSLCertificateKeyFile /etc/letsencrypt/live/mydomain.tld/privkey.pem

		<FilesMatch "\.(cgi|shtml|phtml|php)$">
				SSLOptions +StdEnvVars
		</FilesMatch>

		<Directory /usr/lib/cgi-bin>
				SSLOptions +StdEnvVars
		</Directory>

		ErrorLog ${APACHE_LOG_DIR}/error.log
		CustomLog ${APACHE_LOG_DIR}/access.log combined
	</VirtualHost>
</IfModule>
cat /etc/apache2/sites-enabled/nextcloud.mydomain.tld_ssl.conf | grep -v '#'
<IfModule mod_ssl.c>
	<VirtualHost _default_:443>
		DocumentRoot /var/www/html/nextcloud

		<IfModule mod_headers.c>
			Header always set Strict-Transport-Security "max-age=15768000; preload"
			Header always set Referrer-Policy "strict-origin-when-cross-origin"
			Header always set X-Content-Type-Options "nosniff"
			Header always set X-Frame-Options "SAMEORIGIN"
		</IfModule>

		ServerName nextcloud.mydomain.tld
		ServerAlias anothername.mydomain.tld

		SSLEngine on
		SSLCertificateFile    /etc/letsencrypt/live/mydomain.tld/fullchain.pem
		SSLCertificateKeyFile /etc/letsencrypt/live/mydomain.tld/privkey.pem

		<FilesMatch "\.(cgi|shtml|phtml|php)$">
			SSLOptions +StdEnvVars
		</FilesMatch>

		<Directory /usr/lib/cgi-bin>
			SSLOptions +StdEnvVars
		</Directory>

		<Directory /var/www/html/nextcloud/>
			Require all granted
			AllowOverride All
			Options FollowSymLinks MultiViews

			<IfModule mod_dav.c>
				Dav off
			</IfModule>

			SetEnv HOME /var/www/html/nextcloud
			SetEnv HTTP_HOME /var/www/html/nextcloud
			Satisfy Any

		</Directory>

		ErrorLog ${APACHE_LOG_DIR}/error.log
		CustomLog ${APACHE_LOG_DIR}/access.log combined

	</VirtualHost>
</IfModule>
cat /var/www/html/nextcloud/.htaccess | grep -v "#"
<IfModule mod_headers.c>
  <IfModule mod_setenvif.c>
    <IfModule mod_fcgid.c>
       SetEnvIfNoCase ^Authorization$ "(.+)" XAUTHORIZATION=$1
       RequestHeader set XAuthorization %{XAUTHORIZATION}e env=XAUTHORIZATION
    </IfModule>
    <IfModule mod_proxy_fcgi.c>
       SetEnvIfNoCase Authorization "(.+)" HTTP_AUTHORIZATION=$1
    </IfModule>
  </IfModule>

  <IfModule mod_env.c>

    Header onsuccess unset Referrer-Policy
    Header always set Referrer-Policy "no-referrer"

    Header onsuccess unset X-Content-Type-Options
    Header always set X-Content-Type-Options "nosniff"

    Header onsuccess unset X-Download-Options
    Header always set X-Download-Options "noopen"

    Header onsuccess unset X-Frame-Options
    Header always set X-Frame-Options "SAMEORIGIN"

    Header onsuccess unset X-Permitted-Cross-Domain-Policies
    Header always set X-Permitted-Cross-Domain-Policies "none"

    Header onsuccess unset X-Robots-Tag
    Header always set X-Robots-Tag "none"

    Header onsuccess unset X-XSS-Protection
    Header always set X-XSS-Protection "1; mode=block"

    SetEnv modHeadersAvailable true
  </IfModule>

  <FilesMatch "\.(css|js|svg|gif)$">
    Header set Cache-Control "max-age=15778463"
  </FilesMatch>

  <FilesMatch "\.woff2?$">
    Header set Cache-Control "max-age=604800"
  </FilesMatch>
</IfModule>
<IfModule mod_php7.c>
  php_value mbstring.func_overload 0
  php_value default_charset 'UTF-8'
  php_value output_buffering 0
  <IfModule mod_env.c>
    SetEnv htaccessWorking true
  </IfModule>
</IfModule>
<IfModule mod_rewrite.c>
  RewriteEngine on
  RewriteCond %{HTTP_USER_AGENT} DavClnt
  RewriteRule ^$ /remote.php/webdav/ [L,R=302]
  RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
  RewriteRule ^\.well-known/host-meta /public.php?service=host-meta [QSA,L]
  RewriteRule ^\.well-known/host-meta\.json /public.php?service=host-meta-json [QSA,L]
  RewriteRule ^\.well-known/webfinger /public.php?service=webfinger [QSA,L]
  RewriteRule ^\.well-known/nodeinfo /public.php?service=nodeinfo [QSA,L]
  RewriteRule ^\.well-known/carddav /remote.php/dav/ [R=301,L]
  RewriteRule ^\.well-known/caldav /remote.php/dav/ [R=301,L]
  RewriteRule ^remote/(.*) remote.php [QSA,L]
  RewriteRule ^(?:build|tests|config|lib|3rdparty|templates)/.* - [R=404,L]
  RewriteCond %{REQUEST_URI} !^/\.well-known/(acme-challenge|pki-validation)/.*
  RewriteRule ^(?:\.|autotest|occ|issue|indie|db_|console).* - [R=404,L]
</IfModule>
<IfModule mod_mime.c>
  AddType image/svg+xml svg svgz
  AddEncoding gzip svgz
</IfModule>
<IfModule mod_dir.c>
  DirectoryIndex index.php index.html
</IfModule>
AddDefaultCharset utf-8
Options -Indexes
<IfModule pagespeed_module>
  ModPagespeed Off
</IfModule>

ErrorDocument 403 //
ErrorDocument 404 //
<IfModule mod_rewrite.c>
  Options -MultiViews
  RewriteRule ^core/js/oc.js$ index.php [PT,E=PATH_INFO:$1]
  RewriteRule ^core/preview.png$ index.php [PT,E=PATH_INFO:$1]
  RewriteCond %{REQUEST_FILENAME} !\.(css|js|svg|gif|png|html|ttf|woff2?|ico|jpg|jpeg|map|webm|mp4)$
  RewriteCond %{REQUEST_FILENAME} !core/img/favicon.ico$
  RewriteCond %{REQUEST_FILENAME} !core/img/manifest.json$
  RewriteCond %{REQUEST_FILENAME} !/remote.php
  RewriteCond %{REQUEST_FILENAME} !/public.php
  RewriteCond %{REQUEST_FILENAME} !/cron.php
  RewriteCond %{REQUEST_FILENAME} !/core/ajax/update.php
  RewriteCond %{REQUEST_FILENAME} !/status.php
  RewriteCond %{REQUEST_FILENAME} !/ocs/v1.php
  RewriteCond %{REQUEST_FILENAME} !/ocs/v2.php
  RewriteCond %{REQUEST_FILENAME} !/robots.txt
  RewriteCond %{REQUEST_FILENAME} !/updater/
  RewriteCond %{REQUEST_FILENAME} !/ocs-provider/
  RewriteCond %{REQUEST_FILENAME} !/ocm-provider/
  RewriteCond %{REQUEST_URI} !^/\.well-known/(acme-challenge|pki-validation)/.*
  RewriteRule . index.php [PT,E=PATH_INFO:$1]
  RewriteBase /
  <IfModule mod_env.c>
    SetEnv front_controller_active true
    <IfModule mod_dir.c>
      DirectorySlash off
    </IfModule>
  </IfModule>
</IfModule>
cat /nextcloud_data/.htaccess | grep -v "#"
<IfModule mod_authz_core.c>
  Require all denied
</IfModule>
<IfModule mod_access_compat.c>
  Order Allow,Deny
  Deny from all
  Satisfy All
</IfModule>

<IfModule !mod_authz_core.c>
  <IfModule !mod_access_compat.c>
    <IfModule mod_authz_host.c>
      Order Allow,Deny
      Deny from all
    </IfModule>
    Satisfy All
  </IfModule>
</IfModule>

<IfModule mod_autoindex.c>
  IndexIgnore *
</IfModule>

If you look at the contents of the saved file (with cat) you’ll see that it is the login page you’ve downloaded.

1 Like

Your right, the contents of the file is just the login page for my instance. Thanks!

Ahh… yes, you’re absolutely right @vascowhite! It’s the login page :smiley:

Thank you for the spoonfeeding - I simply didn’t get it :stuck_out_tongue: