Skip to content

[vulnerability][demo][acl] Workers from blob URLs are not hooked #249

Description

@t2ym

[vulnerability][demo][acl] Workers from blob URLs are not hooked

Root Cause

  • No ACLs for Worker/SharedWorker constructor arguments against blob: URLs

Notes

  • Considering how to hook blob: worker scripts
  • Block them for now as a quick fix

Reproducible Code Example

  let blob = new Blob([`
    onmessage = (event) => {
      caches.keys().then(keys => postMessage(keys[0]));
    }
  `], { type: 'text/javascript' });
  let blobUrl = URL.createObjectURL(blob);
  let worker = new Worker(blobUrl);

  worker.addEventListener('message', function onMessage(event) {
    console.log('web-worker-client.js: received message', event.data);
    chai.assert.isOk(event.data.startsWith('version_'), 'blob worker result');
  });
  let message = [];
  console.log('web-worker-client.js: posting message ', JSON.stringify(message));
  worker.postMessage(message);

ACLs to block blob: and data: URLs for Worker/SharedWorker

    Worker: {
      [S_OBJECT]: {
        [S_DEFAULT]: '---',
        '@worker_manipulator': function _WorkerAcl(normalizedThisArg,
                                                   normalizedArgs /* ['property', args], ['property', value], etc. */,
                                                   aclArgs /* [name, isStatic, isObject, property, opType, context] */,
                                                   hookArgs /* [f, thisArg, args, context, newTarget] */,
                                                   applyAcl /* for recursive application of ACL */) {
          let opType = aclArgs[4];
          if (opType === 'x') {
            let url = normalizedArgs[0].trim().toLowerCase();
            if (url.startsWith('blob:') || url.startsWith('data:')) {
              return false;
            }
          }
          return '--x'[opTypeMap[opType]] === opType; // equivalent to '--x' acl
        },
      },
      [S_DEFAULT]: '---',
      [S_ALL]: '---',
      [S_PROTOTYPE]: {
        [S_DEFAULT]: '---',
        [S_ALL]: '---',
        [S_INSTANCE]: {
          [S_DEFAULT]: '---',
          '@worker_manipulator': 'rwx',
        },
      },
    },
    SharedWorker: {
      [S_OBJECT]: {
        [S_DEFAULT]: '---',
        '@shared_worker_manipulator': function _WorkerAcl(normalizedThisArg,
                                                          normalizedArgs /* ['property', args], ['property', value], etc. */,
                                                          aclArgs /* [name, isStatic, isObject, property, opType, context] */,
                                                          hookArgs /* [f, thisArg, args, context, newTarget] */,
                                                          applyAcl /* for recursive application of ACL */) {
          let opType = aclArgs[4];
          if (opType === 'x') {
            let url = normalizedArgs[0].trim().toLowerCase();
            if (url.startsWith('blob:') || url.startsWith('data:')) {
              return false;
            }
          }
          return '--x'[opTypeMap[opType]] === opType; // equivalent to '--x' acl
        },
      },
      [S_DEFAULT]: '---',
      [S_ALL]: '---',
      [S_PROTOTYPE]: {
        [S_DEFAULT]: '---',
        [S_ALL]: '---',
        [S_INSTANCE]: {
          [S_DEFAULT]: '---',
          '@shared_worker_manipulator': 'rwx',
        },
      },
    },

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions