Uploading to a public link via a script?

Nextcloud version: 12.0.1
Operating system and version: Ubuntu 16.04

What am I trying to do:

Our remote support team can run scripts at our clients. What we want to do is run a tool that creates a log file (and zips it) and upload that to our Nextcloud installation. To do so I created a new directory “test” and created a shared link which allows uploading of files (no read permissions).

The issue you are facing:

Following the process of a file upload through the proxyservice Burp Suite I noticed the web interface uses a PUT request to place a file in the directory through webdav. Now I am trying to replicate the request in our script with curl with the following command:

"curl -T logfile.zip https://nextcloud.example.com/public.php/webdav/test/logfile.zip". 

Which gives me an error about the authentication:

"No 'Authorization: Basic' header found."

After checking my captured request I noticed it includes both a requesttoken and an Authorization Basic header. Reading the server reply I noticed it sends a requesttoken upon loading the shared URL:

"<head data-requesttoken="3rYm[...]XmvX8g=">". 

That solved 1 part of the requirements, however since the script will run on untrusted pc’s owned by customers we do not want to send a username/password for basic authentication. Searching on Google resulted in this Github thread explaining the requesttoken should be used as the password of the basic authentication. But no matter how I try to set the requesttoken as part of the Authorization header the server keeps replying with either

"No 'Authorization: Basic' header found." 

or

"Username or password was incorrect, No 'Authorization: Bearer' header found."

The output of your Nextcloud log in Admin > Logging:

Warning	core	Login failed: 'DDxH8o4riP5hy1swONqDNanwqzqd8FiVmu6d8UAAxH4=' (Remote IP: 'xx.xx.xx.xx')

I think your issue is closely related to this issue over here:

An upload tool for public link shared would be a great additional feature to ease uploads for external users without an account.

It seems like we are requesting a similar feature, with the minor difference that the files we need to upload are only a few kB in size. This means installing a Nextcloud client (or portable one) to our customers is a huge overhead and the need to pause/resume uploads is almost non-existent.

As the Github link in my precious post indicates it should be possible with the current setup to upload files to the webdav with the requesttoken, I just can’t seem to get it working.

I partially solved the issue by using the public.php webdav instead of remote.php changing this error:

"Username or password was incorrect, No 'Authorization: Bearer' header found."

into only:

"Username or password was incorrect."

Reading https://stackoverflow.com/a/40906709/6350021 and https://stackoverflow.com/a/37921752/6350021 I managed to get one step further. I now receive a reply from the webdav server instead of the webserver when issuing the following curl command:

curl -x http://127.0.0.1:8080 -k -T testfile.txt -u "AtAxVrKorgC5YJf:" -H "requesttoken: vViawzESPplpdEe3gYLm+U/5qaehyS2DXa4cO5+qQtA=:im7tqnt/cM0MLAjW9fq3uiGL5PXwr1j5MtxobdTiCLU=" https://nextcloud.example.com/public.php/webdav/testfile.txt

I receive this output from the server:

<?xml version="1.0" encoding="utf-8"?>
<d:error xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns">
  <s:exception>Sabre\DAV\Exception\NotAuthenticated</s:exception>
  <s:message/>
</d:error>

Anyone able to assist with the last part?

I managed to succeed in uploading files through my own custom script by adding the “X-Request-With” header. This makes the final curl command something like:

curl -k -T testfile.txt -u "AtAxVrKorgC5YJf:" -H 'X-Requested-With: XMLHttpRequest' https://nextcloud.example.com/public.php/webdav/testfile.txt

-u is the parameter for the “Authorization: Basic” header where the username is the final part of the share link created by nextcloud. This makes sure the file gets uploaded to the correct directory.

3 Likes

There is a client library for python you could use:

2 Likes

This is great, I’ve been looking for this for a long time. Thanks!

Wonderful, but I cannot manage to upload and overwrite the file when it eventually exists on server. Can anyone help me on this?

Hello. I am eager to get scripted anon uploads working, but have hit a roadblock.

Here is the curl invocation I am using:

$ curl -k -T testfile.txt -u “qmyZe9fFk5L3ezp:” -H ‘X-Requested-With: XMLHttpRequest’ https://cloud.mydomain.net/remote.php/webdav/testfile.txt

Here is what is returned by curl.
Do I have something misconfigured? Regular (user/password) uploads work fine.
I am a little above my head here, and could use some help tracking this down further.

<?xml version="1.0" encoding="utf-8"?>
<d:error xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns">
<s:exception>Sabre\DAV\Exception\NotAuthenticated</s:exception>
<s:message>Cannot authenticate over ajax calls</s:message>
</d:error>

Platform is Arch Linux, apache 2.4.34-1, php 7.2.9-1, nextcloud 13.0.6-1. Thanks for any help.

EDIT: Just installed nextcloud-14.0, fixed all the warnings and logs. Above issue persists.

Try exchanging remote.php with public.php

2 Likes

This works. Thanks for replying, I don’t think I would ever have spotted this myself.

I have created a script for this,
added more info on a similar question, here:

Late reply, but today I managed to figure out how to make it replace an existing file: One has to add the X-Method-Override: PUT header. E.g.

curl -T somefile -u "abcd1234:some_password" -H 'X-Requested-With: XMLHttpRequest' -H 'X-Method-Override: PUT' https://somedomain.com/public.php/webdav/

will upload the file somefile to the share abcd1234 with password some_password at the server somedomain.com. If the file exists, it will be replaced.

How did you find the “data-requesttoken”? I do not find it in the response of Get or HEAD requests for the shares link url.