Minor Bug Issue in Bootstrap.unzip #2787
Sehwang Kim opened 3 weeks ago

Although I withheld the report as it required additional verification, I have not yet been able to proceed due to being occupied with my primary job. Given that significant time has passed since I identified it, I decided to report it first.

Title

Zip Slip in Bootstrap.unzip allows arbitrary file write via crafted ZIP archive

Summary

Bootstrap.unzip() extracts ZIP entries using new File(destDir, entry.getName()) without any canonical-path validation. A crafted ZIP archive with ../ sequences in entry names can write files outside the intended destination directory on the OneDev server.

  • Constraints: Requires administrator-level access via backup restore (RestoreDatabase.java:73) or plugin .zip deployment. Local network or admin console access required.
  • Vulnerable action: Bootstrap.unzip() passes ZipEntry.getName() directly to new File(destDir, entryName) (lines 351–363, Bootstrap.java). No getCanonicalPath().startsWith() guard is present. Entry names containing ../../../../etc/cron.d/backdoor resolve outside destDir at the OS level.
  • Result: An administrator-controlled ZIP payload writes to arbitrary paths reachable by the OneDev process user. Escalation to RCE is possible via cron.d injection or overwriting server configuration files.

Details

File: commons-bootstrap/src/main/java/io/onedev/commons/bootstrap/Bootstrap.java, lines 347–369

while((entry = zis.getNextEntry()) != null) {
    var file = new File(destDir, entry.getName());  // no canonical path check
    createDir(file.getParentFile());
    new FileOutputStream(file) // writes outside destDir if getName() contains ../

Missing guard: file.getCanonicalPath().startsWith(destDir.getCanonicalPath() + File.separator).

Trigger paths:

  • RestoreDatabase.java:73 — backup restore via CLI/UI
  • Plugin .zip deployment via admin panel

PoC

Dynamic verification — exact Bootstrap.unzip replica:

Input ZIP entry name: "../../../../target_escape.txt"
destDir: /data/artifacts/project1/build1/
Result file: /target_escape.txt
Execution output:
destDir (artifacts): /private/tmp/fakeonedep/data/artifacts/project1/build1
Target escape:       /private/tmp/fakeonedep/target_escape.txt

[*] Running vulnerable Bootstrap.unzip...
[VULN CONFIRMED] Written to: /private/tmp/fakeonedep/target_escape.txt
                 Content: ZIP SLIP: written outside artifacts dir via Bootstrap.unzip

File written 4 directory levels above destDir.

Impact

Any OneDev instance where an administrator performs a backup restore or installs a plugin via ZIP upload. Allows overwrite of arbitrary server-side files at OneDev process privilege, leading to RCE via cron.d, SSH key injection, or config file tampering.

var file = new File(destDir, entry.getName());
String canonicalDest = destDir.getCanonicalPath() + File.separator;
if (!file.getCanonicalPath().startsWith(canonicalDest))
    throw new RuntimeException("Zip Slip detected: " + entry.getName());
  • Sehwang Kim commented 3 weeks ago

    @robin Actually, I discovered another vulnerability on the same day as my previous report. I hadn't reported it yet because I was too busy with my main job to verify it thoroughly, but since quite some time has passed, I wanted to submit it first.

    Please note that the severity/risk level might change. I will verify it and get back to you as soon as possible.

    This was tested on version 15.0.6.

  • Robin Shen commented 3 weeks ago

    Thanks for reporting. As you've discovered, this can only called by Administrator when restore a backup or by system when unpacks a plugin (normal user cannot upload plugin). So this will not do any harm to the system, and should not be treated as security vulnerability.

    Nevertheless, fixing the zip slip will prevent possible vulnerabilities in future in case it is used to unzip untrusted source by mistake.

  • Sehwang Kim commented 3 weeks ago
    Thank you. To be honest, I hesitated a lot about whether or not to report this. I submitted it first because I wanted it to be judged from a maintainer's perspective. I hope this could be of even a little help. Thank you.

    Best regards,
  • Sehwang Kim commented 3 weeks ago

    Please consider this report as just a minor bug report. Thank you.

  • Sehwang Kim changed fields 3 weeks ago
    Name Previous Value Current Value
    Type
    Security Vulnerability
    Bug
    Affected Versions
    empty
    <= 15.0.6
  • Sehwang Kim changed fields 3 weeks ago
    Name Previous Value Current Value
    Priority
    Normal
    Minor
  • Sehwang Kim changed title 3 weeks ago
    Previous Value Current Value
    Security Issue in Bootstrap.unzip
    Minor Bug Issue in Bootstrap.unzip
  • Robin Shen changed confidential 3 weeks ago
    Previous Value Current Value
    true
    false
  • Robin Shen commented 2 weeks ago

    Already fixed

  • Robin Shen changed state to 'Closed' 2 weeks ago
    Previous Value Current Value
    Open
    Closed
1/1
Type
Bug
Priority
Minor
Assignee
Affected Versions
<= 15.0.6
Labels
No labels
Issue Votes (0)
Watchers (3)
Reference
OD-2787
Please wait...
Connection lost or session expired, reload to recover
Page is in error, reload to recover