🛡️ GHSA-fm76-w8jw-xf8m — plugins-loader
Description
@saltcorn/plugins-loader unsanitized plugin name leads to a remote code execution (RCE) vulnerability when creating plugins using git source
Summary
When creating a new plugin using the git source, the user-controlled value req.body.name is used to build the plugin directory where the location will be cloned. The API used to execute the git clone command with the user-controlled data is child_process.execSync. Since the user-controlled data is not validated, a user with admin permission can add escaping characters and execute arbitrary commands, leading to a command injection vulnerability.
Details
Relevant code from source (req.body) to sink (child_process.execSync).
- file: https://github.com/saltcorn/saltcorn/blob/v1.0.0-beta.13/packages/server/routes/plugins.js#L1400
```js
router.post(
"/",
isAdmin,
error_catcher(async (req, res) => {
const plugin = new Plugin(req.body); // [1]
[...]
try {
await load_plugins.loadAndSaveNewPlugin( // [3]
plugin,
schema === db.connectObj.default_schema || plugin.source === "github"
);
[...]
}
})
);
```
- file: https://github.com/saltcorn/saltcorn/blob/v1.0.0-beta.13/packages/saltcorn-data/models/plugin.ts#L44
```js
class Plugin {
[...]
constructor(o: PluginCfg | PluginPack | Plugin) {
[...]
this.name = o.name; // [2]
[...]
}
```
- file: https://github.com/saltcorn/saltcorn/blob/v1.0.0-beta.13/packages/server/load_plugins.js#L64-L65
```js
const loadAndSaveNewPlugin = async (plugin, force, noSignalOrDB) => {
[...]
const loader = new PluginInstaller(plugin); // [4]
const res = await loader.install(force); // [7]
[...]
};
```
- file: https://github.com/saltcorn/saltcorn/blob/v1.0.0-beta.13/packages/plugins-loader/plugin_installer.js#L41-L61
```js
class PluginInstaller {
constructor(plugin, opts = {}) {
[...]
const tokens =
plugin.source === "npm"
? plugin.location.split("/")
: plugin.name.split("/"); // [5]
[...]
this.tempDir = join(this.tempRootFolder, "temp_install", ...tokens); // [6]
[...]
}
async install(force) {
[...]
if (await this.prepPluginsFolder(force, pckJSON)) { // [8]
[...]
}
async prepPluginsFolder(force, pckJSON) {
[...]
switch (this.plugin.source) {
[...]
case "git":
if (force || !(await pathExists(this.pluginDir))) {
await gitPullOrClone(this.plugin, this.tempDir); // [9]
[...]
}
```
- file: https://github.com/saltcorn/saltcorn/blob/v1.0.0-beta.13/packages/plugins-loader/download_utils.js#L112
```js
const gitPullOrClone = async (plugin, pluginDir) => {
[...]
if (fs.existsSync(pluginDir)) {
execSync(git ${setKey} -C ${pluginDir} pull);
} else {
execSync(git ${setKey} clone ${plugin.location} ${pluginDir}); // [10]
}
[...]
};
```
PoC
- check that the file will be created by the command
echo "hello">/tmp/HACKEDdoes not exists:
```
cat /tmp/HACKED
cat: /tmp/HACKED: No such file or directory
```
- login with an admin account
- visit
http://localhost:3000/plugins/new - enter the following fields:
- Name:
;echo "hello">/tmp/HACKED - Source:
git - other fields blank
- click
Create - you will get an error saying
ENOENT: no such file or directory, ....but the commandtouch /tmp/HACKEDwill be executed - to verify:
```
cat /tmp/HACKED
hello
```
Impact
Remote code execution
Recommended Mitigation
Sanitize the pluginDir value before passing to execSync. Alternatively, use child_process. execFileSync API (docs: https://nodejs.org/api/child_process.html#child_processexecfilesyncfile-args-options)
How this vulnerability can be exploited
This issue can be reached over the network, attack complexity is low, an attacker needs administrative privileges on the target. No user interaction is required. Rated impact: confidentiality high, integrity high, availability high.
Weakness class
GHSA-fm76-w8jw-xf8m is classified as CWE-78: OS Command Injection. Untrusted input reaches a shell command without neutralisation, so an attacker can run arbitrary operating system commands.
Affected software
GHSA-fm76-w8jw-xf8m is recorded against 1 package.
- @saltcorn/plugins-loader
Timeline and source
Published on 3 October 2024. No public exploit is currently recorded for this entry. Record sourced from OSV.
References
github.com (Web)
github.com (Web)
github.com (Package)
github.com (Web)
github.com (Web)
github.com (Web)
github.com (Web)
github.com (Web)
Details
CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:P
Affected Packages
| Software | From version | Fixed in |
|---|---|---|
| @saltcorn/plugins-loader | — | — |
Site Security Check
Is plugins-loader part of your stack?
GHSA-fm76-w8jw-xf8m is rated CVSS 8.0 High. BotEraser scans your installation against known CVE records and tells you whether this vulnerability applies to the versions you actually run.
Scan My Site Free →No credit card required · Results in minutes
ⓘ Data Notice: The information presented above has been compiled from publicly available internet sources. Boteraser aggregates this data solely for informational purposes and does not independently classify, evaluate, or endorse any findings about the vulnerabilities listed. The accuracy and completeness of this information is the sole responsibility of the original publishers. Boteraser and its operators accept no liability for any decisions made based on this data.