| عنوان | RainyGao DocSys 2.02.85 Path Traversal |
|---|
| الوصف | A vulnerability was found in RainyGao DocSys up to 2.02.85. Affected is the function doGetTmp of the file /Doc/doGetTmpFile.do of the component Document Controller. Performing manipulation of the arguments path and fileName results in path traversal (arbitrary file read). The attack can be initiated remotely. The exploit has been made public and could be used. The vendor was contacted early about this disclosure but did not respond in any way.
TECHNICAL DETAILS
Vulnerability type: CWE-22 Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').
Affected endpoint: GET /DocSystem/Doc/doGetTmpFile.do
The endpoint serves files from a per-user temporary download directory. The base path is built by Path.getReposTmpPathForDownload() as follows:
userTmpDir = repos.getPath() + repos.getId() + "/tmp/download/" + login_user.getId() + "/";
For a repository with id 1 the base is <repos root>/1/tmp/download/<user id>/. This directory is the boundary the endpoint is supposed to enforce.
The entry point DocController.doGetTmp() takes path and fileName as raw request parameters without any filtering:
@RequestMapping("/doGetTmpFile.do")
public void doGetTmp(Integer reposId, String path, String fileName, Integer shareId, ...) {
ReposAccess reposAccess = checkAndGetAccessInfo(shareId, session, request, response, reposId, path, fileName, true, rt);
String userTmpDir = Path.getReposTmpPathForDownload(repos, reposAccess.getAccessUser());
String localParentPath = userTmpDir;
if(path != null) { localParentPath = userTmpDir + path; }
sendFileToWebPage(localParentPath, fileName, rt, response, request, null);
}
Access control: checkAndGetAccessInfo() is the only access control point. When no shareId is supplied it only requires a logged-in user (any account, including the lowest-privilege type=0 account). It neither validates whether path contains ".." nor verifies that the resolved path stays inside userTmpDir. The shareId branch performs a string prefix match that does not handle ".." segments, and the verified attack does not go through the share branch.
Sink: BaseController.sendFileToWebPage() concatenates localParentPath and fileName and opens the result with FileInputStream:
String dstPath = localParentPath + fileName;
File file = new File(dstPath);
if(!file.exists()) { ... }
in = new FileInputStream(dstPath);
There is no getCanonicalPath(), no normalize() and no prefix check. Both new File() and new FileInputStream() accept ".." segments which the operating system resolves literally.
Interceptor: MyInterceptor.preHandle() passes requests carrying X-Requested-With: XMLHttpRequest straight through, and Doc/doGetTmpFile is in the allowedUrl list. The interceptor does not waive login; the controller still demands a valid session.
PROOF OF CONCEPT
curl -b "<session>" "http://localhost:8200/DocSystem/Doc/doGetTmpFile.do?reposId=1&path=../../../../../../../etc/&fileName=passwd"
The full /etc/passwd is returned in the response.
IMPACT
Any authenticated user can read arbitrary files readable by the Tomcat process, including:
- Operating system files (e.g. /etc/passwd, /etc/shadow when readable).
- Application configuration files and credentials (database connection strings, SQLite database files, secret keys).
- Files belonging to other repositories and other users of the same installation, since the traversal is not limited to the requesting user's temporary directory.
The vulnerability requires only a valid low-privileged session and is trivially exploitable by any registered user.
REMEDIATION
Canonicalize the resolved path before opening the file and confirm it stays inside the allowed directory:
1. In doGetTmp, apply getCanonicalPath() (or equivalent normalization) to userTmpDir + path + fileName and verify the result is prefixed by the canonical form of userTmpDir.
2. Reject path and fileName values containing ".." segments (including URL-encoded variants such as %2e%2e).
3. Apply the same normalization and boundary check in sendFileToWebPage(), because it is a shared sink used by multiple download endpoints; fixing only doGetTmp would not cover the other callers.
REFERENCES
- Repository: https://gitee.com/RainyGao/DocSys
- Issue: https://gitee.com/RainyGao/DocSys/issues/IKA7W8 |
|---|
| المصدر | ⚠️ https://gitee.com/RainyGao/DocSys/issues/IKA7W8 |
|---|
| المستخدم | CyanM0un (UID 99906) |
|---|
| ارسال | 30/08/2026 03:12 PM (1 شهر منذ) |
|---|
| الاعتدال | 03/10/2026 09:42 PM (1 month later) |
|---|
| الحالة | تمت الموافقة |
|---|
| إدخال VulDB | 413376 [RainyGao DocSys حتى 2.02.85 Document Controller /Doc/doGetTmpFile.do DocController.doGetTmp path/fileName اجتياز الدليل] |
|---|
| النقاط | 20 |
|---|