Back to Devexpress

Control Access to Server Files

aspnet-404858-security-considerations-file-upload-control-access-to-server-files.md

latest13.1 KB
Original Source

Control Access to Server Files

  • May 29, 2025
  • 6 minutes to read

To prevent unauthorized access to files/folders stored on a server, you should follow industry-accepted best practices including the following:

Validate File Paths

Always validate file paths that include untrusted file or folder names. Do not trust user entered file/folder names as this can generate a path outside the upload folder when combining file names with the upload folder path.

The following example validates uploaded file paths:

aspx
<dx:ASPxUploadControl ID="UploadControl" runat="server" ShowUploadButton="True" 
    OnFileUploadComplete="FileUploadComplete">
</dx:ASPxUploadControl>
cs
protected void FileUploadComplete(object sender, DevExpress.Web.FileUploadCompleteEventArgs e) {
    string uploadFolder = "~/App_Data/UploadFiles/";
    string fileName = Path.Combine(uploadFolder, e.UploadedFile.FileName);
    if (e.IsValid && IsValidVirtualPath(fileName, uploadFolder)) {
        e.UploadedFile.SaveAs(Server.MapPath(fileName), true);
    }
}

bool IsValidVirtualPath(string sourceVirtualPath, string folderVirtualPath) {
    var sourceFullPath = Server.MapPath(sourceVirtualPath);
    return IsValidFullPath(sourceFullPath, folderVirtualPath);
}

bool IsValidFullPath(string sourceFullPath, string folderVirtualPath) {
    var folderFullPath = Server.MapPath(folderVirtualPath);

    if (sourceFullPath.EndsWith(@"\"))
        sourceFullPath = sourceFullPath.Substring(0, sourceFullPath.Length - 1);
    if (folderFullPath.EndsWith(@"\"))
        folderFullPath = folderFullPath.Substring(0, folderFullPath.Length - 1);

    return sourceFullPath.Equals(folderFullPath, StringComparison.OrdinalIgnoreCase)
        || sourceFullPath.StartsWith(folderFullPath + @"\", StringComparison.OrdinalIgnoreCase);
}
vb
Protected Sub FileUploadComplete(ByVal sender As Object, ByVal e As DevExpress.Web.FileUploadCompleteEventArgs)
    Dim uploadFolder As String = "~/App_Data/UploadFiles/"
    Dim fileName As String = Path.Combine(uploadFolder, e.UploadedFile.FileName)
    If e.IsValid AndAlso IsValidVirtualPath(fileName, uploadFolder) Then
        e.UploadedFile.SaveAs(Server.MapPath(fileName), True)
    End If
End Sub

Function IsValidVirtualPath(ByVal sourceVirtualPath As String, ByVal folderVirtualPath As String) As Boolean
    Dim sourceFullPath = Server.MapPath(sourceVirtualPath)
    Return IsValidFullPath(sourceFullPath, folderVirtualPath)
End Function

Private Function IsValidFullPath(ByVal sourceFullPath As String, ByVal folderVirtualPath As String) As Boolean
    Dim folderFullPath = Server.MapPath(folderVirtualPath)

    If sourceFullPath.EndsWith("\") 
        Then sourceFullPath = sourceFullPath.Substring(0, sourceFullPath.Length - 1)
    If folderFullPath.EndsWith("\") 
        Then folderFullPath = folderFullPath.Substring(0, folderFullPath.Length - 1)

    Return sourceFullPath.Equals(folderFullPath, StringComparison.OrdinalIgnoreCase) 
        OrElse sourceFullPath.StartsWith(folderFullPath & "\", StringComparison.OrdinalIgnoreCase)
End Function

Protect Temporary Files

To ensure uploaded temporary files are inaccessible to third parties, you should:

  1. Store temporary files in a folder inaccessible by URL.
  2. Use a dedicated file extension for temporary files.
  3. Call the GetRandomFileName method to assign random file names to uploaded files.

The following code sample saves temporary files using industry-accepted best practices:

aspx
<dx:ASPxUploadControl ID="UploadControl" runat="server" UploadMode="Advanced" ShowUploadButton="True"
    OnFilesUploadComplete="FilesUploadComplete">
    <AdvancedModeSettings EnableMultiSelect="True" />
</dx:ASPxUploadControl>
cs
protected void FilesUploadComplete(object sender, DevExpress.Web.FilesUploadCompleteEventArgs e) {
    if (UploadControl.UploadedFiles != null && UploadControl.UploadedFiles.Length > 0) {
        for (int i = 0; i < UploadControl.UploadedFiles.Length; i++) {
            UploadedFile file = UploadControl.UploadedFiles[i];
            string uploadFolder = "~/App_Data/UploadFiles/";
            if (file.IsValid && file.FileName != "") {
                string fileName = Path.Combine(Server.MapPath(uploadFolder), Path.GetRandomFileName() + ".tmp");
                if (IsValidFullPath(fileName, uploadFolder)){
                    file.SaveAs(fileName, true);
                    // Process the uploaded file here
                }
            }
        }
    }
}
bool IsValidFullPath(string sourceFullPath, string folderVirtualPath) {
    var folderFullPath = Server.MapPath(folderVirtualPath);
    if (sourceFullPath.EndsWith(@"\"))
        sourceFullPath = sourceFullPath.Substring(0, sourceFullPath.Length - 1);
    if (folderFullPath.EndsWith(@"\"))
        folderFullPath = folderFullPath.Substring(0, folderFullPath.Length - 1);
    return sourceFullPath.Equals(folderFullPath, StringComparison.OrdinalIgnoreCase)
        || sourceFullPath.StartsWith(folderFullPath + @"\", StringComparison.OrdinalIgnoreCase);
}
vb
Protected Sub FilesUploadComplete(ByVal sender As Object, ByVal e As DevExpress.Web.FilesUploadCompleteEventArgs)
    If UploadControl.UploadedFiles IsNot Nothing AndAlso UploadControl.UploadedFiles.Length > 0 Then
        For i As Integer = 0 To UploadControl.UploadedFiles.Length - 1
            Dim file As UploadedFile = UploadControl.UploadedFiles(i)
            Dim uploadFolder As String = "~/App_Data/UploadFiles/"
            If file.IsValid AndAlso file.FileName <> "" Then
                Dim fileName As String = Path.Combine(Server.MapPath(uploadFolder), Path.GetRandomFileName() & ".tmp")
                If IsValidFullPath(fileName, uploadFolder) Then
                    file.SaveAs(fileName, True)
                    ' Process the uploaded file here
                End If
            End If
        Next
    End If
End Sub
Private Function IsValidFullPath(ByVal sourceFullPath As String, ByVal folderVirtualPath As String) As Boolean
    Dim folderFullPath = Server.MapPath(folderVirtualPath)
    If sourceFullPath.EndsWith("\") 
        Then sourceFullPath = sourceFullPath.Substring(0, sourceFullPath.Length - 1)
    If folderFullPath.EndsWith("\") 
        Then folderFullPath = folderFullPath.Substring(0, folderFullPath.Length - 1)
    Return sourceFullPath.Equals(folderFullPath, StringComparison.OrdinalIgnoreCase) 
        OrElse sourceFullPath.StartsWith(folderFullPath & "\", StringComparison.OrdinalIgnoreCase)
End Function

Protect Thumbnails

The DevExpress File Manager automatically creates content-based thumbnails and stores them in the ThumbnailFolder. Subfolder structure is based on the File Manager’s folder structure. Before the File Manager displays a thumbnail for the first time, the control checks for an existing thumbnail with a corresponding path/name. If the thumbnail does not exist, the control generates a new thumbnail file.

Consider the following when using the File Manager:

  • A threat actor can access private thumbnails if these thumbnails are in a public folder.
  • If you change the RootFolder property value dynamically, multiple thumbnails can use the same relative path and file name. In this instance, the control may display incorrect thumbnails.

In multi-user applications or if you dynamically change the root folder, use the ThumbnailFolder property to specify the thumbnail folder dynamically based on the current user.

aspx
<dx:ASPxComboBox ID="ComboBox" runat="server" AutoPostBack="True" SelectedIndex="0" DataSecurityMode="Strict">
     <Items>
          <dx:ListEditItem Text="Common" Value="Common files" Selected="True" />
          <dx:ListEditItem Text="User 1" Value="User1" />
          <dx:ListEditItem Text="User 2" Value="User2" />
          <dx:ListEditItem Text="User 3" Value="User3" />
     </Items>
</dx:ASPxComboBox>
<dx:ASPxFileManager ID="FileManager" runat="server">
     <Settings RootFolder="~/Content/Common files" ThumbnailFolder="~/Content/Thumbs/Common files" />
</dx:ASPxFileManager>
csharp
protected void Page_Load(object sender, EventArgs e) {
    string userSubFolder = ComboBox.Value.ToString();
    string rootFolder = Path.Combine("~/Content/", userSubFolder);
    string thumbnailFolder = Path.Combine("~/Thumbs/", userSubFolder);

    bool foldersAreValid = IsValidVirtualPath(rootFolder, "~/Content/") 
        && IsValidVirtualPath(thumbnailFolder, "~/Thumbs/");
    if (foldersAreValid) {
        FileManager.Settings.RootFolder = rootFolder;
        FileManager.Settings.ThumbnailFolder = thumbnailFolder;
    }
}
bool IsValidVirtualPath(string sourceVirtualPath, string folderVirtualPath) {
    var sourceFullPath = Server.MapPath(sourceVirtualPath);
    return IsValidFullPath(sourceFullPath, folderVirtualPath);
}
bool IsValidFullPath(string sourceFullPath, string folderVirtualPath) {
    var folderFullPath = Server.MapPath(folderVirtualPath);
    if (sourceFullPath.EndsWith(@"\"))
        sourceFullPath = sourceFullPath.Substring(0, sourceFullPath.Length - 1);
    if (folderFullPath.EndsWith(@"\"))
        folderFullPath = folderFullPath.Substring(0, folderFullPath.Length - 1);
    return sourceFullPath.Equals(folderFullPath, StringComparison.OrdinalIgnoreCase)
        || sourceFullPath.StartsWith(folderFullPath + @"\", StringComparison.OrdinalIgnoreCase);
}
vb
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
    Dim userSubFolder As String = ComboBox.Value.ToString()
    Dim rootFolder As String = Path.Combine("~/Content/", userSubFolder)
    Dim thumbnailFolder As String = Path.Combine("~/Thumbs/", userSubFolder)

    Dim foldersAreValid As Boolean = IsValidVirtualPath(rootFolder, "~/Content/") 
        AndAlso IsValidVirtualPath(thumbnailFolder, "~/Thumbs/")
    If foldersAreValid Then
        FileManager.Settings.RootFolder = rootFolder
        FileManager.Settings.ThumbnailFolder = thumbnailFolder
    End If
End Sub
Function IsValidVirtualPath(ByVal sourceVirtualPath As String, ByVal folderVirtualPath As String) As Boolean
    Dim sourceFullPath = Server.MapPath(sourceVirtualPath)
    Return IsValidFullPath(sourceFullPath, folderVirtualPath)
End Function
Private Function IsValidFullPath(ByVal sourceFullPath As String, ByVal folderVirtualPath As String) As Boolean
    Dim folderFullPath = Server.MapPath(folderVirtualPath)

    If sourceFullPath.EndsWith("\") 
        Then sourceFullPath = sourceFullPath.Substring(0, sourceFullPath.Length - 1)
    If folderFullPath.EndsWith("\") 
        Then folderFullPath = folderFullPath.Substring(0, folderFullPath.Length - 1)

    Return sourceFullPath.Equals(folderFullPath, StringComparison.OrdinalIgnoreCase) 
        OrElse sourceFullPath.StartsWith(folderFullPath & "\", StringComparison.OrdinalIgnoreCase)
End Function

Restrict Access to Files and Folders

The File Manager allows you to specify access rules and security permissions for files/folders. A folder access rule affects the folder, its subfolders, and files. A file access rule affects all files whose path matches a specified pattern. Unlike access rules, each security permission affects an individual file or folder and allows you to implement complex user access logic.

Use the SettingsPermissions.AccessRules property to specify access rules and apply appropriate security permissions. Note the following:

  • Specify only one permission in an access rule object.
  • Access rule order corresponds to rule order in the AccessRules collection.
  • An access rule with a higher index has a higher priority and can override a preceding rule.
  • Security permissions are prioritized over access rules if they affect the same file or folder.

The following example restricts editing operations for the entire file system:

aspx
<dx:ASPxFileManager ID="FileManager" runat="server">
    <SettingsPermissions>
        <AccessRules>
            <dx:FileManagerFolderAccessRule Edit="Deny" />
            <dx:FileManagerFileAccessRule PathPattern="*" Download="Deny" />
        </AccessRules>
    </SettingsPermissions>
</dx:ASPxFileManager>

Refer to the following topics for additional information/guidance: Access Rules and Permissions.

See Also

Unrestricted File Upload