Browse Source

fix: bypass login CSRF protection

fix #976
Gerald 5 years ago
parent
commit
242dd5d870
3 changed files with 25 additions and 21 deletions
  1. 5 14
      src/background/sync/base.js
  2. 8 0
      src/background/sync/webdav.js
  3. 12 7
      src/common/util.js

+ 5 - 14
src/background/sync/base.js

@@ -311,10 +311,7 @@ export const BaseService = serviceFactory({
   },
   },
   loadData(options) {
   loadData(options) {
     const { progress } = this;
     const { progress } = this;
-    let { delay } = options;
-    if (delay == null) {
-      delay = this.delayTime;
-    }
+    const { delay = this.delayTime } = options;
     let lastFetch = Promise.resolve();
     let lastFetch = Promise.resolve();
     if (delay) {
     if (delay) {
       lastFetch = this.lastFetch
       lastFetch = this.lastFetch
@@ -325,17 +322,11 @@ export const BaseService = serviceFactory({
     progress.total += 1;
     progress.total += 1;
     onStateChange();
     onStateChange();
     return lastFetch.then(() => {
     return lastFetch.then(() => {
-      let { prefix } = options;
-      if (prefix == null) prefix = this.urlPrefix;
-      const headers = Object.assign({}, this.headers, options.headers);
+      options = Object.assign({}, options);
+      options.headers = Object.assign({}, this.headers, options.headers);
       let { url } = options;
       let { url } = options;
-      if (url.startsWith('/')) url = prefix + url;
-      return request(url, {
-        headers,
-        method: options.method,
-        body: options.body,
-        responseType: options.responseType,
-      });
+      if (url.startsWith('/')) url = (options.prefix ?? this.urlPrefix) + url;
+      return request(url, options);
     })
     })
     .then(({ data }) => ({ data }), error => ({ error }))
     .then(({ data }) => ({ data }), error => ({ error }))
     .then(({ data, error }) => {
     .then(({ data, error }) => {

+ 8 - 0
src/background/sync/webdav.js

@@ -133,6 +133,14 @@ const WebDAV = BaseService.extend({
     this.headers.Authorization = `Basic ${auth}`;
     this.headers.Authorization = `Basic ${auth}`;
     return true;
     return true;
   },
   },
+  loadData(options) {
+    // Bypassing login CSRF protection in Nextcloud / Owncloud by not sending cookies.
+    // We are not using web UI and cookie authentication, so we don't have to worry about that.
+    // See https://github.com/violentmonkey/violentmonkey/issues/976
+    return BaseService.prototype.loadData.call(this, Object.assign({
+      credentials: 'omit',
+    }, options));
+  },
   handleMetaError(res) {
   handleMetaError(res) {
     if (![
     if (![
       404, // File not exists
       404, // File not exists

+ 12 - 7
src/common/util.js

@@ -139,16 +139,21 @@ export function ensureArray(data) {
  * @return Promise
  * @return Promise
  */
  */
 export async function request(url, options = {}) {
 export async function request(url, options = {}) {
-  options = Object.assign({}, options);
-  const { responseType, body } = options;
-  if (body && Object.prototype.toString.call(body) === '[object Object]') {
-    options.headers = Object.assign({}, options.headers);
-    options.headers['Content-Type'] = 'application/json';
-    options.body = JSON.stringify(body);
+  const { responseType } = options;
+  const init = {
+    method: options.method,
+    body: options.body,
+    headers: options.headers,
+    credentials: options.credentials,
+  };
+  if (init.body && Object.prototype.toString.call(init.body) === '[object Object]') {
+    init.headers = Object.assign({}, init.headers);
+    init.headers['Content-Type'] = 'application/json';
+    init.body = JSON.stringify(init.body);
   }
   }
   const result = {};
   const result = {};
   try {
   try {
-    const resp = await fetch(url, options);
+    const resp = await fetch(url, init);
     const loadMethod = {
     const loadMethod = {
       arraybuffer: 'arrayBuffer',
       arraybuffer: 'arrayBuffer',
       blob: 'blob',
       blob: 'blob',