├── pyimp.JPG
├── screen.JPG
├── sleep-09202002582419-x86.dll
├── sleep-09202002582419-amd64.dll
├── README.md
├── http-telerik-vuln.nse
└── telerik_rce_scan.py
/pyimp.JPG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ThanHuuTuan/Telerik_CVE-2019-18935/HEAD/pyimp.JPG
--------------------------------------------------------------------------------
/screen.JPG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ThanHuuTuan/Telerik_CVE-2019-18935/HEAD/screen.JPG
--------------------------------------------------------------------------------
/sleep-09202002582419-x86.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ThanHuuTuan/Telerik_CVE-2019-18935/HEAD/sleep-09202002582419-x86.dll
--------------------------------------------------------------------------------
/sleep-09202002582419-amd64.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ThanHuuTuan/Telerik_CVE-2019-18935/HEAD/sleep-09202002582419-amd64.dll
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # TelerikUI Python Scanner
2 | (telerik_rce_scan.py)
3 |
4 |
5 | # Examples
6 | Assess an IP for CVE-2019-18935
7 | $ python3 telerik_rce_scan.py -t 192.168.44.21
8 |
9 | Assess a hostname for CVE-2019-18935
10 | $ python3 telerik_rce_scan.py -t vulnerable.telerik.net
11 |
12 | Assess a CIDR network range for CVE-2019-18935
13 | $ python3 telerik_rce_scan.py -r 23.253.4.0/24
14 |
15 | Assess a list of targerts
16 | $ python3 telerik_rce_scan.py -iL hosts.txt
17 |
18 | ------------------------------------------------------------------------------------------------------
19 |
20 | # TelerikUI NSE Scanner
21 | (http-telerik-vuln.nse)
22 |
23 | # Installation
24 | Download to your nmap scripts directory (/usr/share/nmap/scripts/)
25 |
26 | # Update the nmap scripts database
27 | $ nmap --script-updatedb
28 |
29 | # Sample execution:
30 | nmap -sT -p443 --script=http-telerik-vuln 23.253.4.115
31 |
32 | # Screen:
33 |
34 |
35 | ## Thanks
36 |
37 | [@mwulftange](https://twitter.com/mwulftange) initially [discovered](https://codewhitesec.blogspot.com/2019/02/telerik-revisited.html) this vulnerability. [@bao7uo](https://github.com/bao7uo) wrote all of the logic for [breaking RadAsyncUpload encryption](https://github.com/bao7uo/RAU_crypto), which enabled manipulating the file upload configuration object in `rauPostData` and subsequently exploiting insecure deserialization of that object. And thanks to Noperator (@BishopFox) from whom I _copped_ this language and the Legal Disclaimer below.
38 |
39 | ## Legal Disclaimer
40 |
41 | Usage of this tool for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state, and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program.
42 |
--------------------------------------------------------------------------------
/http-telerik-vuln.nse:
--------------------------------------------------------------------------------
1 | local http = require "http"
2 | local stdnse = require "stdnse"
3 | local string = require "string"
4 | local table = require "table"
5 | local vulns = require "vulns"
6 | local shortport = require "shortport"
7 |
8 |
9 | local catch = function()
10 | client_ident:close()
11 | client_service:close()
12 | end
13 |
14 | description = [[
15 | The insecure deserialization of JSON objects in Telerik UI for ASP.NET
16 | results in arbitrary remote code execution. An attacker can break the
17 | RadAsyncUpload encryption (or have prior knowledge of your custom
18 | encryption keys) and stage a malicious request.
19 |
20 | Affects: v2011.1.315 - 2017.2.621 without keys
21 | v2011.1.315 - 2020.1.114 with encryption keys
22 |
23 | Big Ups: Markus Wulftange (@mwulftange) && Paul Taylor (@bao7uo)
24 | Ref: https://github.com/noperator/CVE-2019-18935
25 | See: https://github.com/bao7uo/RAU_crypto
26 | See: https://www.telerik.com/support/kb/aspnet-ajax/details/allows-javascriptserializer-deserialization
27 | ]]
28 |
29 |
30 | -- @changelog
31 | -- 2020-05-15 - hacked together by Brent 'becrevex' Chambers - `support free info`
32 | -- 2020-05-18 - added root path DLL check and version output on fail
33 |
34 | author = "Brent 'becrevex' Chambers"
35 | license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
36 | categories = {"safe", "discovery"}
37 |
38 | portrule = shortport.port_or_service (443, "https", "tcp")
39 |
40 | local result = {}
41 | local path = {"/Telerik.Web.UI.WebResource.axd?type=rau"}
42 | local pattern = "20[0-9]{2}(%.[0-9]*)+"
43 |
44 | action = function(host, port)
45 |
46 | local vuln_table = {
47 | title = "CVE-2019-18935 - Telerik UI Javascript Deserialization RCE",
48 | state = vulns.STATE.NOT_VULN,
49 | risk_factor = "High",
50 | references = {
51 | 'https://nvd.nist.gov/vuln/detail/CVE-2019-18935',
52 | },
53 | IDS = {
54 | CVE = ' CVE-2019-18935',
55 | CWE = ' CWE-913'
56 | },
57 | scores = {
58 | CVSS2 = '8.5'
59 | },
60 | description = [[
61 | Telerik UI for ASP.NET AJAX through 2019.3.1023 contains a
62 | .NET deserialization RCE vulnerability in the RadAsyncUpload function. ]]
63 |
64 | -- (As of 2020.1.114, a default setting prevents the exploit.
65 | -- In 2019.3.1023, but not earlier versions, a non-default
66 | -- setting can prevent exploitation.)]]
67 |
68 | -- This is exploitable
69 | -- when the encryption keys are known due to the presence of CVE-2017-11317 or
70 | -- CVE-2017-11357. Exploitation can result in remote code execution.
71 | }
72 |
73 | local report = vulns.Report:new(SCRIPT_NAME, host, port)
74 |
75 |
76 | stdnse.debug1("Connecting to %s:%s", host.targetname or host.ip, port.number)
77 | local data = http.get(host, port, "/aspnet-ajax/Telerik.Web.UI.WebResource.axd?type=rau")
78 | local data2 = http.get(host, port, "/Telerik.Web.UI.WebResource.axd?type=rau")
79 | local site1 = http.get(host, port, "/")
80 |
81 | if data and data.status then
82 | if string.match(data.body, "RadAsyncUpload handler is registered succesfully") then
83 | stdnse.debug1("Telerik file uploader is available.")
84 | table.insert(result, "\n[!] Possibly vulnerable to CVE-2019-18935 (Telerik UI RCE)")
85 | local response = http.get(host, port, "/aspnet-ajax")
86 | if response.body:match("201[0-9]%.[0-2]%.%d%d%d%.%d%d") then
87 | local version = response['body']:match("201[0-9]%.[0-2]%.%d%d%d%.%d%d")
88 | stdnse.print_debug(1, "%s:..VULNERABLE VERSION FOUND: " .. version, SCRIPT_NAME, response.body)
89 | vuln_table.state = vulns.STATE.VULN
90 | elseif response.body:match("2020%.[0-1]%.%d%d%d%.%d%d") then
91 | local version = response['body']:match("2020%.[0-2]%.%d%d%d%.%d%d")
92 | stdnse.print_debug(1, "%s:..VULERABLE VERSION FOUND (requires encryption key): " .. version, SCRIPT_NAME, response.body)
93 | vuln_table.state = vulns.STATE.VULN
94 | else
95 | local version = response['body']:match("20%d%d%.%d.%d%d%d%.%d%d")
96 | stdnse.debug1("Version discovery: "..version)
97 | stdnse.debug1("Not vulnerable CVE-2019-18935 (TelerikUI RCE)")
98 | end
99 | else
100 |
101 | table.insert(result, "\n[!] Not vulnerable CVE-2019-18935 (TelerikUI RCE)")
102 | end
103 | elseif data2 and data2.status then
104 | if string.match(data2.body, "RadAsyncUpload handler is registered succesfully") then
105 | stdnse.debug1("Telerik file uploader is available.")
106 | table.insert(result, "\n[!] Possibly vulnerable to CVE-2019-18935 (Telerik UI RCE)")
107 | local response = http.get(host, port, "/")
108 | if response.body:match("201[0-9]%.[0-2]%.%d%d%d%.%d%d") then
109 | local version = response['body']:match("201[0-9]%.[0-2]%.%d%d%d%.%d%d")
110 | stdnse.print_debug(1, "%s:..VULNERABLE VERSION FOUND: " .. version, SCRIPT_NAME, response.body)
111 | vuln_table.state = vulns.STATE.VULN
112 | elseif response.body:match("2020%.[0-1]%.%d%d%d%.%d%d") then
113 | local version = response['body']:match("2020%.[0-2]%.%d%d%d%.%d%d")
114 | stdnse.print_debug(1, "%s:..VULERABLE VERSION FOUND (requires encryption key): " .. version, SCRIPT_NAME, response.body)
115 | vuln_table.state = vulns.STATE.VULN
116 | else
117 | local version = response['body']:match("20%d%d%.%d.%d%d%d%.%d%d")
118 | stdnse.debug1("Version discovery: "..version)
119 | stdnse.debug1("Not vulnerable CVE-2019-18935 (TelerikUI RCE)")
120 | end
121 | else
122 |
123 | table.insert(result, "\n[!] Not vulnerable CVE-2019-18935 (TelerikUI RCE)")
124 | end
125 | end
126 | return report:make_output(vuln_table)
127 | end
128 |
--------------------------------------------------------------------------------
/telerik_rce_scan.py:
--------------------------------------------------------------------------------
1 | # Programmer: Brent 'becrevex' Chambers
2 | # Date: May 24, 2020
3 | # Filename: telerik_rce_scan.py
4 | # Description: TelerikUI CVE-2019-18935 vulnerability scanner
5 |
6 | import re
7 | import requests
8 | import argparse
9 | import random
10 | import time
11 | import ipaddress
12 | import traceback
13 | import datetime
14 | requests.packages.urllib3.disable_warnings() # disable lame SSL warnings
15 |
16 | help_example = "EXAMPLE: telerik_rce_check -t 104.28.18.139"
17 | parser = argparse.ArgumentParser(description='Telerik RAU RCE Detection'+'\n\n'+ help_example, formatter_class=argparse.RawTextHelpFormatter)
18 | parser.add_argument('-t', '--target')
19 | parser.add_argument('-r', '--range')
20 | parser.add_argument('-iL', '--inputfile', help='Specify a filename for bulk target scanning.')
21 | parser.add_argument('-search', action='store_true', help='Searches IPv4 space for vulnerable hosts. (2 Second delay)')
22 | args = parser.parse_args()
23 |
24 | vuln_checks = ['/Telerik.Web.UI.WebResource.axd?type=rau',
25 | '/aspnet-ajax/Telerik.Web.UI.WebResource.axd?type=rau']
26 |
27 | def print_vuln_table():
28 | print(" [!] VULNERABLE")
29 | print("""
30 | Risk: HIGH CVE: CVE-2019-18935 CWE: CWE-913
31 | ---------------------------------------------------------------------
32 | Telerik UI for ASP.NET AJAX through 2019.3.1023 contains a
33 | .NET deserialization RCE vulnerability in the RadAsyncUpload function.
34 |
35 | -- As of 2020.1.114, a default setting prevents the exploit.
36 | -- In 2019.3.1023, but not earlier versions, a non-default
37 | -- setting can prevent exploitation.
38 |
39 | -- This is exploitable when the encryption keys are known due
40 | -- to the presence of CVE-2017-11317 or CVE-2017-11357.
41 | -- Exploitation can result in remote code execution.
42 | """)
43 |
44 |
45 | def execution_header():
46 | print("TelerikUI RCE Scan ( github.com/becrevex/Telerik_CVE-2019-18935 ) ")
47 | print(help_example)
48 | stamp = datetime.datetime.now()
49 | print("Starting CVE-2019-18935 (Telerik RCE) scan at " + str(stamp))
50 | print()
51 |
52 |
53 | def is_valid_ip(ip):
54 | """Checks if IP is valid"""
55 | test = re.match(r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$",ip)
56 | if test:
57 | return True
58 | else:
59 | return False
60 |
61 |
62 | def is_valid_hostname(hostname):
63 | """Checks if hostname is valid for scanning """
64 | if hostname[-1] == ".":
65 | # strip exactly one dot from the right, if present
66 | hostname = hostname[:-1]
67 | if len(hostname) > 253:
68 | return False
69 | labels = hostname.split(".")
70 | # the TLD must be not all-numeric
71 | if re.match(r"[0-9]+$", labels[-1]):
72 | return False
73 | allowed = re.compile(r"(?!-)[a-z0-9-]{1,63}(?= 2020 and int(sub) >= 3 and int(sub2) >= 1023):
102 | print("Patched. NOT VULNERABLE")
103 | return False
104 | elif (int(year) <= 2020) and (int(sub) <= 2):
105 | return True
106 | else:
107 | return False
108 |
109 | def check_for_patch(version):
110 | print(version)
111 | year = version.split(".")[0]
112 | sub = version.split(".")[1]
113 | sub2 = version.split(".")[2]
114 | if (int(year) >= 2020 and int(sub) >= 3 and int(sub2) >= 1023):
115 | print(version.split("."))
116 | return True # found patched version
117 | else:
118 | return False
119 |
120 | def read_from_file(filepath):
121 | with open(filepath) as fd:
122 | targets = fd.read().splitlines()
123 | return targets
124 |
125 | def check_source_for_ver(target):
126 | print("Checking target for vulnerable versions...")
127 | s = '20[0-9]{2}(?:\.[0-9]*)+'
128 | source = requests.get("https://"+target, verify=False)
129 | result = re.search(s, source.text)
130 | results = re.findall(s, source.text)
131 | #print(results)
132 | status = False
133 | #print(len(results))
134 | print("Identified version matches:")
135 | for i in list(dict.fromkeys(results)):
136 | if (len(i.split(".")) >= 3):
137 | if check_version_vuln(i):
138 | status = True
139 | #elif check_for_patch(i):
140 | # status = False # if it comes back as patched, return to call and label the version not vulnerable
141 | return status
142 |
143 | def check_vuln(target):
144 | status = ""
145 | string_text = "RadAsyncUpload handler is registered succesfully"
146 | print("Checking: " + target)
147 | for uri in vuln_checks:
148 | try:
149 | r = requests.get('https://'+ target + uri, verify=False)
150 | status = r.status_code
151 | if status == 200:
152 | # if r.body contains "RadAsyncUpload handler is registered succesfully"
153 | if string_text in r.text:
154 | print("[!] RAU Module Found [ " + target + uri + " ]!")
155 | if (check_source_for_ver(target)):
156 | print_vuln_table()
157 | return
158 | return
159 | else:
160 | pass
161 | #print("Telerik RAU Module not found on " + target + ":Status " + str(status))
162 | except Exception as ex:
163 | traceback.print_exc()
164 |
165 |
166 | def check_vuln_bulk(target):
167 | status = ""
168 | string_text = "RadAsyncUpload handler is registered succesfully"
169 | print("Checking: " + target)
170 | for uri in vuln_checks:
171 | try:
172 | r = requests.get('https://'+ target + uri, timeout=0.5, verify=False)
173 | status = r.status_code
174 | if status == 200:
175 | # if r.body contains "RadAsyncUpload handler is registered succesfully"
176 | if string_text in r.text:
177 | print("[!] RAU Module Found [ " + target + uri + " ]!")
178 | if (check_source_for_ver(target)):
179 | print_vuln_table()
180 | return
181 | return
182 | else:
183 | print("Telerik RAU Module not found on " + target + ". Status (" + str(status) + ")")
184 | except Exception as ex:
185 | pass
186 |
187 |
188 | if __name__=='__main__':
189 | if args.inputfile:
190 | execution_header()
191 | targets = read_from_file(args.inputfile)
192 | for host in targets:
193 | check_vuln_bulk(host)
194 |
195 | elif args.search:
196 | execution_header()
197 | search()
198 |
199 | elif args.target:
200 | execution_header()
201 | if is_valid_ip(args.target):
202 | check_vuln(args.target)
203 |
204 | elif is_valid_hostname(args.target):
205 | check_vuln(args.target)
206 |
207 | elif args.range:
208 | execution_header()
209 | range_scan(args.range)
210 |
211 | else:
212 | parser.print_help()
213 | else:
214 | parser.print_help()
215 |
216 |
217 |
218 |
--------------------------------------------------------------------------------